fev 27 2010

Spring MVC 3.0 na prática – Parte 1

Category: Spring MVC 3.0Edson Gonçalves @ 2:50

Olá, tudo bom? Como vão vocês?
Este artigo é o primeiro de uma série ao qual vou ensiná-los a trabalhar com o Spring MVC 3.0.
Nesta primeira parte iremos conhecer o framework Spring MVC 3.0 através de um simples exemplo no estilo “Hello World!”.
Dúvidas e críticas são bem vindas.

Iniciando com o Spring MVC 3.0

Embora no Brasil o mais famoso do Spring Framework seja sua implementação tradicional como contêiner IoC (Inversion of Control – Inversão de Controle[¹]), também temos um excelente framework Web chamado de Spring MVC.

O Spring MVC é um framework open-source que usa como princípio o design MVC  Model 2, ao qual possui suporte, em sua view, também para outras tecnologias como: JSP/JSTL/Tiles, XML/XSLT, Velocity e  FreeMarker. A integração com JasperReports e exportação de documentos para PDF e Excel também estão inclusas.

Em Spring MVC 3.0 – Parte 1, iremos aprender a configurar um ambiente e rodar um exemplo simples utilizando o Spring MVC 3.0.

Download do Framework

Para trabalhar com o Spring MVC 3.0, você deve realizar o download na página: http://www.springsource.org/download. No momento em que este artigo é escrito, a versão utilizada é a Spring Framework 3.0.1.RELEASE. Clique em Download. Neste framework, temos mais de uma opção para baixar. Vamos escolher apenas o framework, cujo tamanho é o menor de todos.

Download do Spring Framework em sua página oficial

Figura 1 - Download do Spring Framework em sua página oficial

Ao baixar, descompacte o arquivo extraindo todos os JARs existentes no diretório lib.

O ambiente de trabalho

A própria empresa responsável pelo Spring Source, divisão da VMware, possui uma ferramenta completa, criada sobre a plataforma Eclipse, chamada de SpringSource Tools Suite.

Para baixar o SpringSource Tools Suite, clique aqui, preencha o formulário e faça o Download. Como a ferramenta possui uma opção de instalador, use-a como facilitador se desejar. Na própria página onde baixar o arquivo, haverá a explicação da instalação em cada plataforma, em Installation Instructions.

Criando um projeto

No SpringSource Tools Suite, clique no menu File>New>Dynamic Web Project. Na caixa de diálogo New Dynamic Web Project, digite ConhecendoSpringMVC (ou o nome que desejar dar) em Project name.

O SpringSource Tools Suite possui embutido um servidor de aplicações Java Web baseado no Apache Tomcat 6, só que com algumas modificações. Como já o temos por padrão, ele será utilizado no primeiro projeto de exemplo.  Confirme no botão Finish.

Criando o projeto ConhecendoSpringMVC

Figura 2 - Criando o projeto Conhecendo SpringMVC

O Apache Tomcat no Projeto

Caso deseje configurar o Apache Tomcat 6.0.x, pode ser adicionado através do botão New. Siga os passos a seguir para instalar:

1) Expanda Apache e selecione Apache Tomcat v6.0. Clique em Next;

Selecionando o Apache Tomcat v6.0 para adicionar a ferramenta

Figura 3 - Selecionando o Apache Tomcat v6.0 para adicionar a ferramenta

2) Na etapa seguinte, em Tomcat Server, selecione Download and Install;

Baixando e Instalando o servidor Apache Tomcat

Figura 4 - Baixando e Instalando o servidor Apache Tomcat

3) Antes de baixar, aceite os termos de licença. Confirme no botão Finish.

Termos de licença para a instalação automática do Tomcat

Figura 5 - Termos de licença para a instalação automática do Tomcat no SO Windows 7

Determine o local onde será instalado o Apache Tomcat e confirme. Retornando a etapa onde determinamos o local de instalação do Tomcat, se houver erro de não reconhecimento após baixá-lo (veja a execução do download na barra de status da ferramenta), clique em Browse e OK novamente para que seja reconhecido o local de instalação. Por fim, confirme em Finish.

Finalizando o projeto

Após retornar a etapa final do projeto, confirme no botão Finish. O SpringSource Tools Suite pedirá para que você mude de perspectiva. E confirme.

Associando a perspectiva ao tipo de projeto a ser criado

Figura 6 - Associando a perspectiva ao tipo de projeto a ser criado

Ao finalizar o assistente, terá um projeto criado e acessível através da view Project Explorer.

Projeto com sua estrutura gerada

Figura 7 - Projeto com sua estrutura gerada

Adicionando as bibliotecas ao projeto

Clique com o direito sobre o projeto, na view Project Explorer e selecione, no menu de contexto, o item Properties.

Na caixa de diálogo aberta, vá até Java EE Module Dependencies e adicione os seguintes JARs do Spring Framework que descompactou (através do botão Add JARs):

org.springframework.asm-3.0.1.RELEASE-A.jar
org.springframework.beans-3.0.1.RELEASE-A.jar
org.springframework.context.support-3.0.1.RELEASE-A.jar
org.springframework.context-3.0.1.RELEASE-A.jar
org.springframework.core-3.0.1.RELEASE-A.jar
org.springframework.expression-3.0.1.RELEASE-A.jar
org.springframework.web.servlet-3.0.1.RELEASE-A.jar
org.springframework.web-3.0.1.RELEASE-A.jar

Após adicionar estes JARs, clique em OK para confirmar.

Bibliotecas do Spring Framework adicionadas ao projeto

Figura 8 - Bibliotecas do Spring Framework adicionadas ao projeto

Seu primeiro projeto Spring MVC 3.0

O projeto deste artigo como início será o famoso “Hello World”, necessário para compreendermos as configurações básicas do framework.

Configurando o web.xml

Dê um duplo clique em  Deployment Descriptor na view Project Explorer e altere o arquivo conforme é exibido na Listagem 1:

Listagem 1 – Configurações do Spring Framework no web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>ConhecendoSpringMVC</display-name>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

Para que o Spring funcione, incluindo o seu módulo MVC, utilizamos o servlet org.springframework.web.servlet.DispatcherServlet, configurado no arquivo web.xml da aplicação.

Por padrão, o Spring MVC procura por beans em arquivos de configuração do próprio framework cujo o princípio de nome possui um similar ao do Servlet configurado no web.xml, seguido de -servlet.xml. A Listagem 2 coloca em prática esta situação, criando o arquivo springmvc-servlet.xml.

Criando o arquivo springmvc-servlet.xml

Para criar o arquivo, clique com o direito do mouse sobre o diretório WebContent/WEB-INF, selecionando no menu de contexto o item XML.

Se estiver utilizando o SpringSource Tool Suite, selecione no menu de contexto o item New>Other.

Na caixa de diálogo New, selecione Spring>Spring Bean Configuration File e prossiga no assistente.

Criando um arquivo de configuração do Spring

Figura 9 - Criando um arquivo de configuração do Spring

Na segunda etapa, mantenha o diretório WEB-INF selecionado e digite o nome do arquivo de springmvc-servlet.xml. Tirando “–servlet.xml”, o nome springmvc foi definido por você no arquivo web.xml da Listagem 1.

Definindo o nome do arquivo

Figura 10 - Definindo o nome do arquivo

Na terceira etapa, selecione os seguintes namespaces e seus respectivos XSDs:

beans – http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

context – http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd

Seleção do primeiro namespace do arquivo de configuração do Spring MVC

Figura 11 - Seleção do primeiro namespace do arquivo de configuração do Spring MVC

Listagem 2 – Configurações do arquivo springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd>
<!-- Rastreia as anotacoes encontradas  -->
<context:component-scan base-package="br.com.integrator.web"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>

O arquivo springmvc-servlet.xml é lido graças ao seguinte trecho encontrado dentro do arquivo web.xml:

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Com a classe org.springframework.web.servlet.view.InternalResourceViewResolver, pré-fixamos o caminho das páginas em /WEB-INF/jsp/ e com o sufixo “.jsp”. InternalResourceViewResolver é uma subclasse de UrlBasedViewResolver, que suporta JSTL, também usada em nossas views.

Como boa prática recomendada pelo Spring, colocamos as páginas JSP dentro do diretório WEB-INF, impedindo assim seu acesso direto, manualmente, através da URL.

Criando o Controller

Com o direito do mouse sobre  Java Resources:src, selecione no menu de contexto New>Class. Na caixa de diálogo New Java Class, digite o pacote e, em OlaMundoController no campo Name. Confime em Finish a criação da classe.

Criação da classe OlaMundoController

Figura 12 - Criação da classe OlaMundoController

Altere a classe como mostrado na Listagem 3.

Listagem 3 – A classe OlaMundoController

package br.com.integrator.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class OlaMundoController {
@RequestMapping("/ola")
public ModelAndView ola() {
String mensagem = "Conhecendo o Spring MVC 3.0";
ModelAndView modelAndView = new ModelAndView("ola");
modelAndView.addObject("mensagem", mensagem);
return modelAndView;
}
}

Desde a versão do Spring MVC 2.5, podemos declarar uma classe controller utilizando simplesmente a anotação @Controller, de org.springframework.stereotype.Controller. Esta anotação permite que o Spring faça uma varredura automatica nas classes através do elemento <context:component-scan>.

Através da anotação @RequestMapping, definimos o caminho HTTP que será utilizado na aplicação, sendo mapeada pela classe. Na prática, todas as chamadas à aplicação contendo “/ola” serão analisadas pela classe controller.

DispatcherServlet (configurado no arquivo web.xml – Listagem 1) é o responsável por receber todas as requisições do cliente, executando a parte comum destes pedidos e delegando implementações específicas para os controllers. Este servlet é responsável por ler todas as configurações e usar a leitura de componentes deste framework.

Após DispatcherServlet receber o pedido e fazer o seu trabalho, ele tenta encontrar um controller, usando a interface HandlerMapping (implementada pelos objetos que definem um mapeamento entre requisições e manipulações).

Ao encontrar o controller, o método handleRequest(HttpServletRequest request, HttpServletResponse response) é chamado com a responsabilidade do pedido e, caso seja necessário, retorna um adequado ModelAndView.  Como padrão, uma instância de ModelAndView consiste em um nome da view e um Map, que contém nomes do bean e objetos correspondentes (como um comando ou formulário, contendo dados).

No caso, o Controller chama a view ola e passa mensagem com o valor de “Conhecendo o Spring MVC 3.0”.

Criando a View

Clique com o direito sobre o diretório WebContent/WEB-INF e selecione, no menu de contexto, o item New>Folder. Chame este diretório de jsp. Estamos fazendo isso porque será onde adicionaremos a página JSP. Este nome foi configurado no arquivo springmvc-servlets.xml, conforme a Listagem 2 no elemento <property value=”/WEB-INF/jsp/”/>.

Clique novamente com o direito do mouse, só que, desta vez,  sobre o diretório jsp recém criado, selecionando New>JSP.

Na caixa de diálogo chame de ola.jsp e clique no bota Finish. Altere como mostrado na Listagem 4.

Listagem 4 – A View ola.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>${mensagem}</title>
</head>
<body>
<h2>${mensagem}</h2>
</body>
</html>

Para visualizar a página, digite em seu navegador:

http://localhost:8080/ConhecendoSpringMVC/ola

Resultado da saída gerada pelo Spring MVC 3.0

Figura 13 - Resultado da saída gerada pelo Spring MVC 3.0

O projeto

O resultado final de todos os arquivos criados e configurados no projeto será como mostrado na Figura 14.

Figura 14 – O projeto completo

Figura 14 – O projeto completo


[¹] Veja mais sobre IoC e DI no site do Martin Fowler: http://martinfowler.com/articles/injection.html

Tags: , , ,


fev 21 2010

JavaServer Faces 2.0 na Prática – Parte 3

Category: JSF 2.0Edson Gonçalves @ 3:55

Olá, tudo bom? Como vão vocês?

Este artigo é o terceiro de uma série ao qual vou ensiná-los a trabalhar com o JavaServer Faces 2.0.

Nesta terceira parte iremos conhecer melhor o framework JavaServer Faces 2.0 e seu comportamento.

Dúvidas e críticas são bem vindas.

Conhecendo melhor o JavaServer Faces

Como pudemos  ver, o framework JSF é responsável por interagir com o usuário (cliente). Porém, o escopo de JSF é restringido à camada de apresentação. A persistência de dados e outras conexões back-end estão fora do escopo de JSF.

Se você está começando agora, recomendo voltar até a Parte 1 para melhor compreender este artigo.

Renderizando componentes

Ao chamar uma página JSF no navegador, o servidor inicia uma chamada a árvore de componentes do JSF para renderizar a página de acordo com o encontrado.

O servlet JavaServer Faces inicializa o código do framework e lê a página index.xhtml. Como esta página contém tags JSF, como <h:form />, <h:inputText />, <h:commandButton /> e <h:outputText />, cada uma possui uma classe tag handler associada. Quando a página é lida, as tags handles são executadas, de modo que cada uma colabora com a outra para construir o que chamamos de árvore de componentes. A Figura 1 mostra as tag handlers dos componentes utilizados no exemplo criado na Parte 2 do conjunto de artigos.

Figura 1 – Os componentes da aplicação de exemplo

Figura 1 – Os componentes da aplicação de exemplo

Após ler cada componente, a página HTML é devolvida ao navegador, que a renderiza. Todo e qualquer texto que não for uma tag JSF será passado adiante, onde as demais que não forem serão convertidas em HTML.

O processo de devolver a página no formato HTML ao navegador é chamado de encoding. Se olhar o código HTML gerado, verá que o objeto UIInput, por exemplo, procura o ID (unique ID) e o seu valor atual da expressão #{meuManagedBean.texto}. Por padrão, as strings de atributos ID, do HTML, são adicionadas pelo framework, podendo ser aleatórias. Caso não houver um ID na tag <h:form/>, como no exemplo desenvolvido, poderemos ter um ID como j_idt17:texto:

<input id=”j_idt17:texto” name=”j_idt17:texto” />

Se houver um atributo ID na tag <h:form/> (ex: <h:form id=”form1″ />), você terá como resultado o ID form1:texto na renderização da página:

<input type=”text” />

Se desejarmos retirar essa pré-definição de nome no atributo ID, basta adicionar seguinte atributo e seu valor na tag <h:form/>: prependId=”false”. O resultado tag <h:form/> completa ficaria assim:

<h:form prependId=”false”>

No encoding, o atributo ID gerado seria apenas o nome atribuído na tag pela propriedade id, como, por exemplo, na tag de entrada <h:inputText id=”texto” />, onde a renderização HTML seria:

<input type=”text” />

Depois de ocorrer o encoding, elas são enviadas ao navegador que agora as reconhece como uma página HTML. A Figura 2 ilustra esta transformação.

Figura 2 – Codificação e decodificação das páginas JavaServer Faces

Figura 2 – Codificação e decodificação das páginas JavaServer Faces

Do navegador para o servidor

Depois que o usuário receber a página, este a preenche como deve e submete o formulário ao servidor novamente. No caso do exemplo, o formulário é submetido pelo método HTTP POST, contendo o endereço da página e os dados do formulário.

Os dados no servidor são colocados em uma tabela hash, como ocorre normalmente em processamentos Servlet, que pode ser acessada por todos os componentes. O framework JSF permite que cada componente inspecione esta tabela em um processo chamado de decoding. Neste momento, cada componente decide como serão interpretados os dados do formulário.

O processo como um todo é chamado de Ciclo de Vida e será visto mais adiante, ainda neste artigo.

A arquitetura do JavaServer Faces

Para melhor compreensão, a seguir teremos um resumo de como funcionam as páginas JavaServer Faces:

A arquitetura Model-View-Controller

JSF conecta a apresentação e o modelo. Como vimos, um componente de apresentação pode ser unido a uma propriedade do Managed Bean de um objeto modelo:

<h:outputText value=”#{meuManagedBean.texto}”/>

O JSF opera como o controlador que reage ao usuário processando a ação e os eventos de alteração de valores, enquanto dirige o código para atualizar o modelo ou a apresentação. A invocação ao controlador ocorre através do componente <h:commandButton />.

Quando o botão é clicado e o formulário é enviado (submetido) ao servidor, a implementação JSF invoca o método para checar o bean do usuário. O componente <h:commandButton /> pode possuir um método que entra em ação para atualizar o modelo e devolver para a navegação o ID da próxima página a ser exibida.

Validações e Conversão de dados

Usuários entram com os dados em um formulário Web com um formato de texto. Podemos validar de forma padrão ou personalizada como serão aceitos estes textos (dados). Estas validações, assim como suas conversões, são feitas pelo conjunto de tags JSF Core, que incluímos da seguinte forma:

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core">

A biblioteca de tags Core pode ser incluída também em uma página JSP da seguinte forma:

<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%>

Para validar, por exemplo, o tamanho mínimo de caracteres aceitos, podemos fazer da seguinte forma:

<h:inputText id="texto" value="#{meuManagedBean.texto}">

<f:validateLength minimum="3" />

</h:inputText>

Também podemos validar se um campo é obrigatório ou não, utilizando required=”true”:

<h:inputText value=”#{meuManagedBean.texto}” required=”true” >

Objetos de negócios também requerem informações como números, datas ou outros tipos de dados. Com JavaServer Faces podemos definir com as tags Core como serão os dados aceitos em um determinado campo, convertendo-os ou até mesmo personalizar a regra de conversão.

Um exemplo simples seria utilizar o <f:convertDateTime />, que faz com que o campo de entrada seja apenas um tipo de data e hora com o formato definido, que pode ser acrescido ao seu código da seguinte forma:

<h:inputText id="texto" value="#{meuManagedBean.texto}">

<f:convertDateTime pattern="dd/MM/yyyy" />

</h:inputText>

Manipulação de erros

O JSF utiliza regras de validação para campos como “este campo é obrigatório”. Claro que, quando os usuários entrarem com dados inválidos, preciamos exibir mensagens de erros mais apropriadas.

Os erros, tanto de validação, como de conversão, são tratados da mesma forma: uma mensagem é adicionada ao componente que não passou na verificação (seja validação ou conversão), onde a página atual é novamente exibida contendo uma frase do problema ocorrido.

As tags utilizadas para tais representações são: <h:message /> e <h:messages />. Os erros também podem ser lançados de forma personalizada utilizando o atributo validatorMessage ou requiredMessage. Para o exemplo, poderíamos ter algo assim:

<h:inputText

value="#{meuManagedBean.texto}"

required="true"

validatorMessage="Mínimo de 3 caracteres"

requiredMessage="Campo obrigatório">

<f:validateLength minimum="3" />

</h:inputText>

<h:messages />

Internacionalização

JSF fornece suporte à internacionalização como codificações de caractere e a seleção de pacotes de recursos.

A internacionalização no JSF 2.0 é possível de duas formas: faces-config.xml e a tag Core <f:loadBundle />.

Para uma internacionalização com o arquivo faces-config.xml, devemos adicionar este arquivo dentro do diretório WEB-INF. O conteúdo é mostrado na Listagem 1.

Listagem 1 – O arquivo faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"

version="2.0">

<application>

<resource-bundle>

<base-name>br.com.integrator.rotulos</base-name>

<var>rotulo</var>

</resource-bundle>

<locale-config>

<default-locale>pt</default-locale>

<supported-locale>en</supported-locale>

</locale-config>

</application>

</faces-config>

O arquivo faces-config.xml é usado no JSF 2.0 principalmente para numerosas configurações globais de sua aplicação.

Os rótulos neste caso são colocados em arquivos .properties, onde o nome de cada arquivo possui _ABREVIAÇÃO DO IDIOMA como, por exemplo: rotulos_pt.properties. Crie os arquivos mostrados nas Listagens 2 e 3 dentro do pacote br.com.integrator.

Listagem 2 – O arquivo rotulos_en.properties

texto = Text:

enviar = Submit Text

obrigatorio = Required Field

validacao = Minimum 3 characters

titulo = One simple JSF Page

Listagem 3 – O arquivo rotulos_pt.properties

texto = Texto:

enviar = Enviar Texto

obrigatorio = Campo Obrigatório

validacao = Mínimo de 3 caracteres

titulo = Uma simples página JSF

Para compreender como ficará seu projeto, a Figura 3 mostra onde estará cada um dos arquivos que o compõem.

Figura 3 – Estrutura de diretórios do projeto

Figura 3 – Estrutura de diretórios do projeto

As alterações na página index.xhtml são mostradas na Listagem 4 a seguir.

Listagem 4 – Alterações na página index.xhtml

...

<h:head>

<title><h:outputText value="#{rotulo.titulo}" /></title>

</h:head>

<h:body>

<h:form>

<h:outputText value="#{rotulo.texto}" />

<h:inputText id="texto"

value="#{meuManagedBean.texto}"

required="true"

validatorMessage="#{rotulo.validacao}"

requiredMessage="#{rotulo.obrigatorio}">

<f:validateLength minimum="3" />

</h:inputText>

<h:messages />

<br />

<h:commandButton value="#{rotulo.enviar}" action="enviar" />

<br />

<h3><h:outputText value="#{meuManagedBean.texto}" /></h3>

</h:form>

</h:body>

...

Para visualizar as alterações, será necessário trocar o idioma padrão do seu navegador. No Mozilla Firefox, por exemplo, basta ir em Ferramentas>Opções>Conteúdo>Idiomas e clicar no botão Selecionar. Coloque o idioma diferente do que está usando como primeiro na ordem da lista de idiomas de preferência e confirme tudo. Dê um reload na página que verá as alterações.

Caso não queira usar uma declaração global dos recursos de localidades, podemos adicionar a tag <f:loadBundle  /> em cada página JSF. A seguir o trecho que poderá substituir a configuração global no arquivo faces-config.xml.

<f:loadBundle

basename="br.com.integrator.rotulos"

var="rotulo />

Nota: Das duas formas apresentadas para internacionalização de uma aplicação Web com o framework JSF, a versão com o elemento <resource-bundle />, encontrado no arquivo faces-config.xml, é a mais eficiente, pois é utilizado em todo o aplicativo e não somente na página configurada.

Componentes customizados

O desenvolvedor de componentes pode criar componentes sofisticados que são chamados pelos designers simplesmente colocando suas tags em suas páginas, ou arrastando-as caso sejam visuais. Um exemplo é pegar bibliotecas criadas, como de calendários, gráficos ou de upload de arquivos com barra de progresso e simplesmente adicionar na página desenvolvida.

Desde o JavaServer Faces 2.0, criar componentes customizados ficou mais fácil, com um recurso chamado de Composite Components (Componentes Compostos). Para exemplificar como funcionam os recursos de Composite Components, altere como nos passos a seguir seu projeto:

  1. Crie um diretório chamado de resources, no mesmo diretório onde se encontra a página index.xhtml.
  2. Dentro do diretório resources, adicione outro diretório chamado de componente.
  3. No diretório componente, crie uma página XHTML, chamada de component.xhtml,  com o conteúdo mostrado na Listagem 5.

Listagem 5 – Conteúdo do arquivo component.xhtml

<!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"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:composite="http://java.sun.com/jsf/composite">

<h:head>

<title>Meu Primeiro Componente JSF 2.0</title>

</h:head>

<h:body>

<composite:interface>

<composite:attribute name="identificacao" required="true"/>

<composite:attribute name="managedbean" required="true"/>

<composite:attribute name="qtdcaracteres" required="true"/>

</composite:interface>

<composite:implementation>

<h:outputText value="#{rotulo.texto}" />

<h:inputText id="#{cc.attrs.identificacao}"

value="#{cc.attrs.managedbean}"

required="true"

validatorMessage="#{rotulo.validacao}"

requiredMessage="#{rotulo.obrigatorio}">

<f:validateLength minimum="#{cc.attrs.qtdcaracteres}" />

</h:inputText>

<h:messages />

<br />

<h:commandButton value="#{rotulo.enviar}" />

<br />

<h3><h:outputText value="#{cc.attrs.managedbean}" /></h3>

</composite:implementation>

</h:body>

</html>

Uma página de componente(s) no JSF 2.0 pode conter suporte aos componentes do JSF, a validação, converters e listeners. Além disso, qualquer outra tag HTML pode ser adicionada ao componente, incluindo também recursos de templates.

As tags utilizadas para criar componentes compostos no exemplo são: <composite:interface/> e <composite:implementation/>. Para utilizá-las, é necessário adicionar o seguinte namespace:

<html xmlns:composite=”http://java.sun.com/jsf/composite”>

A tag <composite:interface/> declara o contrato para um componente, ou seja, definimos quais são os atributos que o componente receberá. Os atributos são definidos dentro desta tag, com a tag <composite:attribute />, onde temos os atributos name e required. Em name colocamos o nome do atributo do nosso componente composto e definindo true, em required, definimos o atributo como de preenchimento obrigatório.

O exemplo mostrado possui um componente que terá os seguintes atributos obrigatórios, em ordem definidos na interface: identificacao, managedbean e qtdcaracteres.

A tag <composite:implementation/> é onde definimos o conteúdo do componente composto. Onde definir #{cc.attrs.x}, sendo que “x” é o nome do atributo do seu componente, será o local de substituição quando preencher o componente na página que o utilizar.

Para utilizar este componente, vá à página index.xhtml e altere seu conteúdo conforme a Listagem 6 a seguir:

Listagem 6– A página index.xhtml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!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"

xmlns:f="http://java.sun.com/jsf/core"

xmlns: comp="http://java.sun.com/jsf/composite/componente">

<h:head>

<title><h:outputText value="#{rotulo.titulo}" /></title>

</h:head>

<h:body>

<h:form>

<comp:component

identificacao="texto"

managedbean="#{meuManagedBean.texto}"

qtdcaracteres="3" />

</h:form>

</h:body>

</html>

Para utilizar o componente criado, você adiciona o seguinte namespace em sua página:

xmlns: comp=”http://java.sun.com/jsf/composite/componente

Observe que componente, no namespace, é o nome do diretório onde se encontra seu componente composto (o diretório fica dentro de resources caso não se lembre). O nome comp é dado por nós para chamar o componente. Podemos ter inúmeros componentes dentro de um diretório, assim como vários diretórios dentro de resources. Os agrupamos como acharmos melhor, de acordo com o conveniente no desenvolvimento de nossos aplicativos.

Para utilizar o componente, o chamamos assim: <comp:component/>. Onde component é o nome do arquivo .xhtml criado. Os atributos deste componente podem ser vários e os definidos como obrigatórios precisam ser preenchidos para que não ocorram erros.

Figura 4 – Da criação do componente até sua utilização e renderização na página

Figura 4 – Da criação do componente até sua utilização e renderização na página

Renderizadores Alternativos

Por padrão, JSF produz HTML em sua saída, mas é extensível o suficiente para produzir outros tipos de saídas como, por exemplo, WML ou XUL.

Ajax

JavaServer Faces possui atualmente uma comunicação Ajax padrão que torna-se totalmente transparente as chamadas cliente-servidor sem a necessidade de reload na página.

Para conhecer rapidamente o Ajax no JavaServer Faces 2.0, altere a página index.xhtml como mostrado na Listagem 7.

Listagem 7 – Alterações na página index.xhtml

...

<h:form>

<h:outputScript name="jsf.js" library="javax.faces" target="head"/>

<h:outputText value="#{rotulo.texto}" />

<h:inputText id="texto" value="#{meuManagedBean.texto}"/>

<br />

<h:commandButton id="enviar" value="#{rotulo.enviar}">

<f:ajax execute="form1:texto" render="form1:saida"/>

</h:commandButton>

<br />

<h3>

<h:outputText id="saida" value="#{meuManagedBean.texto}" />

</h3>

</h:form>

...

Com algumas pequenas mudanças, sua aplicação passou a utilizar o recurso de Ajax.

O JSF 2.0 possui uma nova API JavaScript, ao qual pode chamar o servidor, enviando e recebendo dados. Nesta API JavaScript, temos o seguinte método:

jsf.ajax.request(source, event, options)

Este método envia e recebe os dados do servidor de forma assíncrona diretamente para os componentes da view. Você pode vê-lo no HTML renderizado.

A tag <f:ajax /> que utilizamos no exemplo pode ser substituída pela chamada direta à  jsf.ajax.request() da seguinte forma:

<h:commandButton value=”#{rotulo.enviar}”

onclick=”jsf.ajax.request(this, event,

{execute: ‘form1:texto’, render: ‘form1:saida’}); return false;” />

Em ambos os casos, seja com a tag <f:Ajax/> ou pelo script adicionado na tag, na renderização, o método recebe o elemento que está disparando a ação , que no geral é o próprio que o chama (this), o evento e um conjunto de parâmetros.

Neste conjunto de parâmetros existem duas propriedades: execute e render. Tanto o execute, como o render, recebem os IDs dos elementos HTML renderizados no cliente, ou seja, o ID dos componentes que passaram pelo encoding. O execute define o componente que será submetido ao servidor via Ajax e render qual componente receberá a resposta.

O Ajax padrão de JSF 2.0 é obtido pela tag <h:outputScript />. Esta tag, configurada como no exemplo, renderiza a tag HTML <script/>, que trás um JavaScript existente na biblioteca JSF 2.0. Os três atributos usados no exemplo são:

  • name – O nome do arquivo externo de JavaScript que, no caso, pertence a própria biblioteca de JSF 2.0;
  • library – A biblioteca usada;
  • target –  Onde será renderizada a tag <script/>, que no caso será por entre as tags <head/>, sempre no HTML.

Nota: O JavaScript contido no JSF 2.0 em questão está dentro do JAR jsf-impl.jar, em META-INF/resources/javax.faces/jsf.js. Veja mais a respeito sobre o JavaScript padrão de JSF 2.0 no seguinte link: https://javaserverfaces.dev.java.net/nonav/docs/2.0/jsdocs/index.html.

O MVC de JSF

Para que JSF funcione, registramos a classe FacesServlet no deployment descriptor (web.xml). Ao fazer este registro, os pedidos são controlados pela classe javax.faces.webapp.FacesServlet (o Controller do MVC), uma implementação de javax.servlet.Servlet, roteando o tráfego e administrando o ciclo de vida dos beans e componentes de interface do usuário (UI).

Figura 5 – O MVC do framework JSF

Figura 5 – O MVC do framework JSF

Os componentes UI são organizados em uma estrutura de árvore onde, cada componente, pode ser associado com os métodos e atributos de um bean. Cada componente também pode ser associado com uma função de validação ou classe.

Por trás, FacesServlet aceita pedidos de entrada e controla o objeto javax.faces.lifecycle.Lifecycle. Usando uma factory, ela cria um objeto do tipo javax.faces.context.FacesContext, que contém todos os processos.

O ciclo de vida do JSF

O objeto Lifecycle usa o objeto FacesContext em seis fases que compõem o ciclo de vida de uma aplicação JSF. Cada fase tem uma ação importante em sua aplicação e deve ser bem compreendida para que você possa manipular ao extremo sua interface e melhorar a legibilidade de seu desenvolvimento.

Figura 6 – Ciclo de vida do JavaServer Faces

Figura 6 – Ciclo de vida do JavaServer Faces

As seis fases são executadas na seguinte ordem:

  1. Restaurar Apresentação [1]– Esta fase inicia o processamento da requisição do ciclo de vida por meio da construção da árvore de componentes do JSF. Cada árvore de componentes possui um identificador único durante todo o aplicativo. O JSF constrói a apresentação da página e salva  na instância FacesContext para processamento das fases seguintes.
  2. Aplicar Valores Requisitados – Nesta fase, quaisquer novos valores inseridos são extraídos e armazenados por seus apropriados componentes. Se o valor do componente não for uma String, então ele é convertido para o seu determinado tipo. Se a conversão falhar, ocorrem diversas situações:
  1. 1. Uma mensagem de erro é gerada e associada com o componente;
  2. 2. Uma mensagem de erro é armazenada no FacesContext e depois mostrada posteriormente na fase de Renderizar a Resposta;
  3. 3. O ciclo de vida pula a fase de Renderizar a Resposta quando esta se completou.
  1. Processar Validações – Depois do valor de cada componente ser atualizado, na fase de processo de validações, os componentes serão validados naqueles valores, se necessário. Um componente que necessita de validação deve fornecer a implementação da lógica de validação. Por exemplo, em um carrinho de compras, podemos determinar a quantidade mínima a ser digitada e máxima. O valor requisitado é um inteiro (verificado na fase anterior) e, como passou pela fase 2, nessa fase pode ser barrado por estar além do determinado (com uma quantidade mínima ou máxima diferente da estipulada).
  2. Atualizar Valores do Modelo – Alcança-se essa fase após todos os componentes serem validados. Nesta fase são atualizados os dados do modelo do aplicativo. Na página em que foi criada para enviar um texto, a informação digitada foi armazenada no Managed Bean durante esta fase. Por ter passado pelo processo de validação, temos garantias que o valor armazenado  será garantido nessa fase. Entretanto, os dados podem violar a lógica de negócios, ao qual a validação ocorre na fase seguinte.
  3. Invocar Aplicação – Durante esta fase, a implementação JSF manipula quaisquer eventos do aplicativo, tal como enviar um formulário ou ir a outra página através de um link. Estes eventos são ações que retornam geralmente uma  string que está associada a uma navegação no qual se encarrega de chamar a página determinada.
  4. Renderizar Resposta – Esta é a fase final, ao qual é renderizada a página. Se este é um pedido inicial para esta página,  os componentes são acrescentados à apresentação neste momento. Se este é um postback,  os componentes já foram acrescidos à apresentação.  Se há mensagens de conversão ou erros de validação e a página contém um ou mais componentes <mensage /> ou um componente <messages />, estes serão exibidos.  Reciprocamente, se a página não contém um componente de mensagem,  nenhuma informação aparecerá.

Numa requisição a uma página JSF, podemos passar por todas essas fases ou por nenhuma, dependendo do tipo de pedido, de erros que ocorrem durante as validações, conversões e do tipo de resposta.

Uma requisição e uma resposta são consideradas faces request/response se contiverem tags JSF, assim como as que não as contém são chamadas de non-faces request/response. Uma non-faces request pode vir de um clique em um link, por exemplo.

Como já dito, toda requisição é recebida pelo FacesServlet e prossegue a passagem pelas fases (Lifecycle) até uma resposta ser retornada ao cliente.

O FacesServlet recupera uma instância de FacesContext, do FacesContextFactory, fornecendo uma implementação de LifeCycle. O processamento do ciclo de vida é então delegado a interface LifeCycle, a partir da chamada ao método execute. A implementação de LifeCycle inicia as fases do ciclo de vida. Se existir algum validador associado a algum campo do formulário este é inicializado nessa primeira fase. A árvore é armazenada pelo contexto e será utilizada nas fases seguintes. Também o estado do formulário é salvo automaticamente.

Testando o ciclo de vida

Para confirmar como todas as fases do ciclo de vida são usadas e quais são, basta criar um simples PhaseListener e mandá-lo gerar a saída antes e depois de cada fase.

Criando uma classe Phase Listener

Criar uma classe que implemente a PhaseListener exigem dois passos:

• Criar uma classe que implemente PhaseListener;

• Registrar esta classe no arquivo de configurações do JSF.

A classe PhaseListener deve implementa a classe javax.faces.event.PhaseListener.  A Listagem 8 demonstra como criar esta classe:

Listagem 8 – A classe PhaseListener

package br.com.integrator.listener;

public class PhaseListener implements javax.faces.event.PhaseListener {

public void afterPhase(PhaseEvent event) {

event.getFacesContext().getExternalContext().

log("AFTER: "+event.getPhaseId());

}

public void beforePhase(PhaseEvent event) {

event.getFacesContext().getExternalContext().

log("BEFORE: "+event.getPhaseId());

}

public PhaseId getPhaseId() {

return PhaseId.ANY_PHASE;

}

}

Para a classe da Listagem 8, três métodos são implementados: afterPhase(), beforePhase() e getPhaseId().

Os dois primeiros,  afterPhase()beforePhase(), definem o que ocorre ANTES e DEPOIS de cada fase.  Nestes métodos foram incluídos a capacidade de imprimir na saída console o que ocorreu.

O terceiro método, getPhaseId(), especifica  em  qual das fases é invocado este ouvinte (Listener) e PhaseId.ANY_PHASE menciona que será para todas as fases.

Com a classe criada, o próximo passo é registrar esta classe PhaseListener no arquivo de configurações do JSF (faces-config.xml).

Para fazer isso, no arquivo faces-config.xml,  adicionaremos os seguintes elementos do trecho a seguir:

<faces-config ...>

...

<lifecycle>

<phase-listener>

br.com.integrator.listener.PhaseListener

</phase-listener>

</lifecycle>

</faces-config>

Ao rodar a aplicação, haverá saídas no console de acordo com o uso da aplicação. A Figura 7 mostra tanto o uso da aplicação como sua saída no console, passando pelas seis fases do ciclo de vida.

Figura 7- Execução do exemplo e saída no Console resultante da classe PhaseListener

Figura 7- Execução do exemplo e saída no Console resultante da classe PhaseListener

Podemos testar o comportamento das fases enviando o formulário sem dados preenchidos ou preenchendo erroneamente. É uma forma de analisar de perto o ciclo de vida do framework JavaServer Faces.


[1] Defino aqui como Apresentação a tradução para View, que se refere ao Model-View-Controller, no qual traduzo como Modelo-Apesentação-Controle. Entretanto, a especificação JSF define como View o nome para uma página JSF. No decorrer dos artigos, sempre que me referir a View, estarei tratando da página JSF e não da palavra existente em MVC.

Tags: , , , ,


fev 03 2010

JPA 2.0 na Prática – Parte 2

Category: JPA 2.0Edson Gonçalves @ 14:13

Olá, tudo bom? Como vão vocês?

Este artigo é o segundo de uma série ao qual vou ensiná-los a trabalhar com a Java Persistence API 2.0 (JPA 2.0).  Dúvidas e críticas são bem vindas.

Os primeiros passos na JPA

Com o ambiente configurado, agora podemos  configurar a JPA e dar nossos primeiros passos em sua execução, entendendo como funciona e o que podemos fazer.

Esta parte do artigo está baseada na configuração, criação da entidade e manipulação básica do banco de dados.

Caso você tenha chegado agora, a Parte 1 do artigo ensina como configurar o seu ambiente de desenvolvimento e testes.

Configurando o arquivo persistence.xml

Ao criar o projeto, também foram criados um diretório e arquivo. Note o arquivo chamado persistence.xml,  encontrado no diretório META-INF, dentro de src.

Abra o arquivo persistence.xml e verá que o Eclipse IDE possui um editor do arquivo.

Sua estrutura básica é como mostrada na Listagem 1 abaixo:
Listagem 1 – O arquivo persistence.xml

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistence

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

<persistence-unit>

</persistence-unit>

</persistence>

Ela pode ser visualizada no Editor do Eclipse, em Source.

Configurando a conexão com o banco de dados

No editor do Eclipse, vá na aba Connection, em persistence.xml.

Adicionando as configurações de conexão ao persistence.xml

Adicionando as configurações de conexão ao persistence.xml

Comece alterando para Resource Local em Transaction type.

Esta pequena alteração adiciona o atributo transaction-type com o valor “RESOURCE_LOCAL” em <persistence-unit/> no arquivo persistence.xml.  O atributo transaction-type está definindo que a unidade de persistência terá sua integridade gerida  através da API local (RESOURCE_LOCAL), que é o nosso caso, onde não haverá um servidor de aplicativos Java EE por enquanto envolvido para transações JTA (Java Transaction API).

Mais abaixo, em EclipseLink Connection Pool, clique em Populate from Connection.

Adicionando os parâmetros de conexão no arquivo persistence.xml

Adicionando os parâmetros de conexão no arquivo persistence.xml

Ao abrir a caixa de diálogo Connection Selection, selecione a conexão do MySQL que fez na criação do projeto e confirme.

Conexão do MySQL feita na criação do Projeto

Conexão do MySQL feita na criação do Projeto

Ao retornar ao arquivo persistence.xml, os dados pertencentes ao banco de dados estarão preenchidos.

Configurações para a conexão ao banco de dados

Configurações para a conexão ao banco de dados

Esta mudança da conexão alterou o arquivo persistence.xml da seguinte forma:

<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpapratica"/>
<property name="javax.persistence.jdbc.user" value="edson"/>
<property name="javax.persistence.jdbc.password" value="integrator"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>

Na JPA 2.0, algumas propriedades foram padronizadas. As propriedades que foram adicionadas ao arquivo persistence.xml são padrões para se conectar ao banco de dados. Veja o que significa cada uma delas:

  • javax.persistence.jdbc.driver — o nome do driver da classe totalmente qualificado
  • javax.persistence.jdbc.url — URL específico do driver
  • javax.persistence.jdbc.user — usuário do banco de dados para a conexão
  • javax.persistence.jdbc.password — senha do banco de dados para a conexão

Vá agora até a aba Logging e, em Logging level, altere para All. Isso tornará visível todas as operações que fizemos, utilizando a JPA, no Console do Eclipse.

Alterando o nível de logging para ALL

Alterando o nível de logging para ALL

Infelizmente, nem todas as propriedades de persistence.xml foram padronizadas. A seguinte propriedade foi adicionada ao arquivo:

<property name=“eclipselink.logging.level” value=“ALL”/>

Ainda em persistence.xml, vá até a aba Schema Generation.  Nesta aba temos DDL generation type. Como não fizemos nenhuma tabela no banco de dados, teremos que criá-la ao executar nossa primeira entidade.

Temos três opções:

  • None – não ocorre nada;
  • Create Tables – cria as tabelas baseando-se nas informações contidas nas entidades;
  • Drop and Create Tables – exclui e cria as tabelas através das informações contidas nas entidades;

Para o nosso trabalho inicial, vamos manter um ciclo de criação e exclusão,  selecionando Drop and Create Tables.

Gerando tabelas através da configuração de persistence.xml

Gerando tabelas através da configuração de persistence.xml

As últimas alterações incluíram a seguinte propriedade:

<property name=“eclipselink.ddl-generation” value=“drop-and-create-tables”/>

Com estas mudanças, temos tudo pronto para trabalhar com a JPA.

Criando sua primeira entidade

Clique com o direito do mouse sobre src, do seu projeto JPA. Selecione no menu de contexto New>Entity.

Criando uma entidade JPA no Eclipse IDE

Criando uma entidade JPA no Eclipse IDE

Na caixa de diálogo New JPA Entity, preencha Java package e Class name, no caso: br.com.integrator e Categoria, respectivamente. Mantenha Entity em Inheritance e clique no botão Next.

Criando a classe/entidade Categoria

Criando a classe/entidade Categoria

Na segunda etapa, definimos o nome da tabela que será utilizada pela entidade Categoria e seus respectivos campos/colunas.

Segunda etapa da criação da Entidade JPA

Segunda etapa da criação da Entidade JPA

O Eclipse IDE, através do seu assistente, irá manter o nome da tabela como padrão existente ao nome da entidade. Desmarque Use default e altere para categorias em Table name.

Esta pequena alteração informa que a entidade Categoria está ligada a tabela categorias do banco de dados.

Alteração do nome da tabela para o banco de dados

Alteração do nome da tabela para o banco de dados

Abaixo você vai encontrar Entity fields. Clique em Add para adicionar as os atributos que existirão na entidade Categoria e seus respectivos tipos.

Detalhe da adição de atributos na entidade Categoria

O diálogo Entity Fields possui Type para colocar o tipo ( que também é acessível com Ctrl+Space) e o nome.

Adicionando um atributo

Adicionando um atributo

Os atributos da entidade são mostrados na Figura abaixo:

Atributos da entidade Categoria

Atributos da entidade Categoria

Veja que foi marcado id como key. Isso fará com que este atributo/campo seja a chave primária.

Diálogo completamente preenchido

Diálogo completamente preenchido

Com tudo preenchido, clique no botão Finish para gerar a classe Categoria com as devidas anotações que a fará uma Entidade da JPA.

A classe/entidade Categoria possui a estrutura como mostrado na Listagem 2 após sua geração:

Listagem 2 – A entidade Categoria

package br.com.integrator;
import java.io.Serializable;
import java.lang.Long;
import java.lang.String;
import javax.persistence.*;
@Entity
@Table(name="categorias")
public class Categoria implements Serializable {
@Id
private Long id;
private String categoria;
private String descricao;
//getters e setters omitidos
}

As entidades, na especificação da JPA, são POJOS (Plain Old Java Objects ), onde podemos alocar com o operador new, assim como faríamos com qualquer outro objeto Java simples. As instâncias de uma classe do tipo entidade não se tornam persistentes até estarem associadas a um EntityManager.

No arquivo persistence.xml, verá a classe adicionada em General>Managed Classes.

Detalhe de Managed Classes em persistence.xml

Detalhe de Managed Classes em persistence.xml

No XML de persistence.xml, haverá a seguinte linha adicionada:

<class>br.com.integrator.Categoria</class>

O elemento <class/> lista explicitamente as classes que são consideradas entidades no persistence.xml.

Para finalizar, vá até a classe Categoria. Na view JPA Structure, clique em id. Marque Primary key generation na view JPA Details e selecione Identity em Strategy. Isso informa a entidade que o campo da chave primária é auto-incrementado e, portanto, gerado pela tabela do banco de dados.

Definindo a estratégia de auto-incremento no campo id da entidade

Definindo a estratégia de auto-incremento no campo id da entidade

Na classe veremos a seguinte anotação: @GeneratedValue(strategy = IDENTITY), onde IDENTITY é de javax.persistence.GenerationType.

Testando a JPA

Antes de explicar qualquer coisa, vamos fazer um teste para saber se está tudo corretamente funcionando, simplesmente chamando a persistence-unit através de uma simples classe Java com um método main().

Crie uma classe no próprio projeto JPA , chamando-a de TesteDaJPA. Coloque em um pacote diferente do qual vem usando e marque public static void main(String[] args). Confirme a criação da classe no botão Finish.

Criação da classe de testes

Criação da classe de testes

Altere a classe TesteDaJPA conforme a Listagem 3:

Listagem 3 – A classe TesteDaJPA

package br.com.integrator.teste;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class TesteDaJPA {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JpaNaPratica");
EntityManager em = emf.createEntityManager();
em.close();
emf.close();
 }
}

Execute a classe através do menu Run>Run As>Java Application.

Graças à configuração que fizemos de logging no arquivo persistence.xml (em <property name=“eclipselink.logging.level” value=“ALL”/>) , possuímos uma saída bem detalhada do que ocorreu ao gerar este simples teste.

Assim que iniciada a classe, veremos a saída contendo a conexão ao banco de dados:

[EL Finest]: 2010-02-03 04:33:36.007--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.MySQLPlatform, RegularExpression: (?i)mysql.*.
[EL Fine]: 2010-02-03 04:33:36.007--Thread(Thread[main,5,main])--Detected Vendor platform: org.eclipse.persistence.platform.database.MySQLPlatform
[EL Config]: 2010-02-03 04:33:36.022--ServerSession(11025290)--Connection(29232906)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
 platform=>MySQLPlatform
 user name=> "edson"
 datasource URL=> "jdbc:mysql://localhost:3306/jpapratica"
))
[EL Config]: 2010-02-03 04:33:36.022--ServerSession(11025290)--Connection(9616314)--Thread(Thread[main,5,main])--Connected: jdbc:mysql://localhost:3306/jpapratica
 User: edson@localhost
 Database: MySQL Version: 5.1.43-community
 Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.10 ( Revision: ${svn.Revision} )
[EL Config]: 2010-02-03 04:33:36.022--ServerSession(11025290)--Connection(23255990)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
 platform=>MySQLPlatform
 user name=> "edson"
 datasource URL=> "jdbc:mysql://localhost:3306/jpapratica"
))
[EL Config]: 2010-02-03 04:33:36.038--ServerSession(11025290)--Connection(16496587)--Thread(Thread[main,5,main])--Connected: jdbc:mysql://localhost:3306/jpapratica
 User: edson@localhost
 Database: MySQL Version: 5.1.43-community
 Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.10 ( Revision: ${svn.Revision} )
[EL Finest]: 2010-02-03 04:33:36.069--ServerSession(11025290)--Thread(Thread[main,5,main])--sequencing connected, state is NoPreallocation_State

Entre a saída, veremos que, devido a configuração no persistence.xml (em <property name=“eclipselink.ddl-generation” value=“drop-and-create-tables”/>) , primeiro houve uma tentativa de fazer um drop table na tabela categorias. Como não existia tal tabela, veremos este erro:

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'categorias'
Error Code: 1051
Call: DROP TABLE categorias
Query: DataModifyQuery(sql="DROP TABLE categorias")
Em seguida veremos a criação da tabela na seguinte linha:
[EL Finest]: 2010-02-03 04:33:36.163--ServerSession(11025290)--Thread(Thread[main,5,main])--Execute query DataModifyQuery(sql="CREATE TABLE categorias (ID BIGINT AUTO_INCREMENT NOT NULL, CATEGORIA VARCHAR(255), DESCRICAO VARCHAR(255), PRIMARY KEY (ID))")

Por fim, será possível ver que ocorre a desconexão ao banco de dados.

A tabela gerada no banco de dados

Ao entrar no banco de dados, veremos que a simples classe anotada se transformou em uma tabela. Evidentemente que o POJO, sem a devida configuração no arquivo persistence.xml, antes da sua chamada pela classe executora que fizemos de teste, não teria esse poder.

A tabela gerada no MySQL

A tabela gerada no MySQL

Graças a anotação @Table, pudemos dar o nome da tabela que seria gerada, através do atributo name.

Atributos convertidos em colunas

Observe que cada atributo da classe se transformou em uma coluna na tabela. A coluna chave, tida por ID, foi gerada graças à anotação @Id. Além disso, o MySQL considerou esta coluna como auto-incrementada, ou seja, ela possui um modificador que incrementa em um toda vez que uma informação é inserida na tabela. Isso é automático e gerenciado pelo banco de dados. A anotação @GeneratedValue foi a responsável pela geração do auto-increment do MySQL.

Os tipos de cada coluna são gerados pelo similar em Java. Logo, Long se transformou em bigint e String em varchar. Cada tipo de coluna, na tabela do banco de dados, possui também um tamanho definido na sua criação. Como não especificamos isso na classe Categoria, através de anotações, a tabela foi gerada utilizando o tamanho máximo obtido pelo tipo, isso no banco de dados em questão. Logo, Long se transformou em bigint(20) e String em varchar(255).

Na próxima parte

Na Parte 2 da série JPA 2.0 na Prática finalmente fizemos a configuração da JPA, possibilitando a conexão ao banco de dados. Também foi possível gerar uma tabela baseada em uma entidade da JPA através de um pequeno teste de utilização.

Em JPA 2.0 na Prática – Parte 3, começaremos a compreender a Entidade em questão, suas várias anotações e implicações no banco de dados.

As entidades, na especificação da JPA, são POJOS (Plain Old Java Objects ), onde podemos alocar com o operador new, assim como faríamos com qualquer outro objeto Java simples. As instâncias de uma classe do tipo entidade não se tornam persistentes até estarem associadas a um EntityManager.

No arquivo persistence.xml, verá a classe adicionada em General>Managed Classes.

Tags: , , , , ,


jan 25 2010

JPA 2.0 na Prática – Parte 1

Category: JPA 2.0Edson Gonçalves @ 2:59

Olá, tudo bom? Como vão vocês?

Este artigo é o primeiro de uma série ao qual vou ensiná-los a trabalhar com a Java Persistence API 2.0 (JPA 2.0).  Dúvidas e críticas são bem vindas.

Preparando o ambiente

Se você tem experiência com instruções SQL, JPA é  fácil de entender. A JPA trabalha com objetos diretamente e converte as suas instruções para SQL através da JDBC, de modo a executar no banco de dados.

JPA na prática começará com um ambiente de trabalho simples, onde teremos as execuções fora do ambiente Java EE.

O banco de dados

O banco de dados utilizado será o MySQL. Você pode baixar a versão 5.1, utilizada no artigo, aqui.

Preparando o banco de dados do exemplo

Abra o terminal do MySQL com seu usuário e senha ROOT (aquela que você configurou na instalação).

Crie o banco de dados executando o seguinte comando:

create database jpapratica;

Baixando e descompactando o driver JDBC

No mesmo local onde baixamos o MySQL, existe a versão atual do driver JDBC, chamado de Connector/J 5.1. Baixe o arquivo e o descompacte.  O arquivo JAR do qual iremos precisar será:

mysql-connector-java-5.1.10-bin.jar

O ambiente de trabalho

Os exemplos desenvolvidos serão criados no Eclipse IDE 3.6 M4, ao qual teremos uma breve explicação de como criar projetos JPA.

Baixando o Eclipse

No momento em que este artigo é criado, o Eclipse IDE 3.6 ainda está em desenvolvimento. Esta versão foi escolhida por possuir suporte a JPA 2.0. O pacote que vamos usar é o Eclipse IDE for Java EE Developers.

Download Eclipse IDE 3.6

Figura 1. Download do pacote Eclipse IDE 3.6 para Java EE

A  biblioteca JPA

O EclipseLink é a biblioteca oficial da Java Persistence API 2.0.  Você pode baixá-la clicando aqui. O arquivo baixado para o exemplo é o EclipseLink 2.0.0 Installer Zip.

Ao baixar o arquivo, descompacte-o. Você precisará das seguintes bibliotecas:

  • eclipselink.jar
  • javax.persistence_2.0.0.v200911271158.jar

Criando o projeto

No Eclipse, na view Project Explorer, clique com o direito e selecione New>JPA Project.

Criando um projeto JPA

Figura 2. Criando um projeto JPA no Eclipse

Na caixa de diálogo New JPA Project, digite o nome do projeto em Project name. No exemplo que usaremos será chamado de JpaNaPratica. Em Configuration, mantenha em Minimal JPA 2.0 Configuration. Clique no botão Next para prosseguir.

Primeira etapa do projeto

Figura 3. Primeira etapa da criação do projeto

A segunda etapa mantenha como está, prosseguindo com o botão Next.

Segunda etapa da criação do Projeto

Figura 4. Segunda etapa da criação do projeto

As bibliotecas do EclipseLink no projeto

Na terceira etapa, você vai configurar o EclipseLink 2.0. Para isso, clique no ícone Manage libraries.

Terceira etapa da criação do projeto

Figura 5. Terceira etapa da criação do projeto - Clicando no ícone Manage libraries

Na caixa de diálogo Preferences, clique no botão New.

Caixa de diálogo Preferences

Figura 6. Caixa de diálogo Preferences - Botão New

Na caixa de diálogo New User Library digite EclipseLink e confirme no botão OK.

Caixa de diálogo New User Library

Figura 7. Caixa de diálogo New User Library

Ao retornar a caixa de diálogo Preferences, clique no botão Add JARs e selecione as bibliotecas do EclipseLink.

Caixa de diálogo Preferences - botão Add JARs

Figura 8. Caixa de diálogo Preferences - botão Add JARs

Após selecioná-las, confirme a caixa de diálogo no botão OK.

Biblioteca EclipseLink com os JARs adicionados

Figura 9. Biblioteca EclipseLink com os JARs adicionados

Ao retornar ao diálogo de criação do seu projeto, marque a biblioteca EclipseLink que agora está lá.

Biblioteca EclipseLink adicionada na criação do projeto

Figura 10. Biblioteca EclipseLink adicionada na criação do projeto

A conexão no Eclipse e a biblioteca do banco de dados no projeto

Abaixo, em Connection, clique em Add connection.

Detalhe em Add Connection na criação do projeto

Figura 11. Detalhe em Add Connection na criação do projeto

Na caixa de diálogo New Connection Profile, selecione o MySQL e dê o nome da sua conexão em Name. Prossiga clicando no botão Next.

Caixa de diálogo New Connection Profile

Figura 12. Caixa de diálogo New Connection Profile

Na próxima etapa, você precisa adicionar definir o driver JDBC do banco de dados MySQL. Clique no ícone (New Driver Definition).

Detalhe da localização do ícone New Driver Definition

Figura 13. Detalhe da localização do ícone New Driver Definition

Na caixa de diálogo New Driver Definition, você possui três abas:

Name/Type – Aqui definimos qual a versão do driver JDBC iremos usar. Neste caso, MySQL JDBC Driver.

Selecionando o driver JDBC do MySQL

Figura 14. Selecionando o driver JDBC do MySQL

Jar List – O local onde se encontra o arquivo JAR. Neste caso, remova o atual, clicando em Remove JAR/Zip e adicione o que foi baixado em Add JAR/Zip.

Adicionando o path para o arquivo JDBC do MySQL

Figura 15. Adicionando o path para o arquivo JDBC do MySQL

Properties – Podemos configurar a conexão ao banco de dados. Coloque os dados do seu banco de dados utilizado no exemplo deste artigo.

Propriedades da conexão ao banco de dados do exemplo

Figura 16. Propriedades da conexão ao banco de dados do exemplo

Após configurar o seu driver e conexão com o banco de dados, confirme no botão OK.

Retornando ao diálogo New Connection Profile, agora com as configurações do seu banco de dados preenchidas, marque Save password.

Dados para a conexão preenchidos

Figura 17. Dados para a conexão preenchidos

Clique no botão Test Connection e, se estiver com tudo funcionando perfeitamente, verá uma mensagem de sucesso.

Conexão executada com sucesso

Figura 18. Conexão executada com sucesso

Terminadas estas configurações, seu perfil de conexão está pronto. Pode finalizar o diálogo clicando em Finish.

Caixa de diálogo New Connection Profile com dados da conexão

Figura 19. Caixa de diálogo New Connection Profile com dados da conexão

Retornando a criação do projeto, em New JPA Project, agora você possui todas as informações necessárias para criar o projeto JPA. Clique no botão Finish para gerar o projeto.

Etapa final do diálogo New JPA Project com tudo preenchido

Figura 20. Etapa final do diálogo New JPA Project com tudo preenchido

O Eclipse desejará colocar a perspectiva associada ao tipo de projeto. Basta confirmar em Yes.

Autorizando a mudança de perspectiva

Figura 21. Autorizando a mudança de perspectiva

O projeto gerado é mostrado na Figura a seguir:

Projeto JPA gerado

Figura 22. Projeto JPA gerado

Adicionando a biblioteca JDBC no projeto

Embora, para configurar o projeto JPA, você criou uma conexão com o MySQL, esta apenas funciona no Eclipse IDE. Para adicionar no seu projeto a biblioteca JDBC, clique com o direito do mouse sobre ele e selecione Properties no menu de contexto.

Na caixa de diálogo Properties, vá em Java Build Path, na aba Libraries e clique em Add Library.

Caixa de diálogo Properties, em Java Build Path, na aba Libraries

Figura 23. Caixa de diálogo Properties, em Java Build Path, na aba Libraries

Na caixa de diálogo Add Library, selecione Connectivity Driver Definition e clique no botão Next.

Caixa de diálogo Add Library, em Connectivity Driver Definition

Figura 24. Caixa de diálogo Add Library, em Connectivity Driver Definition

Na segunda etapa, selecione a configuração do MySQL que fez para o Eclipse, em Available Driver Definitions e confirme no botão Finish.

Seleção da configuração do MySQL em Available Driver Definitions

Figura 25. Seleção da configuração do MySQL em Available Driver Definitions

Agora você possui a biblioteca JDBC também em seu projeto. Agora confirme a caixa de diálogo e seu projeto estará pronto para trabalhar com a JPA 2.0.

Detalhe da biblioteca JDBC do MySQL adicionada ao projeto

Figura 26. Detalhe da biblioteca JDBC do MySQL adicionada ao projeto

Em JPA 2.0 na Prática – Parte 2, vocês verão como configurar, criar entidades e executar operações em JPA que serão refletidas no banco de dados do MySQL.

Bons Códigos!

Tags: , , , , ,


« Página anterior