Introdução ao JSF Managed Bean

Neste artigo mostraremos o funcionamento do JSF Managed Bean e como utilizá-la em nossa View. O ManagedBean funciona como uma classe que delega funções para cada View.

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.

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 = "#") 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]; } } }
Listagem 1. O ManagedBean para CRUD de Funcionários

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>
Listagem 2. Usando o ManagedBean na nossa View

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

Saiba mais sobre Java ;)

Artigos relacionados