Desenvolvimento - Java

Desenvolvendo Aplicações Web com o Java Server Faces

Neste artigo estarei abordando o desenvolvimento de uma aplicação web usando uma implementação do JSF chamada MyFaces.

por Rogério Pereira Araújo



Introdução:

Como resultado do advento do ASP.NET, a Sun desenvolveu a especificação de uma tecnologia que unisse as camadas de apresentação e controle do modelo MVC em um único framework, chamado Java Server Faces.

Java Server faces nada mais é que a junção do que o Struts tem a oferecer à nível de camada de controle junto com o JSTL ou Taglibs para uso na camada de apresentação.

Seu funcionamento segue princípios semelhantes ao que encontramos no ASP.NET, um exemplo é o managed bean ou backing bean que nada mais é uma estrutura semelhante ao codebehind do ASP.NET

Existem algumas IDE"s que já suportam o desenvolvimento visual de aplicações usando o Java Server Faces, entre elas o Sun Java Studio Creator e o WebSphere Studio Developer, sendo que a segunda oferece maior flexibilidade que a primeira no desenvolvimento de aplicações web usando o JSF.

Propósito:

Neste artigo estarei abordando o desenvolvimento de uma aplicação web usando uma implementação do JSF chamada MyFaces, que é um projeto opensource que visa ser uma implementação completa do JSF com uma licensa que permite a distribuição de suas bibliotecas para uso em uma aplicação web de fins comerciais.

Vamos abordar o desenvolvimento sem o uso das IDE"s citadas anteriormente, lembrando que com o uso dessas ferramentas nenhum dos passos citados serão necessários visto que as mesmas farão todo o trabalho de publicação de sua aplicação web para você.

Instalando o MyFaces:

  • Baixe o arquivo myfaces-1.0.6.tgz

    http://umn.dl.sourceforge.net/sourceforge/myfaces/myfaces-1.0.6.tgz

  • Descompacte para uma pasta de sua escolha usando o Fillzip ou outro compactador qualquer capaz e extrair conteúdo de arquivos .tar.gz ou .tgz

  • Crie uma pasta para sua aplicação web, neste caso vamos chamá-la de Cadastros, dentro dela crie uma pasta chamada WEB-INF.

  • Dentro da pasta WEB-INF crie outras duas pastas, classes e lib.

  • Copie todos os arquivos .jar do conteúdo extraído do arquivo myfaces-1.0.6.tgz para a pasta lib.

  • Coloque todos os arquivos .jar da pasta lib na sua variável de ambiente CLASSPATH, pois elas serão necessárias futuramente para compilar o código do backing bean.

  • A estrutura da pasta de sua aplicação web ficará assim:


Fig. 1 – Estrutura de pastas da aplicação web

Preparando o banco de dados no MySQL:

  • Dentro do utilitário de acesso ao servidor MySQL, digite os seguintes comandos:
    update mysql.users set password = PASSWORD("root") where user = "root";
    
    flush privileges
    
    create database cadastros
    
    use cadastros
    
    create table CLIENTES(
    
    ID_CLIENTE varchar(18) not null primary key,
    
    RAZAO_SOCIAL varchar(40)
    
    );
    

  • Você vai encontrar o driver JDBC do MySQL neste link:

    http://www.linorg.usp.br/mysql/Downloads/Connector-J/mysql-connector-java-3.1.4-beta.zip

  • Descompacte esse arquivo e coloque o arquivo mysql-connector-java-3.1.4-beta-bin.jar no local indicado pela figura 1.

    Configurando sua aplicação web para trabalhar com o JSF:

  • Crie um arquivo chamado web.xml e dentro do arquivo copie e cole o conteúdo a seguir:
    <?xml version="1.0"?>
    
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    
    <web-app>
        <context-param>
            <param-name>javax.faces.CONFIG_FILES</param-name>
            <param-value>
                /WEB-INF/cadastros-config.xml
            </param-value>
            <description>
                Lista de arquivos separados por virgula do arquivos de configuracao do JSF.
                (ex. /WEB-INF/my-config.xml)
                Veja JSF 1.0 PRD2, 10.3.2
            </description>
        </context-param>
    
    
        <context-param>
            <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
            <param-value>server</param-value>
            <description>
               Modo de salvameno de estado:
               "client" ou "server" 
               Veja a secao 2.5.2 da especificação do JSF
            </description>
        </context-param>
    
    
        <context-param>
            <param-name>net.sourceforge.myfaces.ALLOW_JAVASCRIPT</param-name>
            <param-value>true</param-value>
            <description>
                Esse parametro informa ao MyFaces se o codigo javascript e permitido na saida HTML 
                resultante.
                Se o codigo javascript e permitido, ancoras command_link terao codigo javascript que 
                submeterao
                para o formulario respectivo.
                Se o javascript nao for permitido, as informacoes de salvamento de estado e 
                parametros aninhados serao adicionados a url como parametros.
                Padrao: "true"
            </description>
        </context-param>
        
    
        <context-param>
            <param-name>net.sourceforge.myfaces.DETECT_JAVASCRIPT</param-name>
            <param-value>false</param-value>
            <description>
                Esse parametro informa ao MyFaces se o codigo javascript e permitido na saida HTML 
                resultante.
                Se o codigo javascript e permitido, ancoras command_link terao codigo javascript que 
                submeterao para o formulario respectivo.
                Se o javascript nao for permitido, as informacoes de salvamento de estado e parametros 
                aninhados
                serao adicionados a url como parametros.
                Padrao: "true"
                Ajustando este parametro para true voce podera combina-lo com STATE_SAVING_METHOD "server" 
                para melhores resultados.
    
                Este e um recurso experimental. Voce tambem tera que habilitar o detector filter/filter no 
                mapeamento abaixo para fazer a deteccao de JavaScript funcionar.
            </description>
        </context-param>
    
    
        <context-param>
            <param-name>net.sourceforge.myfaces.PRETTY_HTML</param-name>
            <param-value>true</param-value>
            <description>
                Se true, o codigo HTML resultante sera formatado, isso quer dizer "humanamente legivel".
                ex. Sepadores de linha adicionais e espacos em branco serao escritos, o que nao influencia
                o codigo HTML.
                Padrão: "true"
            </description>
        </context-param>
    
    
        <!-- Filtro MultiPartes -->
        <filter>
            <filter-name>multipartFilter</filter-name>
            
    <filter-class>net.sourceforge.myfaces.custom.fileupload.MultipartFilter</filter-class>
            <init-param>
                <param-name>maxFileSize</param-name>
                <param-value>10m</param-value>
                <description>Ajusta o limite de tamanho dos arquivos carregados (upload).
                    Formato: 10 - 10 bytes
                            10k - 10 KB
                            10m - 10 MB
                </description>
            </init-param>
        </filter>
    
    
        <filter-mapping>
           <filter-name>multipartFilter</filter-name>
           <url-pattern>*.jsf</url-pattern>
        </filter-mapping>
    
    
        <!-- Listener, que faz todo o trabalho de inicializacao (configuracao e etc). -->
        <listener>
            <listener-class>net.sourceforge.myfaces.webapp.StartupServletContextListener</listener-class>
        </listener>
    
    
        <!-- Faces Servlet -->
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
    
        <!-- mapeamento por extensao -->
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.jsf</url-pattern>
        </servlet-mapping>
    
    
        <!-- arquivos de indice da pasta virtual-->
        <welcome-file-list>
           <welcome-file>index.jsf</welcome-file>
           <welcome-file>index.jsp</welcome-file>
           <welcome-file>index.html</welcome-file>
        </welcome-file-list>
    </web-app>
    

    Este arquivo deverá estar dentro da pasta WEB-INF conforme exibido na figura 1, o web.xml é usado para configurar a aplicação web e quaisquer mecanimos que a mesma utiliza.

    Agora crie o arquivo cadastros-config.xml, copie e cole dentro do mesmo o conteúdo a seguir:

    <?xml version="1.0"?>
    
    <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
    "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
    
    
    <!-- =========== ARQUIVO DE CONFIGURACAO COMPLETO =========================== -->
    
    
    <faces-config>
       <!-- definindo a classe java que vai atuar como backing bean da pagina Cliente.jsp -->   
       <managed-bean>
          <managed-bean-name>formClientes</managed-bean-name>
          <managed-bean-class>cadastros.FormClientes</managed-bean-class>
          <managed-bean-scope>request</managed-bean-scope>
        </managed-bean>
    
        <!-- 
             Regras de navegacao entre paginas da aplicacao, onde um identificador aponta para uma pagina 
             especifica, isso evita que o programador informe localizacao de paginas dentro dos arquivos,    
             o que pode ser muito util no momento em que qualquer manutencao envolvendo muitos arquivos 
             seja necessaria. 
        -->
        <navigation-rule>
          <navigation-case>
             <!-- se foi feita uma referencia para esse identificador -->
             <from-outcome>gravacao_concluida</from-outcome>
             <!-- redirecione para essa pagina -->
             <to-view-id>/gravacao_concluida.jsp</to-view-id>
          </navigation-case>
        </navigation-rule>
        <navigation-rule>
          <navigation-case>
             <!-- se foi feita uma referencia para esse identificador -->
             <from-outcome>erro_gravacao</from-outcome>
             <!-- redirecione para essa pagina -->
             <to-view-id>/erro_gravacao.jsp</to-view-id>
          </navigation-case>
        </navigation-rule> 
    </faces-config>
    

    Este arquivo também deverá ser colocado na pasta WEB-INF, ele é utilizado para definir mapeamento de identificadores para páginas jsp, como também para informar os managed beans ou backing beans utilizados pela aplicação.

    Desenvolvendo a aplicação web:

    Vamos agora criar um script jsp responsável pela camada de apresentação (view) do Java Server Faces, crie este script com o nome Clientes.jsp dentro da pasta Cadastros e coloque dentro do arquivo o conteúdo abaixo:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    <HTML>
      <HEAD>
        <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" 
    %>
        <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <META http-equiv="Content-Style-Type" content="text/css">
        <TITLE>Clientes.jsp</TITLE>
      </HEAD>
    
      <!-- a tag f:view indica o inicio do conteudo JSF -->
      <f:view>
        <BODY>
           <P align="center"><B><U><FONT size="+2">Cadastro de 
    Clientes</FONT></U></B></P>
           <DIV align="center">
    
             <!-- a tag h:form indica um novo formulario a ser usado pelo JSF -->
             <h:form styleClass="form" id="form1">
               <TABLE border="0" width="573" height="20" cellspacing="0" cellpadding="0">
                  <TBODY align="left">
                    <TR>
                      <TD height="18" width="106">Cnpf / Cpf:</TD>
                      <TD height="18" width="387">
    
                        <!-- 
                        a tag h:inputText indica a criacao de um campo de entrada de texto, vale ressaltar 
                        a presenca de dois atributos, o primeiro, required, e usado para informar se e 
                        exigido um valor para o campo e o atributo value que e usado para determinar o 
                        valor do campo, neste caso o atributo value está vinculado a uma propriedade do 
                        backing bean FormCliente chamado idCliente
                        -->
                        <h:inputText styleClass="inputText" id="txtId_Cliente"                                
                         required="true" value="#{formClientes.idCliente}"></h:inputText>
    
                        <!--
                        a tag h:message indica a criacao de uma mensagem especifica para um componente, 
                         neste caso o campo txtId_Cliente, mensagens indicando que o valor do campo e 
                         requerido, tal como mensagens de erro de validacao do campo serao exibidas com a 
                         inclusao desta tag, onde o atributo for indica qual e o componente vinculado e 
                         txtId_Cliente 
                        -->
                        <h:message id="txtId_ClienteError" for="form1:txtId_Cliente" styleClass="error" 
    />
    
                        <!-- 
                        a tag h:commandButton indica a criacao de um botao para submeter dados, vale 
                         ressaltar a presença do atributo action que determina qual sera o metodo dentro 
                         do backing bean que vai realizar o processamento dos dados submetidos neste caso 
                         o metodo a ser invocado será o metodo doBtnPesquisarAction.
                        -->
                        <h:commandButton value="Pesquisar" id="btnPesquisar"
                        action="#{formClientes.doBtnPesquisarAction}"></h:commandButton>
                      </TD>
                    </TR>
                    <TR>
                      <TD height="8" width="106">Nome:</TD>
                      <TD height="8" width="367">
                        <!--
                        o mesmo que na tag h:inputText comentada anteriormente, porem este campo nao e 
                         requerido e a propriedade do backing bean associada a esse campo e nomeCliente
                        -->
                        <h:inputText styleClass="inputText" id="txtNomeCliente" size="60" 
    required="false"
                        value="#{formClientes.nomeCliente}"></h:inputText>
                      </TD>
                    </TR>
                  </TBODY>
               </TABLE>
               <BR>
               <!--
               o mesmo que na tag h:commandButton mencionada anteriormente, porém este botão invocará o 
                método doBtnGravarAction
               -->
               <h:commandButton value="Gravar" id="btnGravar" 
    action="#{formClientes.doBtnGravarAction}">       
               </h:commandButton>
             </h:form>
           </DIV>
        </BODY>
      </f:view>
    </HTML>
    

    Por fim, e finalmente, o código do backing bean, o codebehind do JSF, responsável pela camada de controle (controller) do Java Server Faces, crie o arquivo FormClientes.java e coloque dentro deste arquivo o conteúdo abaixo:

    package cadastros;
    
    import javax.faces.FacesException;
    import javax.faces.context.FacesContext;
    
    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    
    public class FormClientes {
           
       public String idCliente;
       public String nomeCliente;
            
       public FormClientes(){
       
       }    
    
       public String doBtnGravarAction() {
          String resultadoOperacao = null; 
    
          try {
             Class.forName("com.mysql.jdbc.Driver").newInstance();
    
             //conectando no banco de dados
             Connection conexaoBanco = 
    DriverManager.getConnection("jdbc:mysql://localhost/cadastros?user=root&password=root");
    
             //insere um registro no banco de dados o codigo do cliente e a sua razao social obtendo os 
             //dados das propriedades idCliente e nomeCliente desta classe e que estao vinculadas com os 
             //campos txtId_Cliente e txtNomeCliente presentes no formulário da página Clientes.jsp
             PreparedStatement comandoBanco = conexaoBanco.prepareStatement("INSERT INTO 
    CLIENTES(ID_CLIENTE,
             RAZAO_SOCIAL) VALUES(?, ?)");
    
             //associa as propriedades ao comando de insercao preparado
             comandoBanco.setString(1, idCliente);
             comandoBanco.setString(2, nomeCliente); 
    
             //executa a insercao do registro na tabela clientes
             comandoBanco.executeUpdate(); 
    
             //caso a insercao ocorra sem falhas redirecione para a pagina com a mensagem de gravacao 
             //concluida
             resultadoOperacao = "gravacao_concluida";       
             conexaoBanco.close();   
          }
          catch(Exception Erro){
             //caso ocorra algum problema na gravacao do registro redirecione para a pagina de erro
             resultadoOperacao = "erro_gravacao";    
          }
          //efeutua o redirecionamento
          return resultadoOperacao;
       }
            
       public String doBtnPesquisarAction() {
          try{
             Class.forName("com.mysql.jdbc.Driver").newInstance();
             //conectando no banco de dados
             Connection conexaoBanco = 
    DriverManager.getConnection("jdbc:mysql://localhost/cadastros?user=root&password=root");
    
             //realiza uma consulta no banco de dados usando como chave a propriedade 
             //idCliente que esta vinculada         
             //com o campo txtId_Cliente la no formulario da pagina Clientes.jsp
             PreparedStatement comandoBanco = conexaoBanco.prepareStatement("SELECT RAZAO_SOCIAL FROM 
    CLIENTES WHERE ID_CLIENTE = "" + idCliente + """);
                            
             //executa a consulta
             ResultSet resultadoBanco = comandoBanco.executeQuery();
    
                    
             //testa se ha registros no resultado da consulta
             if(resultadoBanco.next()){
                //se ha algum registro entao exiba o valor do campo RAZAO_SOCIAL no campo 
                //txtNomeCliente atraves da propriedade nomeCliente que esta vinculada a esse campo.
                nomeCliente = resultadoBanco.getString("RAZAO_SOCIAL");
             }
             else{
                //caso nao existam registros entao exiba o texto “Nao encontrado”
                nomeCliente = "Não encontrado!";
             }
             resultadoBanco.close();
             conexaoBanco.close();
          }
          catch(Exception Erro){
             throw Erro instanceof javax.faces.FacesException ? (FacesException) Erro : new 
    FacesException(Erro);       
          }
          //recarrega a pagina atual, associando os dados das propriedades aos campos do formulario
          return null;
       }
          
       public String getIdCliente() {
          return idCliente;
       }
    
       public String getNomeCliente() {
          return nomeCliente;
       }
    
       public void setIdCliente(String string) {
          idCliente = string;
       }
    
       public void setNomeCliente(String string) {
          nomeCliente = string;
       }
    }
    

    Distribuindo a aplicação

    Para preparar a aplicação para distribuí-la em um servidor como o Tomcat ou JBoss, basta compactar a pasta WEB-INF e o arquivo Clientes.jsp dentro do arquivo Cadastros.zip e logo após renomeando a extensão para .war e então copie este arquivo compactado para a pasta webapps do tomcat, se o tomcat estiver em execução ele vai efetuar o deploy da aplicação automaticamente.

    Conclusão

    Com o Java Server Faces é possível criar aplicações web com alto nível de reuso de código e componentes, sendo possível definir eventos server-side, além de facilidades para a criação de eventos do lado do cliente sem a necessidade de se adicionar um atributo via linha de código, a versão 2.0 do JSF virá com suporte à comunicação entre frames e janelas, tal como aperfeiçoamentos para uso em IDE"s.

    Sem dúvida o Java Server Faces surge como um grande concorrente do ASP.NET, juntando o que há de melhor em tecnologia já estabelecidas no mercado, como as taglibs (JSTL) e o framework Struts.

  • Rogério Pereira Araújo

    Rogério Pereira Araújo - Consultor de Informática da Druid Internet Systems, desenvolvedor de soluções em busca corporativa, mobilidade e gestão de negócios, possui experiência em diversas tecnologias como Python, Bash, SQL, Perl, Java (JSF, J2ME, EJB), .NET (ASP.NET, Compact Framework), PHP, XML (SOAP e XQuery) e Delphi. Colaborador da revista webmobile e de vídeo-aulas para a JavaMagazine.
    http://faces.eti.br