domingo, 29 de setembro de 2013

A camada de visão - o managed bean do JSF

Este post faz parte de uma série sobre Spring, JPA e JSF. Caso algum assunto abordado aqui não esteja claro, consulte este link: Spring + JPA.

Finalizando essa série de posts sobre Spring, JPA e JSF, vou mostrar finalmente como juntar todas as camadas e executar uma pequena aplicação para testar tudo o que foi feito até aqui.

Relembrando que a integração do JSF ocorre sem problemas desde que sejam feitas as alterações no obsoleto arquivo faces-config.xml, como já foi dito aqui: A camada de visão - Business Delegate.

Antes de executar o exemplo, é interessante deixar o arquivo persistence.xml configurado para apagar e criar as entidades, pois assim o teste pode ser refeito quantas vezes forem necessárias.

Vamos usar uma classe Pessoa,  como foi mostrado aqui: Criando entidades de bancos de dados e uma classe Autor conforme o código a seguir:

package entidades;

import java.io.Serializable;
import javax.persistence.Entity;

@Entity
public class Autor extends Pessoa implements Serializable {

    public Autor() {
    }
}

É apenas uma herança direta, já que a classe Pessoa é abstrata e não pode ser instanciada. Em seguida criamos um pacote chamado controle e dentro dele uma classe Controlador.java conforme o código abaixo:

package controle;

import delegate.FacadeBD;
import entidades.Entidade;
import entidades.Autor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

@ManagedBean(name = "controlador")
@ViewScoped
public class Controlador implements Serializable {

    @ManagedProperty(value = "#{facadeBD}")
    private FacadeBD facadeBD;

    public Controlador() {
    }

    public String listaGravada() {
        String retorno = "";
        List<Autor> la = facadeBD.listar(Autor.class);
        retorno += "\n\nLista gravada:\n\n";
        if (la != null) {
            for (Autor autor : la) {
                retorno += "("+autor.getId()+") "+autor.getNome() + "\n";
            }
        }
        return retorno;
    }

    public String getResultado() {
        String retorno = "";
        Autor autor1 = new Autor();
        autor1.setNome("Stephen King");
        Autor autor2 = new Autor();
        autor2.setNome("Dan Brown");
        List<Entidade> listaAutores = new ArrayList<Entidade>();
        listaAutores.add(autor1);
        listaAutores.add(autor2);
        retorno += "\nInserindo dois autores\n";
        facadeBD.salvarLista(listaAutores);
        retorno += listaGravada();
        autor1.setFlagRemover(Boolean.TRUE);
        facadeBD.salvar(autor1);
        retorno += "\nExcluindo ("+autor1.getId()+") "+autor1.getNome()+"\n";
        retorno += listaGravada();
        Autor autor3 = new Autor();
        autor3.setNome("ray bradbury");
        listaAutores.add(autor3);
        retorno += "\nInserindo novo autor "+autor3.getNome()+"\n";
        facadeBD.salvarLista(listaAutores);
        retorno += listaGravada();
        retorno += "\nAlterando "+autor3.getNome()+"\n";
        autor3.setNome("Ray Bradbury");
        facadeBD.salvarLista(listaAutores);
        retorno += listaGravada();
        return retorno;
    }

    public FacadeBD getFacadeBD() {
        return facadeBD;
    }

    public void setFacadeBD(FacadeBD facadeBD) {
        this.facadeBD = facadeBD;
    }
}

Esta classe possui um atributo facadeBD, injetado pelo JSF, ou seja, é uma instância da classe FacadeBD. Podemos verificar na linha 13 que essa classe é colocada no contexto do JSF com o nome "controlador" (em minúsculas), e é como será referenciada logo a seguir, no página que será construída. Temos ainda um método listaGravada para recuperar o conteúdo do banco de dados correspondente à tabela pessoas. Podemos observar, na linha 25, o uso do método listar.

Finalmente, um método acessor getResultado na linha 35. Apesar de não termos um atributo resultado, verificamos aqui que o JSF só precisa do método acessor, e não do atributo, como já era esperado. Esse método faz várias chamadas aos métodos DAO por meio de facadeBD. É importante ressaltar que não há preocupação com conexões, transações, etc.. Vemos também que para excluir um registro do banco de dados, mudamos o atributo flagRemover para true e salvamos. No final do processamento, temos uma String com o histórico das operações, que vai ser acessada na página a seguir:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Livraria</title>
    </h:head>
    <h:body>
        <h:inputTextarea cols="100" rows="50" value="#{controlador.resultado}" />
    </h:body>
</html>

Na linha 9, temos a referência ao "atributo" resultado, acessado por meio do método getResultado do managed bean controlador. Ao executar essa aplicação, há um redirecionamento para a página de autenticação, e em seguida, ocorre o processamento nas camadas e o histórico de operações é exeibido no inputTextArea:

Inserindo dois autores


Lista gravada:

(1) Stephen King
(2) Dan Brown

Excluindo (1) Stephen King


Lista gravada:

(2) Dan Brown

Inserindo novo autor ray bradbury


Lista gravada:

(2) Dan Brown
(3) ray bradbury

Alterando ray bradbury


Lista gravada:

(2) Dan Brown
(3) Ray Bradbury

Outra observação importante é que também não há uma preocupação com as classes que vão ser gravadas. Pode ser uma lista com apenas um tipo de classe (autores) ou com mais de um tipo (autores mesclados com publicações, por exemplo). A única restrição é que as classes devem ser subclasses de Entidade.

Ainda, se observarmos as chamadas que foram feitas ao método salvarLista, veremos que em nenhum momento removemos da lista listaAutores o autor que foi excluído do banco. A classe GenericDAO já prevê tudo isso, justamente para que a camada de visão fique ainda mais desacoplada da camada de serviços, deixando para o desenvolvedor apenas a preocupação com o fluxo da aplicação e a disposição dos dados nas páginas.

E assim termina a série de posts sobre uso de JPA, Spring, JSF, MVC. Temos um projeto básico completo que será usado na próxima série de posts, ode serão abordados os relacionamentos entre entidades e como utilizar o Primefaces para construção de uma aplicação completa.

Nenhum comentário:

Postar um comentário