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 = "#{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];
		}
	}

}
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 ;)