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újoComo 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:
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) );
http://www.linorg.usp.br/mysql/Downloads/Connector-J/mysql-connector-java-3.1.4-beta.zip
Configurando sua aplicação web para trabalhar com o JSF:
<?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.