jan 28 2011

Gerando relatórios JasperReports na Web com Fontes embebidas

Category: iReport,JasperReportsEdson Gonçalves @ 5:43

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

Em 2011 quero começar com um artigo ensinando uma dúvida muito frequente aos usuários de hospedagem da Integrator Host: embeber as fontes desktop no relatório JasperReports para serem usadas no aplicativo Web.

No geral, relatórios são criados no desktop, onde usamos uma ferramenta visual, arrastando,  modificando e, claro, gerando uma aparência agradável. Se a aparência então for feita por um Designer, este pouco se importa onde vai ser gerado tal relatório, o importante é o VISUAL. É neste momento que começa o problema.

Um relatório pode usar fontes desktop que não estão disponíveis no servidor online. Pior, se o seu aplicativo roda em um servidor compartilhado, raramente uma empresa de hospedagem vai ficar instalando suas fontes desktop na máquina servidora, toda vez que você estiver com um relatório “enfeitadinho”. Se instalar, também não será na hora. O que fazer neste caso então? Como obter independência?

Pensando nesta questão, a equipe de desenvolvimento do JasperReports incluiu a capacidade de adicionar as fontes desktop em seu aplicativo, para que estejam disponíveis quando aquele seu belo relatório for gerado para o cliente.

O que veremos neste artigo é como executar tal tarefa, partindo de um relatório já gerado no iReport.

Para acompanhar este artigo

Criei um banco de dados simples, com uma tabela chamada produtos, contendo os campos selecionados como mostra a Figura 1.

Figura 1 – A tabela usada

O relatório foi criado usando o assistente do iReport 4, onde o resultado final, após minhas pequenas alterações, é o que mostra a Figura 2.

Figura 2 – Relatório gerado pelo assistente com pequenas modificações

Tenham em mente que este artigo não vai ensiná-los a criar relatórios e sim como contornar um problema comum entre os desenvolvedores Java. Caso queiram dominar a arte de desenvolver relatórios JasperReports com o iReport, vejam a minha seção de livros clicando aqui.

Trabalhando com fontes personalizadas no relatório

Após desenhar o relatório, chega o momento de finalizar a “arte” com alguns toques e, em meio as mudanças, eis que surge a ideia de personalizar a fonte também do texto contido no relatório.

No exemplo que fiz, os textos fixos foram todos personalizados com uma fonte que possuo em minha máquina, chamada Impact.

Figura 3 – A fonte escolhida para o texto estático Produtos do relatório

Embora esta fonte seja importante para o design do meu relatório, não tenho garantias que ela exista no servidor onde hospedo meus aplicativos.  Logo, o que parece simples, pode se tornar um pesadelo se não for eu o responsável pela administração do sistema operacional.

Adicionando a fonte ao aplicativo

Graças ao problema de ausência de fontes em servidores de hospedagem, muitos desenvolvedores não podiam depender da empresa ou administrador que fornece a máquina onde disponibilizam se encontram aplicativos, principalmente quando se trata de uma hospedagem compartilhada.  É nisto que o JasperReports inclui a  possibilidade de ter todas as fontes que usou em seu relatório em produção.

Adicionando e exportando a fonte no iReport

Vá no menu Tools >Options (menu iReport>Preferences no Mac OS X) e, na janela Options, em iReport, selecionem a aba Fonts.

Através do botão Install Font selecionamos as fontes que desejamos importar no iReport. Depois de importadas, podemos selecionar todas elas e exportá-las através do botão Export as extension.

Figura 4 – A fonte escolhida e usada no relatório pronta para ser exportada

No exemplo que explico, chamei o arquivo que exportei de font.jar. É justamente este arquivo que vou adicionar em meu projeto.

A fonte como uma biblioteca no seu aplicativo Web pelo Eclipse IDE

No Eclipse, basta clicar com o direito do mouse sobre o projeto, selecionar o item Properties. Na caixa de diálogo Properties, vamos em Java Build Path, na aba Libraries. Para adicionarmos a biblioteca font.jar, vamos no botão Add External JARs.

Figura 5 – O JAR font.jar adicionado nas bibliotecas do meu projeto

Claro que eu não poderia deixar de comentar uma particularidade do Eclipse IDE na versão Helios. Para projetos Java EE. Nesta versão, temos um item de nome diferente para adicionarmos as bibliotecas do projeto no aplicativo Web. Este item está na janela Properties, em  Deployment Assembly. É neste local que determinamos quais bibliotecas serão exportadas ao executarmos o servidor Java.

Figura 6 – Adicionando os arquivos JARs do projeto no aplicativo Web

Ao clicarmos no botão Add, a caixa de diálogo New Assembly Directive surge. Esta caixa de diálogo é a responsável por selecionarmos as bibliotecas do projeto em Java Build Path Entries.

Figura 7 – Obtendo os arquivos JARs de Java Build Path

Ao clicarmos em Next, veremos todas as bibliotecas que dispomos em Java Build Path. Selecionem todas – as bibliotecas para executar o relatório JasperReports devem estar presentes – finalizando no botão Finish.

Figura 8 – Arquivos JARs selecionados

Retornando ao diálogo Properties, no item Deployment Assembly, temos todas as bibliotecas que serão adicionadas ao diretório lib do projeto, incluindo font.jar.

Figura 9 – As bibliotecas que serão exportadas para o diretório /lib do projeto Web

A fonte como uma biblioteca no seu aplicativo Web pelo NetBeans IDE

No NetBeans IDE, basta adicionar em Libraries, clicando com o direito do mouse e selecionando, no menu de contexto, o item Add JAR / Folder.

Figura 10 – As bibliotecas que serão exportadas para o diretório /lib do projeto Web

Antes e depois da fonte adicionada ao projeto

Para satisfazer a curiosidade do que será visto, temos a Figura 11 que mostra um relatório gerado, em formato PDF, sem a fonte no diretório lib do projeto. Note a diferença com a Figura 12 em relação ao formato da fonte, principalmente do título “Produtos”.

Figura 11 – Arquivo PDF gerado como relatório sem a fonte no diretório lib do projeto

Figura 12 – Arquivo PDF gerado como relatório com a fonte no diretório lib do projeto


O projeto para download

Clique aqui para baixar o projeto e alterá-lo como desejar.

Tags: , , , , ,


out 24 2010

Spring MVC 3 na Prática com Bean Validation

Category: Spring,Spring MVC 3.0Edson Gonçalves @ 20:56

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

Este é o terceiro artigo da série Spring MVC 3.0. Se vocês não tiveram um contato inicial com o framework, recomendo ver este artigo primeiro.

Para acompanhar esta terceira parte, recomendo ter criado o projeto do segundo artigo.

Como sempre, dúvidas e críticas são bem vindas.

Alterando o CRUD criado com o Spring MVC

O projeto neste artigo é o mesmo do segundo artigo da série. Entretanto, faremos algumas alterações para que passe a utilizar validações do Bean Validation.

Adicionando as bibliotecas ao projeto utilizando o Maven

Mais uma vez, recorreremos ao Maven para adicionar as bibliotecas que necessitamos. Neste caso, teremos que baixar o Hibernate Validator. Para utilizar o Bean Validation, utilizaremos dois JARs: hibernate-validator-4.0.2.GA.jar e validation-api-1.0.0.GA.jar.

Abram o arquivo pom.xml , encontrado na view Package Explorer para que possamos adicionar as configurações que necessitamos.

Criando a propriedade

Na aba Overview, em Properties, cliquem no botão Create. Na caixa de diálogo Add property, preencham como na Figura 1.

Figura 1 – Criação da property da versão do hibernate validator

Criando a dependência

Com a propriedade definida para informar qual versão desejamos utilizar, no qual o Maven deverá baixar, resta configurar as dependências.

Na aba Dependencies, cliquem no botão Create e preencham conforme a Figura 2 ilustra.

Figura 2 – A dependência do Hibernate Validator

Alterando a entidade Contato

A entidade do artigo, chamada de Contato, será a primeira coisa que iremos modificar no projeto.

Graças a JSR 303, chamada de Bean Validation, podemos anotar as entidades com validações. Com as anotações de Bean Validation na entidade, concentramos a validação em um único local, de forma padronizada, tornando possível portar estas validações para as classes controladoras do Spring MVC.

A Listagem 1 exibe  a entidade Contato modificada. Note as anotações de validação onde colocamos as mensagens de erro embutidas. Mais adiante iremos capturá-las para exibir o problema ao usuário.

Listagem 1. A entidade Contato com anotações Bean Validation.

package br.com.integrator;

import javax.persistence.*;
import javax.validation.constraints.*;

@Entity
@Table(name = "contato")
public class Contato {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	private Long id;
	@NotNull
	@Size(min=5, message="O nome não pode ter menos que 5 caracteres!")
	private String nome;
	@NotNull
	@Pattern(regexp = "^[\\w\\-]+(\\.[\\w\\-]+)*@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$", message="E-mail com formato incorreto.")
	private String email;
	@Pattern(regexp = "\\(?\\b([0-9]{2})\\)?[-. ]?([0-9]{4})[-. ]?([0-9]{4})\\b", message="Telefone em formato incorreto")
	private String telefone; 

     //getters e setters
 }

A infra-estrutura definida pela JSR 303 nos permite descrever as restrições, usando anotações no modelo de classes de persistência, como definir se um campo aceitará uma quantidade mínima de caracteres ou se não aceitará nulo, por exemplo.

Cada anotação é associada a uma validação, verificando se a instância da entidade anotada obedece à regra ou não.

A Tabela 1 apresenta todas as anotações possíveis de serem usadas e suas funcionalidades.

Annotation O que faz?
@AssertFalse Checa se a propriedade anotada é falsa.
@AssertTrue Checa se a propriedade anotada é verdadeira.
@DecimalMax(value=) A propriedade anotada precisa ser um número, cujo valor deve estar menor ou igual ao valor máximo previsto. O parâmetro value é a representação em string do valor máximo aceito de acordo com o formato representado em BigDecimal. Suporta tipos como BigDecimal, BigInteger, String, byte, short, int, long e os respectivos wrappers de tipos primitivos.
@DecimalMin(value=) A propriedade anotada precisa ser um número, cujo valor deve estar maior ou igual ao valor mínimo previsto. O parâmetro value é a representação em string do valor mínimo de acordo com a representação de sequência de BigDecimal. Suporta tipos como BigDecimal, BigInteger, String, byte, short, int, long e os respectivos wrappers de tipos primitivos.
@Digits(integer=, fraction=) Verifica se a propriedade possui a quantidade de dígitos antes e depois do separador de casa decimal. Por exemplo: @Digits(integer=9, fraction=2) significa que espera-se 9 dígitos inteiros e 2 dígitos fracionários. Suporta os tipos: BigDecimal, BigInteger, String, byte, short, int, long e os respectivos wrappers de tipos primitivos.
@Future Checa se a data está no futuro. Suporta os tipos java.util.Date e java.util.Calendar.
@Max(value=) Verifica se o valor é menor ou igual ao valor anotado. Suporta os tipos: BigDecimal, BigInteger, String, byte, short, int, long e os respectivos wrappers de tipos primitivos.
@Min(value=) Verifica se o valor é maior ou igual ao valor anotado. Suporta os tipos: BigDecimal, BigInteger, String, byte, short, int, long e os respectivos wrappers de tipos primitivos.
@NotNull Checa se o valor anotado não é nulo (null). Uma String cujo valor seja vazio (“”) vai passar.
@Null Checa se o valor anotado é nulo (null).
@Past Checa se uma data está no passado. Suporta os tipos java.util.Date e java.util.Calendar.
@Pattern(regex=, flag=) Checa se a propriedade obedece à expressão regular.
@Size(min=, max=) Confere se a quantidade de elementos está entre o mínimo e o máximo, suportando tipos como: Strings, Collections, Maps e arrays.
@Valid Impõe uma validação recursiva aos objetos associados. Digamos que, no bean Post, houvesse a anotação @Valid no atributo comments. Já na classe Comment, temos um atributo de validação anotado. Se um valor transmitido a comments, de Post, não estiver de acordo com a validação existente na classe Comment, de acordo com o atributo anotado, um erro será gerado em tempo de execução. A notação @Valid está sendo usada no PostController para validar os erros existentes em Post ou Comment.

Tabela 1. Anotações e regras para criar restrições (Constraints).

Alterando o controlador

Alteraremos a classe ContatoController, criada no pacote br.com.integrator.web, de acordo com o mostrado na Listagem 2.

Listagem 2. A classe ContatoController alterada.

package br.com.integrator.web;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import br.com.integrator.dao.ContatoDAO;
import br.com.integrator.Contato;

@Controller
@RequestMapping("/contato/**")
public class ContatoController {
@Autowired
private ContatoDAO contatoDao;

@RequestMapping(value = "/contato/{id}", method = RequestMethod.GET)
public String show(@PathVariable("id") Long id, ModelMap modelMap) {
modelMap.addAttribute("contato", contatoDao.find(id));
return "contato/show";
}

@RequestMapping(value = "/contato", method = RequestMethod.GET)
public String list(ModelMap modelMap) {
modelMap.addAttribute("contatos", contatoDao.findAll());
return "contato/list";
}

@RequestMapping(value = "/contato/{id}", method = RequestMethod.DELETE)
public String delete(@PathVariable("id") Long id) {
contatoDao.remove(contatoDao.find(id));
return "redirect:/contato";
}

@RequestMapping(value = "/contato/form", method = RequestMethod.GET)
public String form(ModelMap modelMap) {
modelMap.addAttribute("contato", new Contato());
return "contato/create";
}

@RequestMapping(value = "/contato", method = RequestMethod.POST)
public String create(@Valid Contato contato, BindingResult result) {
if (result.hasErrors())
return "contato/create";

contatoDao.persist(contato);
return "redirect:/contato";
}

@RequestMapping(value = "/contato/{id}/form", method = RequestMethod.GET)
public String updateForm(@PathVariable("id") Long id, ModelMap modelMap) {
modelMap.addAttribute("contato", contatoDao.find(id));
return "contato/update";
}

@RequestMapping(method = RequestMethod.PUT)
public String update(@Valid Contato contato, BindingResult result) {
if (result.hasErrors())
return "contato/update";

contatoDao.merge(contato);
return "redirect:/contato";
}

}

Como visto na Listagem 1, as anotações @Size e @Pattern possuem o atributo message, que capturamos pelo Spring MVC na classe ContatoController (Listagem 2)  – através da classe javax.validation.Valid (anotação @Valid). Assim como a anotação @Controller, as anotações pertencentes a Bean Validation são obtidas graças a adição do elemento <mvc:annotation-driven />. Isto permite que as informações anotadas sejam injetadas onde a validação é necessária na sua aplicação.Caso haja um erro, o método hasErrors(), de org.springframework.validation.BindingResult, retorna true, nos possibilitando conduzir a navegação da página, com seus respectivos erros, inclusive paralisando a ação ao qual se encontra. A utilização de hasErrors() ocorre em ContatoController, nos métodos create() e update() com o seguinte if:

if (result.hasErrors())

//executa uma ação para conduzir a página com os erros ao usuário

As informações recebidas da validação pela classe Controller são transmitidas para o formulário e capturadas. Veja como isto ocorre na descrição da Listagem 3.

Alterando as views

Temos três páginas que representam nosso CRUD feitas. Estas páginas foram criadas dentro do diretório chamado WEB-INF/jsp/contato(fisicamente na ferramenta: src/main/webapp/WEB-INF/jsp/contato). Teremos que alterá-las para permitir que os erros sejam exibidos.

O formulário de cadastro

Abra o arquivo create.jsp e altere como na Listagem 3, adicionando as tags  <form:errors />.

Listagem 3. A página create.jsp.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <style type="text/css" media="screen">
 @import url("<c:url value="/static/styles/style.css"/>");
 </style>
<title>Cadastrar</title>

</head>
<body>
 <div id="wrap">

 <div id="menu">
 <%@ include file="/menu.jsp" %>
 </div>
 <div id="main">
 <div id="body">
 <c:url var="url" value="/contato" />
 <form:form action="${url}" method="POST" modelAttribute="contato">
 <div>
 <label for="nome">Nome:</label>
 <form:errors path="nome" cssClass="errors"/><br />
 <form:input cssStyle="width:250px" maxlength="30" path="nome" size="30"/>

 </div>
 <br/>
 <div>
 <label for="email">Email:</label>
 <form:errors path="email" cssClass="errors"/><br />
 <form:input cssStyle="width:250px" maxlength="30" path="email" size="30"/>

 </div>
 <br/>
 <div>
 <label for="telefone">Telefone:</label>
 <form:errors path="telefone" cssClass="errors"/><br />
 <form:input cssStyle="width:250px" maxlength="30" path="telefone" size="20"/>
</div>
 <br/><div>
 <input id="criar" type="submit" value="Criar Contato"/>
 </div>
 </form:form>
 </div>
 </div>
 </div>
</body>
</html>
A tag  <form:errors /> foi utilizada na Listagem 3 com dois parâmetros: path e cssClass. No parâmetro path transmitimos o  atributo da classe Contato, validada pelas anotações de Bean Validation, onde receberá a mensagem.

Figura 3 – Processo de validação partindo da anotação no JavaBean Contato

Podemos ter uma idéia de como ficará a página create.jsp depois das alterações visualizando a Figura 4.

Figura 4 – Validação transmitida para a página de JSP

Figura 4 – Validação transmitida para a página de JSP

Alterando a página de atualização de dados

Como feito na página create.jsp, a página update.jsp também receberá as tags <form:errors />. A Listagem 4 exibe a página com as mudanças, na íntegra.

Listagem 4. A página update.jsp.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <style type="text/css" media="screen">
 @import url("<c:url value="/static/styles/style.css"/>");
 </style>
<title>Atualizar</title>
</head>
<body>
 <div id="wrap">
 <div id="menu">
 <%@ include file="/menu.jsp" %>
 </div>
 <div id="main">
 <div id="body">
 <c:url var="url" value="/contato/${contato.id}" />
 <form:form action="${url}" method="PUT" modelAttribute="contato">
 <div>
 <label for="nome">Nome:</label>
 <form:errors path="nome" cssClass="errors"/><br />
 <form:input cssStyle="width:250px" maxlength="30" path="nome" size="30"/>
 </div>
 <br/>
 <div>
 <label for="email">Email:</label>
 <form:errors path="email" cssClass="errors"/><br />
 <form:input cssStyle="width:250px" maxlength="30" path="email" size="30"/>
 </div>
 <br/>
 <div>
 <label for="telefone">Telefone:</label>
 <form:errors path="telefone" cssClass="errors"/><br />
 <form:input cssStyle="width:250px" maxlength="30" path="telefone" size="20"/>
 </div>
 <br/>
 <div>
 <input id="atualizar" type="submit" value="Atualizar Contato"/>
 </div>
 <form:hidden path="id"/>
 </form:form>
 </div>
 </div>
 </div>
</body>
</html>

O projeto para download

Clique aqui para baixar o projeto e alterá-lo como desejar.

Considerações finais

Com as validações, boa parte dos problemas iniciais de um desenvolvimento usando o Spring MVC foram resolvidos. Mas vejam só: é o começo. Caso haja interesse do leitor em aprender um exemplo mais complexo, a revista JavaMagazine #78 publicou, um artigo meu com o Spring MVC 3 na criação de um blog, do começo ao fim. É um bom início para se desenvolver um projeto mais completo e complexo.
Para os que acompanham o blog, o assunto Spring MVC não para por aqui. Veremos em breve um site completo, feito com o framework, unindo várias características do Spring, de seu framework MVC e a parte de segurança com Spring Security.

Tags: , , , , , , , ,


ago 16 2010

Spring MVC 3 na Prática com JPA 2

Category: Spring MVC 3.0Edson Gonçalves @ 0:49

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

Este é o segundo artigo da série Spring MVC 3.0. Desta vez iremos trabalhar com a JPA em conjunto com o framework Spring MVC. Se vocês não tiveram um contato inicial com o framework, recomendo ver este artigo primeiro.

Como sempre, dúvidas e críticas são bem vindas.

O Servidor Java

Para este artigo, vamos utilizar o Tomcat 7.0, ainda em beta. Para baixar o binário do Tomcat 7, vá até o endereço http://tomcat.apache.org/.

A versão que vamos baixar é a compactada. Por exemplo, se o seu Windows for de uma versão 64bits, baixe o arquivo apache-tomcat-7.0.0-windows-x64.zip.

Atenção: O Tomcat 7.0 roda somente na JDK 6 ou superior.

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 springmvc;

 

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, usem-na 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 o projeto

Na view Package Explorer, com o direito do mouse, selecionem New>Spring Template Project no menu de contexto.

Figura 1 – Iniciando a criação de um projeto modelo utilizando Spring MVC

Figura 1 – Iniciando a criação de um projeto modelo utilizando Spring MVC

Na caixa  de diálogo New Template Project, selecione Spring MVC Project e clique no botão Next.

Figura 2 – Opção Spring MVC Project

Figura 2 – Opção Spring MVC Project

Ao aparecer a caixa de diálogo Import, cliquem no botão Yes para permitir que o projeto faça o download das bibliotecas do Spring MVC. No segundo projeto que criar, não haverá necessidade deste download. Falaremos mais adiante sobre este download e como ele ocorre.

Figura 3 – Confirmação para o download das bibliotecas do projeto

Figura 3 – Confirmação para o download das bibliotecas do projeto

Após o download das bibliotecas, prosseguiremos na criação do projeto. Coloque o nome do seu projeto em Project name e o pacote principal abaixo. Confirmem no botão Finish.

Figura 4 – Definição do nome do projeto e pacote principal

Figura 4 – Definição do nome do projeto e pacote principal

O assistente criará, em sua conclusão, um projeto com uma estrutura básica, contendo uma classe, página e arquivos de configurações do framework Spring MVC, como mostra na Figura 5.

Figura 5 – Estrutura inicial do projeto gerado

Figura 5 – Estrutura inicial do projeto gerado

Alterando o projeto base gerado pelo assistente

Além dos arquivos contidos para a execução do projeto, temos o pom.xml, o que denota que o projeto é gerado sobre a estrutura do Maven.

Na view Package Explorer, se expandirmos Maven Dependencies, veremos as bibliotecas que o projeto necessita para ser executado. Neste momento, o projeto está funcionando tal como foi gerado pelo assistente.

Figura 6 – Página inicial gerada pelo assistente utilizando o framework Spring MVC

Figura 6 – Página inicial gerada pelo assistente utilizando o framework Spring MVC

Para compreendermos o que foi gerado, vejam o primeiro artigo que escrevi sobre o Spring MVC, ao qual explico a base do framework.

Entretanto, não vamos utilizar alguns dos arquivos criados. Selecione os seguintes diretórios e arquivos do projeto e os remova:

  • WelcomeController.java
  • WelcomeControllerTests.java
  • spring/
  • views/
  • urlrewrite.xml

Adicionando outras bibliotecas ao projeto utilizando o Maven

Embora boa parte das bibliotecas que precisamos no projeto já estejam disponíveis, precisamos adicionar a biblioteca JDBC do MySQL e as do Hibernate para trabalharmos com a JPA 2.

Abram o arquivo pom.xml , encontrado na view Package Explorer. No canto superior do lado direito, temos o ícone Show Advanced Tabs. Vamos exibir, ao clicar neste ícone, novas tabs que permitirão configurar novos repositórios.

Figura 7 – Exibindo tabs avançadas do editor visual para o arquivo pom.xml

Figura 7 – Exibindo tabs avançadas do editor visual para o arquivo pom.xml

Adicionando um repositório

Na aba Repositories, cliquem no botão Create. Preencham com JBoss Repo em Id e http://repository.jboss.com/maven2.  Este repositório será necessário para obtermos a última versão do Hibernate, importante para nosso projeto.

Figura 8 – O repositório JBoss configurado

Figura 8 – O repositório JBoss configurado

Criando propriedades

Caso o leitor não conheça o Maven ainda, já deve ter desconfiado que informamos um endereço para baixarmos as bibliotecas. Entretanto, quais desejamos?

Na aba Overview, em Properties, cliquem no botão Create. Na caixa de diálogo Add property, preencham como na Figura 9.

Figura 9 – Criação da property da versão do Hibernate

Figura 9 – Criação da property da versão do Hibernate

Adicione outra property preenchendo o diálogo como na Figura 10.

Figura 10 – Criação da property da versão da JPA

Figura 10 – Criação da property da versão da JPA

Por fim, adicionem mais uma property e preencham como a Figura 11.

Figura 11 – Criação da property da versão da biblioteca JDBC do MySQL

Figura 11 – Criação da property da versão da biblioteca JDBC do MySQL

Criando as dependências

As propriedades foram definidas para informar qual versão desejamos utilizar das bibliotecas que o Maven deverá baixar. Entretanto, precisamos configurar as dependências.

Na aba Dependencies, cliquem no botão Create e preencham conforme a Figura 12 ilustra.

Figura 12 – A dependência do Hibernate

Figura 12 – A dependência do Hibernate

Criem uma nova dependência e configurem conforme a Figura 13 demonstra.

Figura 13  - A dependência da API JPA 2.0

Figura 13 – A dependência da API JPA 2.0

Façam o mesmo processo preenchendo conforme a Figura 14 exibe.

Figura 14 – A dependência da biblioteca JDBC do MySQL

Figura 14 – A dependência da biblioteca JDBC do MySQL

E para a parte de transações do Spring, configure a dependência  conforme a Figura 15.

Figura 15 – A dependência da biblioteca para transações do Spring Framework

Figura 15 – A dependência da biblioteca para transações do Spring Framework

Para trabalhar com banco de dados no Spring, configure a dependência  conforme a Figura 16.

Figura 16 – A dependência da biblioteca jdbc do Spring Framework

Figura 16 – A dependência da biblioteca jdbc do Spring Framework

Como estamos trabalhando com a JPA, o  Spring precisa da dependência  que configuramos no Maven conforme a Figura 17.

Figura 17 – A dependência da biblioteca orm do Spring Framework

Figura 17 – A dependência da biblioteca orm do Spring Framework

Ao salvar o arquivo, automaticamente o Maven entrará em ação trazendo as bibliotecas faltantes para o seu projeto. Vemos isto na view Console.

Nota: Detalhes de como o Maven funciona não serão mostrados neste artigo. É importante lembramos que o objetivo deste artigo não é ensinar a trabalhar com Maven, seja através do arquivo pom.xml ou pelo Eclipse IDE.

Um CRUD com Spring MVC utilizando JPA 2.0

O projeto neste artigo será baseado em apenas uma entidade, suficiente mostrar a vocês a integração entre as duas tecnologias no desenvolvimento.

Iremos agora modificar o projeto criado automaticamente pelo assistente.

A entidade Contato

Teremos para o exemplo apenas uma entidade, chamada de Contato. Esta entidade, trabalhará com uma tabela contato, no qual possui quatro atributos, sendo o atributo id o único que será gerado automaticamente. A Listagem 1 exibe  a entidade que será usada no exemplo.

Listagem 1. A entidade Contato.

package br.com.integrator;

import javax.persistence.*;

@Entity

@Table(name = "contato")

public class Contato {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

@Column(name = "id")

private Long id;

private String nome;

private String email;

private String telefone;

//getters and setters

}

Para fazê-la, cliquem com o direito do mouse sobre o pacote br.com.integrator e selecionem, no menu de contexto, o item New>Class.

Figura 18 – Criação da classe Contato

Figura 18 – Criação da classe Contato

Acessando os dados

O acesso aos dados é feito pelo padrão DAO (Listagem 2), com a adição de anotações do Spring Framework.  No princípio, adicionamos a anotação @Repository(“contatoDao”), ao qual indica ao Spring Framework que se trata de um DAO. Veremos mais a respeito adiante, na configuração final do Spring.

Utilizamos a anotação @Transactional, para fazer o controle transacional e a anotação @PersistenceContext, permitindo assim com que o Spring injete um EntityManager no serviço quando instanciado. Esta anotação pode ser colocada no atributo ou método setter. Com a esta injeção, temos um comportamento similar ao oferecido pelo EJB 3, incluindo transações, só que sem a necessidade de um contêiner EJB para isso.

Para criar a classe da Listagem 2, criem uma nova classe e coloquem o pacote br.com.integrator.dao e preencham o nome da classe como ContatoDAO.

Figura 19 – Criação da classe ContatoDAO

Figura 19 – Criação da classe ContatoDAO

Listagem 2. A classe ContatoDAO.

package br.com.integrator.dao;

import java.util.List;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import org.springframework.transaction.annotation.Transactional;

import br.com.integrator.Contato;

@Repository("contatoDao")

public class ContatoDAO{

protected EntityManager entityManager;

public ContatoDAO() {

}

@PersistenceContext

public void setEntityManager(EntityManager entityManager) {

this.entityManager = entityManager;

}

public Contato find(Long id) {

return entityManager.find(Contato.class, id);

}

@Transactional

public void persist(Contato contato) {

entityManager.persist(contato);

}

@Transactional

public void merge(Contato contato) {

entityManager.merge(contato);

}

@Transactional

public void remove(Contato contato) {

entityManager.remove(contato);

}

@SuppressWarnings("unchecked")

public List<Contato> findAll() {

return entityManager.createQuery("SELECT c FROM Contato c").getResultList();

}

}

Controlando como o aplicativo funciona

A classe ContatoController, que será criada no pacote br.com.integrator.web, exibida na Listagem 3, lida com as requisições do cliente, controlando o rumo que será dado na chamada a uma determinada view.

Listagem 3. A classe ContatoController.

package br.com.integrator.web;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.*;

import br.com.integrator.dao.ContatoDAO;

import br.com.integrator.Contato;

@Controller

@RequestMapping("/contato/**")

public class ContatoController {

@Autowired

private ContatoDAO contatoDao;

@RequestMapping(value = "/contato/{id}", method = RequestMethod.GET)

public String show(@PathVariable("id") Long id, ModelMap modelMap) {

modelMap.addAttribute("contato", contatoDao.find(id));

return "contato/show";

}

@RequestMapping(value = "/contato", method = RequestMethod.GET)

public String list(ModelMap modelMap) {

modelMap.addAttribute("contatos", contatoDao.findAll());

return "contato/list";

}

@RequestMapping(value = "/contato/{id}", method = RequestMethod.DELETE)

public String delete(@PathVariable("id") Long id) {

contatoDao.remove(contatoDao.find(id));

return "redirect:/contato";

}

@RequestMapping(value = "/contato/form", method = RequestMethod.GET)

public String form(ModelMap modelMap) {

modelMap.addAttribute("contato", new Contato());

return "contato/create";

}

@RequestMapping(value = "/contato", method = RequestMethod.POST)

public String create(@ModelAttribute("contato") Contato contato) {

contatoDao.persist(contato);

return "redirect:/contato";

}

@RequestMapping(value = "/contato/{id}/form", method = RequestMethod.GET)

public String updateForm(@PathVariable("id") Long id, ModelMap modelMap) {

modelMap.addAttribute("contato", contatoDao.find(id));

return "contato/update";

}

@RequestMapping(method = RequestMethod.PUT)

public String update(@ModelAttribute("contato") Contato contato) {

contatoDao.merge(contato);

return "redirect:/contato";

}

}

Introduzida na versão do Spring MVC 2.5, podemos declarar uma classe como sendo a controller do framework simplesmente utilizando a anotação @Controller, de org.springframework.stereotype.Controller. Esta anotação permite que o Spring faça seu “scan” automaticamente através do elemento <context:component-scan>.

Com a anotação @RequestMapping, encontrada após @Controller, definimos o caminho HTTP que será utilizado na aplicação, sendo mapeada pela classe. Na prática, todas as chamadas na aplicação contendo o “/contato/*” serão analisadas pela classe controller.

O suporte a RESTful foi completamente adicionado no Spring MVC 3, onde determinamos o seu comportamento através também da anotação @ResquestMapping. Agora, o servlet Spring Dispatcher suporta os seguintes métodos HTTP: GET, HEAD, POST, PUT e DELETE.

Para efeitos comparativos, se colocarmos cada um dos métodos HTTP ao lado de um simples aplicativo que executa as quatro operações básicas (CRUD), teríamos o GET como sendo o READ, o POST como CREATE, o PUT como UPDATE e o DELETE como por ele mesmo.

Infelizmente, os navegadores não compreendem nada além de GET e POST em formulários HTML. Ao declarar no formulário do Spring MVC que o método de submissão é o DELETE, por exemplo, este se transformará em um método POST, para que o navegador entenda, só que contendo um campo oculto com o valor DELETE. Infelizmente este feito não é mágico e no Spring MVC esta característica só é possível porque configuramos o filtro org.springframework.web.filter.HiddenHttpMethodFilter no arquivo web.xml(veja a Listagem 4).

Ao submeter o formulário, a anotação @ResquestMapping verifica o caminho e o método submetido. Imagine que @ResquestMapping recebe uma chamada HTTP com o caminho “/contato/1”, seria apenas uma visualização do contato número 1 se RequestMethod.DELETE não fosse acionado, disparando automaticamente o método delete(), que tem como objetivo remover o contato. Esta remoção é feita pelo remove() do DAO.

Através de templates URI, a anotação @PathVariable determina à variável que será recebida e transmitida para o método em questão. Se quisermos excluir um determinado contato, enviamos ao navegador o caminho “/contato/1”, mas que será traduzido como “contato?id=1”. Como parâmetro, a variável pode ser convertida para um determinado tipo em sua captura, assim como renomeada.

A conclusão de cada operação no controller pode ser feita através de um redirecionamento, enviando a string “redirect:/caminho” ou simplesmente retornando o caminho que deseja exibir.

A configuração do web.xml

O arquivo web.xml precisa de alguns ajustes, uma vez que este já possui configurações iniciais para trabalhar com o Spring MVC. A Listagem 4 exibe o arquivo web.xml na íntegra.

Listagem 4. O web.xml.

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

<web-app version="2.5" 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-app_2_5.xsd">

<display-name>SpringMVC</display-name>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<servlet>

<servlet-name>ContatoManager</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>ContatoManager</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>/static/*</url-pattern>

</servlet-mapping>

<!-- habilitar o suporte REST do Spring 3.0 -->

<filter>

<filter-name>httpMethodFilter</filter-name>

<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>

</filter>

<!-- Permite colocar um campo oculto para PUT e DELETE -->

<filter-mapping>

<filter-name>httpMethodFilter</filter-name>

<servlet-name>ContatoManager</servlet-name>

</filter-mapping>

<filter>

<filter-name>OpenEntityManagerInViewFilter</filter-name>

<filter-class>

org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter

</filter-class>

</filter>

<filter-mapping>

<filter-name>OpenEntityManagerInViewFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<session-config>

<session-timeout>10</session-timeout>

</session-config>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

Para o Spring MVC funcionar, utilizamos o servlet org.springframework.web.servlet.DispatcherServlet, configurado no arquivo web.xml da aplicação. Por padrão, o Spring olha beans em arquivos cujo começo possui o mesmo nome do Servlet configurado, seguido de -servlet.xml. Para melhor entendimento, o nome ContatoManager, dado no elemento <servlet-name/>, fará com que o Spring procure por um arquivo chamado ContatoManager-servlet.xml.

Evidentemente ele não é o único item que deve ser configurado no arquivo, já que, se pretendemos trabalhar com REST, como já foi citado anteriormente, precisamos adicionar o filtro pela classe org.springframework.web.filter.HiddenHttpMethodFilter.

Para trabalhar com a JPA, utilizamos o filtro org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter, do Spring. Entretanto, deixarei para falar sobre este filtro em outra ocasião.

O arquivo persistence.xml

A Listagem 5 mostra o arquivo persistence.xml, que configura como provider o Hibernate.  Este arquivo deve ser criado dentro do diretório META-INF. Este diretório será criado em src/main/Java. Veja como ficará em seu projeto através da Figura 20.

Figura 20 – Localização do arquivo persistence.xml dentro de META-INF

Figura 20 – Localização do arquivo persistence.xml dentro de META-INF

Listagem 5. Configuração do 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 name="ContatoPU" transaction-type="RESOURCE_LOCAL">

<provider>org.hibernate.ejb.HibernatePersistence</provider>

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

<properties>

<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/springmvc"></property>

<property name="javax.persistence.jdbc.user" value="edson"></property>

<property name="javax.persistence.jdbc.password" value="integrator"></property>

<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>

<property name="hibernate.show_sql" value="true" />

<property name="hibernate.format_sql" value="true" />

<property name="hibernate.hbm2ddl.auto" value="create"/>

</properties>

</persistence-unit>

</persistence>

Configurando o Spring

Revisando até o momento o que criamos, temos um DAO simples que se comunica com o banco de dados através da JPA, utilizando o Hibernate como provider.

Este DAO será executado pelo Controller do Spring MVC, também já configurado.

Para trabalhar com todas estas informações, dividiremos as configurações em dois arquivos, separando suas responsabilidades.

O primeiro arquivo, chamado de applicationContext.xml (Listagem 6), será o utilizado para a trabalhar com a injeção de dependências na classe DAO, lidando com as características da JPA. Este arquivo deve ser criado dentro do diretório WEB-INF.

Para criá-lo, cliquem com o direito do mouse em src/main/webapp/WEB-INF e selecionem New>Spring Bean Configuration File no menu de contexto.

Na caixa de diálogo Create a new Spring Bean Definition file coloque o nome do arquivo de applicationContext (Figura 21) e clique no botão Next.

Figura 21 – Criação do arquivo applicationContext.xml pelo assistente

Figura 21 – Criação do arquivo applicationContext.xml pelo assistente

Na segunda etapa, mantenha o beans – http://www.springframework.org/schema/beans e mantenha selecionado o item XSD como mostrado na Figura 22.

Figura 22 – Seleção do namespace beans

Figura 22 – Seleção do namespace beans

Ainda na segunda etapa, mantenha o context – http://www.springframework.org/schema/context e mantenha selecionado o item XSD como mostrado na Figura 23.

Figura 23 – Seleção do namespace context

Figura 23 – Seleção do namespace context

A última opção que selecionaremos na segunda etapa será o tx – http://www.springframework.org/schema/tx e mantenha selecionado o item XSD como mostrado na Figura 24. Confirmem no botão Finish.

Figura 24 – Seleção do namespace tx

Figura 24 – Seleção do namespace tx

Caso tenhamos esquecido de selecionar algum namespace, não tem importância, pois ao finalizar o assistente, o editor do arquivo de configuração do Spring se abre. Neste caso, vamos adicionar um último namespace. Cliquem na aba Namespaces e marquem o namespace mvc – http://www.springframework.org/schema/mvc e selecionem o XSD como mostrado na Figura 25.

Figura 25 – Seleção do namespace mvc

Figura 25 – Seleção do namespace mvc

O conteúdo completo do arquivo applicationContext.xml está na Listagem 6.

Listagem 6. Configuração do arquivo applicationContext.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:tx="http://www.springframework.org/schema/tx"

xmlns:mvc="http://www.springframework.org/schema/mvc"

xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

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

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

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

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property value="ContatoPU" />

</bean>

<context:component-scan base-package="br.com.integrator"/>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

<property name="entityManagerFactory" ref="entityManagerFactory"/>

</bean>

<mvc:annotation-driven/>

<tx:annotation-driven />

<context:annotation-config />

</beans>

No Spring MVC, para determinar a classe controladora, utilizamos a anotação @Controller. Entretanto, para que seja possível detectar esta anotação, o Spring utiliza o elemento <context:component-scan />, onde indicamos  o pacote em que ele pode verificar. Este recurso é chamado de Classpath scanning, que permite ao Spring ler as classes encontradas no pacote indicado da aplicação em busca das que estão anotadas. Isso evita que tenhamos de declarar estas classes no XML. Ao fazer este “scanning”, as classes são passadas por um filtro e então a definição de um bean é criada para cada uma delas. Evidentemente que este filtro é determinado pelas anotações, onde não existem apenas as anotações que utilizamos neste exemplo,  mas de outras mais que temos como referencia para o framework: @Component, @Service, @Controller e @Repository (que foi introduzida no Spring 2.0). Você pode também criar suas próprias anotações e filtros para declarar os componentes.

Para o Spring trabalhar com a JPA, onde a execução ocorre em ambientes Java EE, utilizamos a factory org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean:

<bean

class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property name="persistenceUnitName" value="ContatoPU" />

</bean>

Com a propriedade de LocalContainerEntityManagerFactoryBean especificamos o nome  da persistence unit do arquivo persistence.xml. É neste arquivo que temos as configurações de acesso ao banco de dados pela JPA para realizar as operações de persistência.

Para a configuração do controle transacional em uma aplicação baseada no Spring, é necessário declarar um gerenciador que, neste caso, será a classe org.springframework.orm.jpa.JpaTransactionManager. Esta classe é utilizada para trabalhar com a JPA, independente de provedor ORM. A declaração da classe é ilustrada no trecho a seguir:

<bean

class="org.springframework.orm.jpa.JpaTransactionManager">

<property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

JpaTransactionManager precisa de qualquer implementação de javax.persistence.EntityManagerFactory para colaborar com EntityManager produzido pela fabrica, para conduzir transações. A classe JpaTransactionManager é recomendada para aplicações que utilizam apenas uma EntityManager.

Para que não tenhamos que fazer injeção de dependência do EntityManager em todos os nossos DAOs, utilizamos o elemento <context:annotation-config />, que procura todas as classes anotadas com @PersistenceContext, @Autowired (que veremos mais adiante), entre outros, e faz a injeção de dependência automaticamente.

Por termos configurado as transações no DAO, por meio da utilização da anotação @Transactional, o elemento <tx:annotation-driven> foi utilizado.

Como se não bastasse, temos também a parte do Spring MVC, que utiliza o elemento mvc:annotation-driven />, permitindo enviar as requisições das classes que possuem a anotação @Controller.

Configurando o Spring MVC

O segundo arquivo, com o nome de ContatoManager-servlet.xml (Listagem 7), será o responsável por configurar o caminho das views e a tecnologia empregada no projeto do Spring MVC.

Para criá-lo, cliquem com o direito do mouse sobre o diretório src/main/webapp/WEB-INF e selecionem New>Spring Bean Configuration File no menu de contexto.

Na caixa de diálogo Create a new Spring Bean Definition file coloquem o nome do arquivo de ContatoManager-servlet (Figura 26) e clique no botão Next.

Figura 26 – Criação do arquivo ContatoManager-servlet.xml pelo assistente

Figura 26 – Criação do arquivo ContatoManager-servlet.xml pelo assistente

Na segunda etapa, mantenham apenas o item beans – http://www.springframework.org/schema/beans selecionado como mostrado na Figura 27. Finalizem o assistente pelo botão Finish.

Figura 27 – Seleção do namespace beans

Figura 27 – Seleção do namespace beans

A Listagem 7 exibe, na íntegra, o conteúdo do arquivo ContatoManager-servlet.xml.

Listagem 7. Configuração do arquivo ContatoManager-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"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<property value="/WEB-INF/jsp/"/>

<property value=".jsp"/>

</bean>

</beans>

O Spring MVC possui um suporte a inúmeros tipos de views, utilizando diversos tipos de tecnologias, como JSP, FreeMarker, JasperReports, Velocity, XML, XSLT e outros. Quando vamos criar um projeto Spring MVC, podemos utilizar uma ou diversas ao mesmo tempo, o que significa que é possível apresentar uma página em HTML gerada pelo JSP contendo os dados vindos do banco de dados através do uso do Spring MVC e também um XML contendo os mesmos dados, com uma pequena alteração de extensão no navegador.

Com a classe org.springframework.web.servlet.view.InternalResourceViewResolver pré-fixamos o caminho das páginas em “/WEB-INF/jsp/” e damos o sufixo, sendo “.jsp”. Para o conteúdo das páginas, temos InternalResourceViewResolver, uma subclasse de UrlBasedViewResolver, que suporta JSTL, onde utilizaremos em nossas views.

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

As views

Criaremos agora três páginas que representarão nosso CRUD. Estas páginas serão criadas dentro de um diretório chamado contato, que ficará dentro de jsp em WEB-INF. Os diretórios jsp e contato ainda não foram criados. Para criá-los, clique com o direito do mouse sobre src/main/webapp/WEB-INF e selecione New>Folder no menu  de contexto.

Figura 28 -  Os diretórios jsp e contato criados dentro de WEB-INF do projeto

Figura 28 – Os diretórios jsp e contato criados dentro de WEB-INF do projeto

O formulário de cadastro

Se preferir, mude a perspectiva do Eclipse para Java EE, assim será possível clicar com o direito do mouse sobre o diretório e selecionar, no menu de contexto, o item New>JSP File. O assistente de criação de páginas JSP pode lhe ajudar com um template Basico. Por fim, dê o nome de create.jsp no arquivo e coloque o conteúdo similar ao mostrado na Listagem 8.

Listagem 8. A página create.jsp.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<style type="text/css" media="screen">

@import url("<c:url value="/static/styles/style.css"/>");

</style>

<title>Cadastrar</title>

</head>

<body>

<div id="wrap">

<div>

<%@ include file="/menu.jsp" %>

</div>

<div>

<div>

<c:url var="url" value="/contato" />

<form:form action="${url}" method="POST" modelAttribute="contato">

<div>

<label for="nome">Nome:</label>

<form:input cssStyle="width:250px" maxlength="30" path="nome" size="30"/>

</div>

<br/>

<div>

<label for="email">Email:</label>

<form:input cssStyle="width:250px" maxlength="30" path="email" size="30"/>

</div>

<br/>

<div>

<label for="telefone">Telefone:</label>

<form:input cssStyle="width:250px" maxlength="30" path="telefone" size="20"/>

</div>

<br/>

<div class="submit">

<input value="Criar Contato"/>

</div>

</form:form>

</div>

</div>

</div>

</body>

</html>

Podemos ter uma idéia de como ficará a página create.jsp através da Figura 29.

Figura 29 – A página create.jsp

Figura 29 – A página create.jsp

Analisando o web.xml, veremos o elemento <servlet-mapping/>, que define onde a aplicação encontrará os conteúdos estáticos do aplicativo. O Servlet default, utilizando neste caso, pertence as configurações padrão do Tomcat, responsável por servir conteúdos estáticos de aplicações web. Mesmo que seus arquivos não estejam em um diretório com este nome, é necessário acrescentá-lo como parte do caminho. Isso inclui imagens e folhas de estilo[1].

Para criar estas páginas, utilizamos tags da biblioteca JSTL e tags do próprio Spring. No caso do Spring, as tags <form/> possibilitam que tenhamos um formulário ligado ao controller. Para utilizar estas tags, devemos acrescentar a seguinte taglib:

<%@ taglib prefix=”form” uri=”http://www.springframework.org/tags/form” %>

Na construção dos formulários para inserir e atualizar, utilizamos a tag <form:form/> que possui um atributo modelAttribute,  ligando o formulário ao parâmetro do método que executa sua ação. O atributo method indica qual o tipo de ação será feita no controller.

A tag <form:input/> possui o atributo path com o valor correspondente aos atributos existentes no bean Contato.

A página que lista todos os cadastros e permite a exclusão

Para a listagem de todos os cadastros efetuados, criaremos uma página chamada list.jsp, contendo as mesmas informações existentes na Listagem 9.

Junto a listagem, teremos a possibilidade de excluir o cadastro diretamente por esta página.

Figura 30 – A página list.jsp

Figura 30 – A página list.jsp

Listagem 9. A página list.jsp.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<style media="screen">

@import url("<c:url value="/static/styles/style.css"/>");

</style>

<title>Listar</title>

</head>

<body>

<div>

<div id="menu">

<%@ include file="/menu.jsp" %>

</div>

<div id="main">

<div>

<c:if test="${not empty contatos}">

<table width="600px">

<tr>

<thead>

<th>Id</th>

<th>Nome</th>

<th>E-mail</th>

<th>Telefone</th>

<th>Atualizar</th>

<th>Excluir</th>

</thead>

</tr>

<c:forEach items="${contatos}" var="contato">

<c:url var="url" value="/contato/${contato.id}" />

<tr>

<td>${contato.id}</td>

<td>${contato.nome}</td>

<td>${contato.email}</td>

<td>${contato.telefone}</td>

<td>

<form:form action="${url}/form" method="GET">

<input alt="Atualizar Contato" src="<c:url value="/static/images/update.png"/>" title="Atualizar Contato" value="Atualizar Contato"/>

</form:form>

</td>

<td>

<form:form action="${url}" method="DELETE">

<input alt="Excluir Contato" src="<c:url value="/static/images/delete.png"/>" title="Excluir Contato" value="Excluir Contato"/>

</form:form>

</td>

</tr>

</c:forEach>

</table>

</c:if>

<c:if test="${empty contatos}">Não há contatos cadastrados.</c:if>

</div>

</div>

</div>

</body>

</html>

O Spring MVC gera um Map através de sua classe org.springframework.ui.ModelMap, onde capturamos os valores retornados pelo método findAll(), de ContatoDAO. Este Map é capturado pela view, no clássico esquema definido pelo MVC.

No caso da listagem de contatos, este Map, definido como contatos no método list(), de ContatoController, é varrido por um loop criado pela tag JSTL <c:forEach /> no seguinte trecho:

<c:forEach items=”${contatos}” var=”post”>

Na listagem dos contatos, em uma das tags <form:form/>, vemos em um de seus atributos method o valor DELETE, definido como a ação de exclusão de contatos.

Como os navegadores não reconhecem o envio de formulários além dos métodos POST e GET, precisamos de uma ajuda do Spring Framework para fazer a operação DELETE. O que o Spring MVC fará é traduzir o valor do atributo desta tag, na geração do HTML, da seguinte forma:

<form … method=”post”>

<input type=”hidden” value=”DELETE”/>

Observe que ele criou uma tag oculta HTML na renderização da página com um nome _method e com o valor DELETE. Esta simples adição permitirá a ação de excluir pela classe PostController.

A página de atualização de dados

A última página que teremos no CRUD é a de atualizar (update.jsp), similar ao de adicionar dados, exceto pelo fato de receber os dados vindos do banco de dados para serem exibidos.

Listagem 10. A página update.jsp.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<style type="text/css" media="screen">

@import url("<c:url value="/static/styles/style.css"/>");

</style>

<title>Atualizar</title>

</head>

<body>

<div id="wrap">

<div>

<%@ include file="/menu.jsp" %>

</div>

<div>

<div>

<c:url var="url" value="/contato/${contato.id}" />

<form:form action="${url}" method="PUT" modelAttribute="contato">

<div>

<label for="nome">Nome:</label>

<form:input cssStyle="width:250px" maxlength="30" path="nome" size="30"/>

</div>

<br/>

<div>

<label for="email">Email:</label>

<form:input cssStyle="width:250px" maxlength="30" path="email" size="30"/>

</div>

<br/>

<div>

<label for="telefone">Telefone:</label>

<form:input cssStyle="width:250px" maxlength="30" path="telefone" size="20"/>

</div>

<br/>

<div class="submit">

<input value="Atualizar Contato"/>

</div>

<form:hidden path="id"/>

</form:form>

</div>

</div>

</div>

</body>

</html>

Similar ao que ocorre com a listagem de contatos, temos no formulário da página de atualização o valor PUT para o atributo method. Novamente, o Spring Framework irá gerar um campo oculto, em HTML, contendo esta informação e transmitindo ao navegador o HTML como ele já o conhece.

Figura 31  - A página update.jsp

Figura 31 – A página update.jsp

As páginas que não fazem parte do CRUD

O menu e a página inicial não fazem parte do CRUD e, portanto, serão apenas apresentadas aqui com seus códigos para completar o exemplo.

A página index.jsp deverá ser criada em  webapps:

Listagem 11. A página index.jsp.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<link href="<c:url value="/static/styles/style.css"/>" rel="stylesheet" />

<title>Principal</title>

</head>

<body>

<div id="wrap">

<div>

<%@ include file="/menu.jsp" %>

</div>

<div>

<div>

Aplicação CRUD criada utilizando o Spring MVC 3.0 com suporte a REST.

</div>

</div>

</div>

</body>

</html>

Assim como index.jsp, crie o menu.jsp em webapps.

Listagem 12. A página menu.jsp.

<ul>

<li>

<h2>Contato</h2>

<ul>

<li><a href="<c:url value="/contato"/>">Ver todos</a></li>

<li><a href="<c:url value="/contato/form"/>">Novo Contato</a></li>

</ul>

</li>

</ul>
Figura 32 – Visão geral de todos os arquivos utilizados na geração do projeto

Figura 32 – Visão geral de todos os arquivos utilizados na geração do projeto

O projeto para download

Clique aqui para baixar o projeto completo como feito até o momento.

Considerações finais

Agora que aprendemos a fazer um CRUD com o Spring MVC, podemos criar projetos mais complexos. Caso estejam com pressa em aprender algo mais complexo, a revista JavaMagazine #78 publicou, alguns meses atrás, um artigo meu com o Spring MVC 3 na criação de um blog, passo a passo.

No próximo artigo

Faremos alterações neste projeto, criando as verificações utilizando Bean Validation e depois trabalhando com testes.

Até o próximo artigo pessoALL.


[1] Imagens e folhas de estilo foram omitidos neste artigo, mas podem ser obtidos no projeto completo encontrado no final para download

Tags: , , , , , ,


ago 12 2010

Guia de Certificação SCJP

Category: CertificaçõesEdson Gonçalves @ 1:07

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

O artigo que veremos a seguir foi escrito pelo jovem autor Camilo Lopes, falando a respeito de seu livro Guia do Exame SCJP e também de seu simulado para o exame SCJP.
Dúvidas e críticas são sempre bem vindas.

A Certificação SCJP

É muito comum que os candidatos para SCJP tenham dúvidas referentes a qual material devam adquirir para ser um SCJP 5/6.

Neste post vou falar um pouco sobre o livro Guia do Exame SCJP(não à nível comercial) e como o candidato deve se preparar para o exame. O objetivo maior do post é deixar o futuro SCJP ciente de quais referências ele deve ter em mãos, mantendo o custo x benefício.

Antes de comprar qualquer material de estudo ou até fazer uma matricula na escola mais próxima de sua casa, o candidato deve ter um objetivo: por que ele quer  ser certificado? Qual ou quais o(s) objetivo(s) que este tem para sua carreira à curto/médio prazo? Não queira pensar à longo prazo, algo em torno de 10 anos, mas em um tempo mais próximo e que consiga realizar. Por exemplo:

  1. Há pessoas que tiram certificações para encantar os headhunters (nem sempre funciona).

  2. Outros obtém a certificação para testar o próprio conhecimento na tecnologia ou área especifica.

  3. Alguns para buscar um diferencial em uma vaga de emprego; porém este tem sólidos conhecimentos tanto práticos quanto teóricos.  Enquadrados nesta opção estão muitos estudantes recém-formados sem experiência, que conseguiram a primeira oportunidade de trabalhar na área devido à uma certificação.

Olha o que a Kathy, fala a respeito do porque de obter uma certificação:

Passar no exame provará três itens importantes para o empregador atual ou futuro: Que você sabe das coisas; que sabe como estudar e se preparar para um teste desafiador; e acima de tudo, que conhece a tecnologia e está de acordo com os objetivo cobrados para tal exame. Se um empregador tiver que optar entre um candidato que passou no exame e outro que não tenha passado, ele saberá que o programador certificado não demorará no aprendizado.”

Aonde eu quero chegar?

Quero chegar que não importa se você tem um livro que foi escrito por um dos desenvolvedores do exame, fabricante da tecnologia ou qualquer outro. Se você não tem um objetivo, não adianta ter a melhor ferramenta.

E o livro Guia SCJP? Para o que,  de fato, ele apóia o candidato? Acho tão parecido com o livro oficial da Kathy.

Essa é uma pergunta bem comum de alguns futuros candidatos a certificados SCJP. O livro pode parecer que é mais um que foi publicado para concorrer com o livro oficial, mas não é verdade, ele veio para completar os seus estudos após a leitura do oficial, uma vez que o candidato já fez os exercícios e está cansado daquele material, precisando de um novo que lhe ajude revisar os pontos chaves do exame, mostrando as possíveis pegadinhas, com explicações dentro do código Java ajudando a fixar e compreender a teoria com a pratica, apresentando exemplos de todo tipo: compila, não compila, com exceções especificas, genéricas e etc. Enfim, o guia trabalha em cima dos detalhes que você, futuro SCJP, não pode pensar em esquecer no dia do exame.

Mas, para qual versão do exame o livro é mais adequado?

Para os dois: SCJP 5 e 6. Entretanto, o livro não aborda as particularidades que foram adicionadas no exame 6, pois essas não correspondem nem a 20% do total das questões. O objetivo do Guia é literalmente guia-lo para os pontos críticos e que tem mais “peso” na certificação, que são os assuntos como: Threads, Orientação à objetos, Exceções, fundamentos Java, etc. E todos esses assuntos estão presentes nos dois exames.

O Guia

Guia do Exame SCJP

O guia foi criado baseado em algumas dificuldades que o autor encontrou na época em que se preparava para certificação. Uma delas era ter um material que pudesse ler nas pequenas horas livres, tais como:

  • intervalo da faculdade;
  • Sala de espera;
  • Metrô, ônibus;
  • esperando a namorada trocar de roupa;
  • não estava com paciência de ler os capítulos longos do livro oficial;
  • etc.

Foi a partir dessas necessidades que nasceu o Guia. Este guia não tem o objetivo de ensinar a tecnologia Java de modo prático. Não espere aprender à criar aplicações Java, criar conexões com o Banco de dados ou algo semelhante. Este livro é focado no exame, querendo deixar o candidato mais seguro e atento as armadilhas que estão na SCJP. Foram meses de pesquisas com mais de 400 classes compiladas e inúmeros testes. A “fecundação” do Guia iniciou em 2007, porém somente em meados de 2009 que a “criança” começou a criar seu formato para ser publicado em 2010. Antes disso, foram horas e meses de trabalho para que se pudesse ter de fato um guia focado no exame e não apenas mais um livro repetindo levemente o que há em outros.

O Guia acompanha um simulado(beta) exclusivo para os leitores testarem  o conhecimento. E uma das vantagens do simulado é que há questões em português e inglês, sem falar nas questões que possuem um temporizador para responder, o que ajuda o candidato a obter a disciplina em saber que ele não tem todo o tempo do mundo para responder uma questão. No exame, o candidato precisa ser rápido e eficiente, ou seja, ter conteúdo suficiente para “matar” uma questão no menor tempo possível.

Simulado Gratuito

O autor lançou um simulado inteiramente grátis para a comunidade, o chamado SimSCJP Beta, que possui algumas questões para que o interessado possa conhecer o seu trabalho e “brincar” um pouco com o seu conhecimento. Para aqueles que desejam uma versão completa, o autor oferece o Premium Beta, com mais simulados. Os interessados na versão Premium Beta, podem obter estes simulados por um valor simbólico R$ 19,90 (boleto/ cartão crédito).

Nota do Edson Gonçalves: Em se tratando de simulados para exame, é talvez o mais barato e bem elaborado já lançado até o momento para o preparo da certificação SCJP.

Onde adquirir o livro?

Você pode adquirir o livro no site da editora www.lcm.com.br, com 30% de desconto, bastando informar o código V00014, através de qualquer uma das grandes livrarias espalhadas pelo Brasil ou em lojas virtuais como Fnac, Saraiva e etc.

Quanto custa?

O autor teve uma grande preocupação neste quesito, onde queria um livro que todos pudessem comprar sem apertar o orçamento. Em parceria com a editora, isso foi possível e o valor sem desconto é de R$ 49,00. Existem livrarias que parcelam em até 2x, outras que oferecem com frete grátis.

Vou ficando por aqui, espero que tenham gostado do post e qualquer dúvida é só perguntar.

O Autor

Camilo Lopes profissional trabalha com Tecnologia de Informação desde 2003, possui experiência em desenvolvimento de sistemas Web. Conhecimento em servidores de aplicações, banco de dados e linguagens de programação. Programador certificado pela Sun Microsystems SCJP 5. Possui Experiência em treinamento corporativos na área de TI aos usuários. Bacharelado em Análise de Sistemas, Pós-Graduando em Gestão Estratégia de Negócios. Atualmente trabalha na IBM/Brazil onde atua como Analista Programador/Specialist IT em projetos Internacionais. Vem atuando como Consultor TI orientando pequenas e médias empresas como aprimorar e ampliar seus negócios usando TI. Nas horas livres  gosta de escrever livros e artigos técnicos para editora Ciência ModernaRevista Java Magazine.

Alguns trabalhos:

  • Colunista Java desde 2008, tem uma série de artigos Java, BD, JEE, Certificação etc.

Tags: , , ,


« Página anteriorPróxima página »