Pesquisar este blog

segunda-feira, 14 de setembro de 2015

Spring Data com anotações e JSF

No último post foi mostrado um padrão de MVC push, ou seja, a interface enviava os dados e realizava as chamadas aos controllers. Aqui será mostrado uma maneira de desenvolver uma aplicaçao Web com o MVC pull, ou seja, a interface pucha os dados da camada de serviço.

Java Server Faces

JSF é uma especificação do Java, baseada em componentes, para se construir a interface de um aplicativo Web. Na primeira versão do JSF as páginas eram construidas utilizando a tecnologia JSP, depois da versão 2.0 do JSF elas passaram a ser construidas sobre uma tecnologia chamada Facelets.
Facelet é uma tecnologia da apache de modelos das interfaces web.

Configuração de um aplicativo Web com JSF e Spring Data

Aqui serão apresentados os detalhes da configuração do web.xml de uma aplicação JSF com Spring Data
A primeira coisa que devemos nos preoupar, ao configurar um aplicativo web, é a configuração do seu servlet, para o JSF utilizamos o FacesServlet, que será responsável por mapear todas as requisições das páginas a camada de serviço, a sua configuração é feita por:
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
A tag servlet-mapping é de extrema importância, pois é nela que declaramos onde estarão localizados os nossos arquivos de interface, o que neste caso serão todos os arquivos .xhtml da pasta raiz:

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
A configuração do spring por anotações é realizada pela classe AnnotationConfigWebApplicationContext, e introduzindo o texto a seguir no seu web.xml irá configurar o spring para ler as anotações do projeto e configurar os Beans a partir delas.
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

Depois de definir que o projeto será configurado por anotações deveremos especificar qual é a classe de configuração dos nossos beans:

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>br.unip.dsd.config.JPAConfig</param-value>
    </context-param>
A última configuração a ser adicionada é a configuração dos listeners. O ContextLoaderListener é responsável por ler e parsear todas as configurações referentes ao contexto da aplicação, como a instanciação dos beans. Já o ConfigureListener irá ler e parsear todas as configurações do JSF, e a sua configuração no web.xml é assim:
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
    </listener>
Com isso o nosso aplicativo está pronto para ser executado, agora serão mostradas as configurações do JSF.

Configuração do JSF

Todas as configurações dos aplicativos Web ficam em uma pasta WEB-INF, o arquivo de configuração do JSF chama-se faces-config.xml. Nele serão definidas as configurações dos beans do JSF e da classe responsável por enviar mensagens ao nosso aplicativo.
No nosso post de MVC, as classes que recebiam as chamadas da interface eram chamadas de Controllers, aqui no JSF elas são chamadas de Managed-Bean. Um managed-bean é um Bean do Java que pode ser acessado através dos componentes do JSF, e sua configuração define o nome, que será utilizado na interface, e a sua respectiva classe:
    <managed-bean>
        <managed-bean-name>usuarioBean</managed-bean-name>
        <managed-bean-class>br.unip.dsd.bean.UsuarioBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
Também podemos configurar as mensagens da nossa interface, por mensagens entenda qualquer texto que será utilizado em nossa interface. Nesta configuração podemos usar a internacionalizaçao do Java. Mas o que é isto?
Nesta configuração pode-se definir quais são as linguas suportadas pelo nosso aplicativo, e cada lingua suportada, terá um arquivo de mensagens específico. O browser detecta automaticamente a lingua do cliente, e exibe as mensagens na sua lingua específica, caso a lingua do usuário não seja suportada, ele mostrará a lingua padrão.
Nesta configuração defini-se como lingua padrão o br (de portugues do Brasil) e en (de English, ou Inglês) como segunda lingua suportada.

  <application>
    <message-bundle>br.unip.dsd.mensagens.MensagensAplicacao</message-bundle>
    <locale-config>
       <default-locale>br</default-locale>
       <supported-locale>en</supported-locale>
    </locale-config>
    <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
        </el-resolver>
   
  </application>
A tag message-bundle, define a localização dos arquivos de mensagem do aplicativo, o que será um arquivo localizado no pacote  br.unip.dsd.mensagens, chamado MensagensAplicacao.properties (para o ingles) e MensagensAplicacao_br.properties (para o portugues). Aqui é possível adicionar quantas linguas você quiser, para isso basta adicionar um supported-locale, e um arquivo de propriedades.
Um arquivo de propriedades é um arquivo de chave, valor, ou seja, ele possui uma coluna com as chaves, nomes usados no nosso aplicativo e que deverão estar definidos em todos os arquivos utilizados aqui, e um valor, que é o texto mostrado para o usuário:
erroEmailExiste=Email já cadastrado
erroConfirmacaoEmail=Por favor verifique se os emails digitados são idênticos
Acima temos um exemplo de duas mensagens de erro, sendo que as chaves, que serão utilizadas pelo aplicativo para recuperar as mensagens, estão grifadas, e os valores, que serão mostrados ao usuário estão definidos logo a frente.
No aplicativo, para acessar estas mensagens vamos precisar de uma Factory, que é definida assim:
  private ResourceBundle bundle;
  private Locale locale;
 
  public MessagemFactory() {
    locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
      bundle = ResourceBundle.getBundle("br.unip.dsd.mensagens.MensagensAplicacao", locale);
  }
Nestes caso o bundle é onde foi definido as nossas mensagens, e locale é onde está localizado o nosso cliente.
Para recuperar uma mensagem basta usar um bundle.getString(valor) e pronto, ele irá cuidar de mostrar a mensagem correta ao nosso cliente.

Managed Bean

A definição de um bean é feita através da anotação @ManagedBean, conforme mostrado abaixo:
@Component
@ManagedBean
public class UsuarioBean
Todos os valores que forem acessados pela sua interface, devem ser definidos como propriedades do seu Bean, e eles devem ter seus métodos de get e set, para que o JSF consiga acessar e alterar os seus valores.
Então você pode estar pensando que aqui você vai por os seus modelos? Bem não é exatamente isto o que deve ser feito. Nos beans colocamos regras de negócios, por exemplo se o seu bean for um bean de gravação de usuário, aqui podemos colocar as regras de validação dos valores digitados, assim como uma instância do repositório dos usuuários.
Para colocar qualquer instância de qualquer bean definido no contexto do seu aplicativo, basta usar a anotação @Autowired, que toda aquela configuração colocada no web.xml irá cuidar de encontrar o bean e instanciá-lo:
@Autowired
 private RepositorioUsuario repositorioUsuario;
Irá prover uma instância do repositório do usuário, definido pela interface RepositorioUsuario.
Com isso conseguimos gravar os dados recebidos da tela no banco de dados.

Interface JSF

Bom, já foi mostrada toda a integração e a parte de backend, mas e os componentes do JSF, como utilizá-los?
A definição dos componentes JSF podem ser feitos em um arquivo HTML, aqui neste projeto estamos usando arquivos .xhtml. Precisamos definir as configurações do JSF nos metadados do nosso html e isso é feito usando:
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html">
Repare que definimos xmlns:h e isso determina que os componentes do jsf serão definidos como h:componente.
Para definirmos um campo que acessa o valor de nome do nosso bean do usuário, basta fazermos:
<h:inputText id="nome" value="#{usuarioBean.usuario.nome}"
            required="true" />
Para que isto funcione, o nosso bean de usuário, deverá ter uma propriedade usuario, que por sua vez terá uma propriedade nome. Com isso acessamos a propriedade nome, do usuario do usuarioBean e o valor digitado no nosso campo texto será automaticamente setado nele.
Aqui devemos considerar que para que isso funcione, o usuário não pode ser nulo, do contrário teremos uma NullPointerException sendo disparada.
Todos os arquivos deste exemplo estão disponíveis no meu repositório e a apresentação.

Nenhum comentário:

Postar um comentário