O JSF (Java Server Faces) trabalha diretamente com algo chamado de ManagedBean para fazer o “link” entre as regras de negócio da sua aplicação (geralmente BO, DAO e etc) com a View (HTML, XHTML e assim por diante).
Neste artigo iremos mostrar o funcionamento desta classe e como utilizá-la em nossa View. Você logo perceberá que o ManagedBean funciona como uma classe que “delega” funções específicas para cada View na sua aplicação.
ManagedBean na prática
Nada melhor do que códigos e exemplos para demonstrar o funcionamento desta classe. Então como exemplo, mostraremos um ManagedBean criado para um módulo do sistema que cadastra funcionários (um CRUD simples). Para facilitar o entendimento, colocamos comentários em cada linha importante do código.
Relacionado: Curso completo de Java
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import org.apache.log4j.Logger;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
/*
* Anotação que reflete o nome que usaremos para chamar essa classe
* através da nossa View.
*/
@ManagedBean(name = "funcionarioMB")
/*
* Este é o escopo da classe, que diz respeito até quando nosso objeto
* continuará persistente em memória. Como utilizamos o ViewScoped ele
* permanecerá até o fechamento da View, ou da página, se assim preferir.
* */
@ViewScoped
public class FuncionarioMBImpl extends BasicMBImpl {
/*
* Utilizamos o logger para realizar log's da aplicação no servidor
* */
private static Logger logger = Logger.getLogger(FuncionarioMBImpl.class);
/*
* Aqui entra uma ponto importante, pois o ManagedProperty 'injeta' um objeto
* da nossa classe ManagedBean, a questão aqui é que se você
* tiver usando Spring Framework
* você poderia usar o próprio 'Autowired', mas por questão
* de estarmos trabalhando dentro da classe
* ManagedBean, vamos manter a padronização e utilizar o ManagedProperty.
* */
@ManagedProperty(value = "#{funcionarioBO}")
private FuncionarioBOImpl funcionarioBO;
/*
* Este é o objeto que vamos usar para manipular inserções,
* edições e deleções na nossa base.
* */
private Funcionario funcionario;
/*
* Mostra uma lista de funcionários carregadas do banco
* */
private List<Funcionario> funcionarios;
/*
* Lista de estados civis que um funcionário pode ter
* */
private List<EstadoCivil> estadosCivis;
/*
* Esta é a mesma lista de estados civis da lista acima, porém
* retornando um SelectItem que será usado no filterOptions da tag do
* primefaces
* */
private SelectItem estadosCivisAsSelectItem[];
private List<SituacaoPessoa> situacoesPessoa;
private SelectItem situacoesPessoaAsItem[];
private List<Sexo> sexos;
private List<Uf> ufs;
/*
* É importante colocar suas inicializações no post construct e não no
* construtor da classe, isso porque se você estiver realizando injeção de
* dependência (no Spring, por exemplo) todas as dependências podem não estar
* carregadas na construção da sua classe, então no post construct você garante
* que tudo já foi carregado e agora você pode usá-los.
* */
@PostConstruct
public void init() {
logger.debug("Inicializando componentes no PostConstruct");
estadosCivis = (List<EstadoCivil>) funcionarioBO
.findByNamedQuery("EstadoCivil.findAll");
situacoesPessoa = (List<SituacaoPessoa>) funcionarioBO
.findByNamedQuery("SituacaoPessoa.findAll");
sexos = (List<Sexo>)
funcionarioBO.findByNamedQuery("Sexo.findAll");
ufs = (List<Uf>) funcionarioBO.findByNamedQuery("Uf.findAll");
}
/*
* Ao clicar no botão novo na nossa View, acionamos
* essa Action criando um novo objeto em memória.
* */
public void novo(ActionEvent event) {
funcionario = new Funcionario();
}
/*
* Salvamos o funcionario criado em memória, mas antes verificamos se ele
* já tem um ID ou não, pois se tiver um ID sabemos que não é uma inserção e sim
* uma atualização de registro.
* */
public void salvar(ActionEvent event) {
try {
if (funcionario.getId() == null) {
funcionario = (Funcionario) funcionarioBO.save(funcionario,
uploadedFile);
addInfoMessage("Funcionário salvo com sucesso");
} else {
funcionarioBO.update(funcionario, uploadedFile);
addInfoMessage("Funcionário salvo com sucesso");
}
funcionarios = (List<Funcionario>) funcionarioBO
.findByNamedQuery("Funcionario.findAllCompleto");
} catch (BOException e) {
FacesContext.getCurrentInstance().validationFailed();
addErrorMessage(e.getMessage());
}
}
/*
* Deletamos o funcionario
* */
public void deletar() {
try {
funcionarioBO.delete(funcionario);
addInfoMessage("Funcionário deletado com sucesso");
funcionarios = (List<Funcionario>) funcionarioBO
.findByNamedQuery("Funcionario.findAllCompleto");
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
}
/*
* ***********************************************************
* *******************GETTERS e SETTERS***********************
* ***********************************************************
*
* Fique atento aos GETTERS e SETTERS definidos no nosso ManagedBean.
* perceba que não precisamo definir um SET para a lista de funcionarios,
* isso porque apenas retornaremos uma lista, não adicionaremos nada de novo
* nela da View para o ManagedBean, nesse caso o SET é dispensável,
* assim como no caso de EstadosCivis.
* */
public List<Funcionario> getFuncionarios() {
try {
if (funcionarios == null)
funcionarios = (List<Funcionario>) funcionarioBO
.findByNamedQuery("Funcionario.findAllCompleto");
return funcionarios;
} catch (BOException e) {
addErrorMessage(e.getMessage());
}
return null;
}
/*
* Pegamos aqui nossa lista de situações possíveis e transformamos em um
* array de SelectItem, para utilizar no filterOptions do JSF.
* */
public SelectItem[] getSituacoesPessoaAsItem() {
if (situacoesPessoa.size() > 0) {
situacoesPessoaAsItem = new SelectItem[situacoesPessoa.size() + 1];
situacoesPessoaAsItem[0] = new SelectItem("", "Todos");
for (int i = 0; i < situacoesPessoa.size(); i++)
situacoesPessoaAsItem[i + 1] = new SelectItem(
((SituacaoPessoa) situacoesPessoa.get(i))
.getDescricao(),
((SituacaoPessoa) situacoesPessoa.get(i))
.getDescricao());
return situacoesPessoaAsItem;
} else {
return new SelectItem[0];
}
}
public Funcionario getFuncionario() {
return funcionario;
}
public void setFuncionario(Funcionario funcionario) {
this.funcionario = funcionario;
}
public List<EstadoCivil> getEstadosCivis() {
return estadosCivis;
}
public List<SituacaoPessoa> getSituacoesPessoa() {
return situacoesPessoa;
}
public List<Sexo> getSexos() {
return sexos;
}
public List<Uf> getUfs() {
return ufs;
}
public FuncionarioBOImpl getFuncionarioBO() {
return funcionarioBO;
}
public void setFuncionarioBO(FuncionarioBOImpl funcionarioBO) {
this.funcionarioBO = funcionarioBO;
}
public SelectItem[] getEstadosCivisAsSelectItem() {
if (estadosCivis.size() > 0) {
estadosCivisAsSelectItem = new SelectItem[estadosCivis.size() + 1];
estadosCivisAsSelectItem[0] = new SelectItem("", "Todos");
for (int i = 0; i < estadosCivis.size(); i++)
estadosCivisAsSelectItem[i + 1] = new SelectItem(
((EstadoCivil) estadosCivis.get(i)).getDescricao(),
((EstadoCivil) estadosCivis.get(i)).getDescricao());
return estadosCivisAsSelectItem;
} else {
return new SelectItem[0];
}
}
}
Um código um tanto quanto grande mas simples de se entender, o que acontece é que toda carga da View fica aqui, no nosso ManagedBean. O ideal é que na nossa View só utilizemos funções básicas para deixá-la o mais simples possível. Veja na Listagem 2 um exemplo simples de utilização de nosso ManagedBean em uma página XHTML com tag's primefaces.
<p:toolbar>
<p:toolbarGroup align="left">
<p:commandButton icon="ui-icon-plus" value="Novo"
id="commandButtonCadastrar"
oncomplete="varDialogManterFuncionario.show()"
actionListener="#{funcionarioMB.novo}"
update=":formManterFuncionario:dialogManterFuncionario" />
<p:commandButton disabled="#{funcionarioMB.funcionario == null}"
id="commandButtonAlterar" value="Alterar" icon="ui-icon-pencil"
oncomplete="varDialogManterFuncionario.show()"
update=":formManterFuncionario:dialogManterFuncionario" />
<p:commandButton disabled="#{funcionarioMB.funcionario == null}"
id="commandButtonRemover" value="Remover" icon="ui-icon-trash"
onclick="varConfirmRemover.show()" />
<p:confirmDialog id="confirmRemover" message="Deseja Remover ?"
showEffect="fade" hideEffect="fade" header="Remover"
severity="alert" widgetVar="varConfirmRemover">
<p:commandButton value="Sim"
oncomplete="varConfirmRemover.hide()"
actionListener="#{funcionarioMB.deletar}"
update=":formFuncionarios:dataTableFuncionarios" />
<p:commandButton value="Não" onclick="varConfirmRemover.hide()"
type="button" />
</p:confirmDialog>
</p:toolbarGroup>
</p:toolbar>
Perceba na listagem 2 que sempre utilizamos “#{funcionarioMB..” para fazer referência a qualquer variável do nosso ManagedBean. Então como falamos acima, logo ao clicar no botão de “Novo” já criamos um objeto Funcionario em memória, assim trabalhamos diretamente com o objeto para posteriormente salvá-lo ou atualizá-lo no banco.
Esperamos que, principalmente com a Listagem 1, fique claro a utilização do ManagedBean em conjunto com nossa View. Como dissemos logo na introdução, fica bem óbvio que o ManagedBean funciona como uma classe que delega funções, pois a nossa View não sabe quem vai salvar, alterar ou deletar, essa é a função do ManagedBean que passa ao nosso BO (Bussiness Object) a tarefa de salvar, deletar ou alterar algum registro.
Links Úteis
- Java 7: Site com informações sobre o lançamento do Java 7
- JavaFX: Site para fazer download de aplicações JavaFX
- JFXtras: Site do projeto JFXtras