Adendo - Spring Framework (2.5)
Framework para
Desenvolvimento de Aplicações
em Java
Diego Pacheco
Set/2009
Apostila desenvolvida especialmente para a Crom Microsystems.
Sua cópia ou reprodução é livre.
Sobre o Autor
Diego Pacheco
Técnico em Processamento de Dados e graduando em Ciências da Computação (7º sem.)
na Ulbra. Já trabalhou com desenvolvimento de software em VB, ASP, .NET e PHP.
Atualmente é Arquiteto de Software, certificado pela Sun, atua desenvolvendo soluções
corporativas em arquitetura JEE, provendo coaching/mentoring em software e processo
de desenvolvimento de software. Gosta muito de música, tocar guitarra, jogar PSP,
Bloggar, Ler - principalmente as incríveis histórias do Conan -. Mantem o blog <
http://diego-pacheco.blogspot.com/> a mais de 3 anos.
Spring Framework – Framework para Desenvolvimento de Aplicações Java
Diego Pacheco – http://diego-pacheco.blogspot.com I
Sumário
Sobre o Autor .................................................................................................................................. 3
6. Anotações e Web .............................................................................................................. 1
Objetivos ...................................................................................................................................... 2
Anotações no Java .................................................................................................................. 3
Anotações no Spring Framework .................................................................................... 7
Anotações para injeção ........................................................................................................ 9
Testes Unitários com TestNG ........................................................................................... 14
Integração com JSF ............................................................................................................... 18
Expondo os seus beans via JMX ................................................................................... 29
Espaço para anotações ....................................................................................................... 33
Spring Framework – Framework para Desenvolvimento de Aplicações Java
Diego Pacheco – http://diego-pacheco.blogspot.com
66.. AAnnoottaaççõõeess ee WWeebb
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 2
Objetivos
• Conhecer os recursos básicos de anotações do Spring Framework;
• Saber construir testes unitários utilizando TestNG com anotações e Spring
Framework.
• Saber como integrar o Spring Framework a uma aplicação Web com JSF.
• Saber como expor um bean do Spring como um JMX.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 3
Anotações no Java
Com o lançamento da versão 5 do Java, ganhamos um poderoso recurso, as
anotações. Antes do Java 5 a comunidade já tinha inventado algumas maneiras de
trabalhar com metadados, isto era feito com o Xdoclet e outras soluções similares,
mas a abordagem tinha alguns problemas.
Dentre os diversos problemas, destaco a propenção a erros, pois o recurso nada
mais era do que algumas tags em um bloco de documentação do Javadoc. Além
disso, a documentação ficava misturada com metadados e sempre era necessário
executar uma task ant para realizar a leitura das informações e aplicar o
processamento necessário.
Agora com as anotações é possivel ter estes recursos de forma nativa e com muito
mais beneficios, porque este recurso já vem com o Java e o compilador do Java - o
Javac - verifica sintática e semânticamente a validade das anotações.
Quando trabalhamos com anotações podemos definir em que tempo do programa
vamos utilizar este recurso, os valores possíveis são definidos pela enumeração
java.lang.annotation.RetentionPolicy conforme segue a baixo:
• SOURCE
• CLASS
• RUNTIME
A retenção do tipo SOURCE é descartada pelo compilador, ou seja, só é valida em
tempo de design. A retenção do tipo CLASS é a padrão, o compilador marca na
classe mas a JVM não mantem essa informação acessível em tempo de runtime. Se
você deseja acessar a anotação em tempo de runtime, precisa utilizar a retenção do
tipo RUNTIME e com isso você pode acessar o elemento anotado via reflection.
Além das informação sobre o tipo de retenção das anotações, quando criamos este
tipo de recurso ainda precisamos especificar qual é o alvo da anotação, ou seja, em
que tipo de elemento ela vai estar atuando. Os elementos suportados são definidos
pela enumeração java.lang.annotation.ElementType, que segue abaixo:
• TYPE
• FIELD
• METHOD
• PARAMETER
• CONSTRUCTOR
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 4
• LOCAL_VARIABLE
• ANNOTATION_TYPE
• PACKAGE
Os recursos mais utilizados em termos de elementos são para interfaces e classes
através do TYPE, para métodos o elemento METHOD e para anotar pacotes o
PACKAGE.
As anotações são úteis para diversos motivos, pois conseguimos definir um modelo
de metaprogramação de forma fácil e verificável. Confira um exemplo de utilização
de anotações abaixo.
package com.blogspot.diegopacheco.springframework25.annotations.java;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Anotação que infica que um campo de uma classe nada pode ser nulo ou vazio. <br>
* Logo você é obrigado a informar um valor ao campo que for anotado com esta anotação.
*
* @author Diego Pacheco
* @version 1.0
* @since 26/09/2009
*
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CampoObrigatorio {
}
Código 6.1 CampoObrigatorio.Java – Anotação do Java 5
O código acima se refere a uma anotação, repare que para criar uma anotação foi
utilizado mais 3 anotaões, duas você já conhece, são referentes a política de
retenção e ao tipo de elemento anotadado.
A anotação @Documented indica que esta anotação possui Javadoc. Repare
também que para criar a anotação foi utilizado o @interface, isto é o que indica que
é uma anotação para o compilador do Java.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 5
Agora vamos colocar esta anotação em um objeto, confira o código abaixo:
package com.blogspot.diegopacheco.springframework25.annotations.java;
public class Pessoa {
@CampoObrigatorio
private Integer id;
private String nome;
public Pessoa() { }
public Pessoa(Integer id, String nome) {
super();
this.id = id;
this.nome = nome;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
@Override
public String toString() {
return "id: " + id + ",Nome: " + nome;
}
}
Código 6.2 Pessoa.Java – Pojo com anotação
Repare que este é um pojo normal com dois atributos, sendo um nome do tipo
String e um id do tipo Integer, além dos construtores vazio e full e seus métodos
getters e setters.
Perceba que o campo id está anotado, a anotação criada acima chamada
@CampoObrigatório, agora vamos ao código que processa a anotação e manipula
as informações da mesma, confira o código abaixo:
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 6
package com.blogspot.diegopacheco.springframework25.annotations.java;
import java.lang.reflect.Field;
public class TestaAnotacaoMain {
public static void main(String[] args) {
Pessoa p = new Pessoa();
p.setNome("Diego Pacheco");
try{
validate(p);
System.out.println("Objeto válido!");
}catch(Exception e){
System.out.println("Objeto inválido!");
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public static void validate(Pessoa p) throws Exception {
Class<Pessoa> clazz = (Class<Pessoa>) p.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(CampoObrigatorio.class))
{
field.setAccessible(true);
if (field.get(p) == null){
throw new RuntimeException("O campo
obrigatório não foi informado. Objeto inválido! ");
}
}
}
}
}
Código 6.3 TestaAnotacaoMain.Java – Pojo com anotação
No código acima, o objeto Pessoa é instânciado para a memória e apenas a
propriedade nome é informada, perceba que o id não é informado em momento
algum no código a cima.
O método validate processa a validação do objeto Pessoa utilizando a API de
reflecation do Java e é verificado se o campo anotado com a anotação
@CampoObrigatorio tem valor, caso ele seja nulo uma exception é levantada
informando este erro.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 7
Anotações no Spring Framework
O Spring é conhecido pela utilização de arquivos xml para configuração de
injeção de dependências (DI) e bem como inversão de controle (IoC), utilizar xml é
bom porque possibilita ao desenvolvedor ter em um único lugar todas as
configurações de injeções do seu sistema, além de ser mais extensivél, porque
podemos modificar o comportamento da aplicação sem abrir o código e sem ter
que recompilar o código.
Porém a utilização de xml tem desvantagens, como por exemplo, ser mais propença
a erros de digitação e de configuração, além de ser menos produtivo do que as
anotações, as anotações dão muito mais produtividade e simplicidade para o
desenvolvedor.
Apartir do Spring Framework 2.5 várias anotações ficaram disponíveis para facilitar o
trabalho e prover um leque de opções maior do que existia nas outras versões da
solução. Esta versão do Spring implementa a JSR-250 que é sobre anotações padrão
do Java como @Resource, @PostConstruct, and @PreDestroy.
Confira o código abaixo:
package com.blogspot.diegopacheco.springframework25.annotations.spring;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class AnotacoesJava {
@PostConstruct
public void init(){
System.out.println("Código de inicialização...");
}
@PreDestroy
public void shutdown(){
System.out.println("Código de shutdown...");
}
}
Código 6.4 AnotacoesJava.Java – Classe que usa anotações padrão
Como você pode reparar a classe acima está utilizado duas anotações padrão do
Java @PostConstruct, and @PreDestroy que serão executadas pelo spring depois de
contruir o objeto e antes de destruir o mesmo.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 8
Para ativar este recurso no spring é necessário registrar um bean post processor
padrão, confira esta configuração no código abaixo.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-
2.5.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.blogspot.diegopacheco"/>
</beans>
Código 6.5 spring-annotation-beans.xml – XML de configuração
Existem 3 pontos importantes neste xml, o primeiro é a utilização do schema xsd
chamado de context, é através dele que realizamos configurações no contexto do
spring. O segundo ponto é a utilização da entrada annotation-config, isto registra
os bean post processors do spring para tratamento de anotações. Por fim o terceito
ponto é a utilização de component-scan que indica um pacote base, logo o spring
vai varrer todos os subpacotes a procura de outros beans que estejam anotados.
Vamos ver o código para testar a utilização de anotações com o Spring Framework
2.5, confira o código abaixo:
package com.blogspot.diegopacheco.springframework25.annotations.spring;
import org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestaAnotacoesJava {
public static void main(String[] args) {
AbstractApplicationContext ctx = new
ClassPathXmlApplicationContext("classpath:spring-annotation*.xml");
ctx.getBean("anotacoesJava");
ctx.registerShutdownHook();
}
}
Código 6.6 TestaAnotacoesJava – Classe para testes
Neste código foi instânciado o contexto do spring e obtido o bean anotado e
depois o contexto foi derrubado com o registerShutdownHook().
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 9
O Spring vai procurar beans com as seguintes anotações
• @Component
• @Service
• @Repository
• @Controller
Caso ele encontre algum bean com alguma destas anotações, ele vai registrar o
bean no contexto, o nome do bean vai ser definido da seguinte forma: Supondo
que a classe se chama PessoaFisicaService o bean ter o mesmo nome só que com a
primeira letra não captalizada, ou seja: pessoaFisicaService.
A anotação @Component é a mais genérica do Spring, ela serve para indicar que é
um bean gerenciado pelo Spring, você utiliza isso em qualquer bean de propósito
geral.
As outras anotações são mais específicas, elas indicam um serviço @Service, um
objeto de controle (arquitetura MVC) @Controller e um objeto de acesso a dados,
vulgo DAO com @Repository.
Quando você utiliza @Service, @Component ou @Controller ainda não tem uma
diferença prática, mas o spring pretende utilizar isso como informações para
aspéctos em futuras implementações.
Quanto a anotação @Repository, você já ganha o recurso de tradução de
exceptions automaticamente, logo, não vai ter que lidar com exceptions específicas
como as de lock otimista do JPA.
Anotações para injeção
O Spring também prove anotações para injeção de beans. Para isso estão
disponíveis as anotações:
• @Resource
• @Autowired
A anotação @Resource faz a injeção baseado nos nomes dos beans e a anotação
@Autowired faz baseada em tipos. Se você não trabalha com interfaces ou tem só
uma implementação, pode usar @Autowired sem problemas, mas a sua aplicação
pode crescer e com isso podem vir vários erros de injeção.
Para resolver este problema precisamos qualificar a injeção utilizando a anotação
@Qualifier indicando o identificador do bean que você quer.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 10
Confira o código abaixo para ver a utilização destas anotações em prática.
package com.blogspot.diegopacheco.springframework25.annotations.spring;
import org.springframework.stereotype.Component;
@Component
public class Livro {
private String isbn;
private String titulo;
public Livro() {
isbn = "10ergregKL2";
titulo = "O código de Da vince";
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
}
@Override
public String toString() {
return "[livro={isbn: " + isbn + ",titulo: " + titulo + "}]";
}
}
Código 6.7 Livro.java – Pojo Livro
Este é um pojo simples, que foi anotado com a anotação @Component do spring
framework 2.5, agora vamos ao bean autor, neste bean vamos injetar o código do
livro que está acima.
package com.blogspot.diegopacheco.springframework25.annotations.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component()
public class Autor {
private Integer id;
private String nome;
@Autowired
private Livro livro;
public Autor() {
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 11
id=0;
nome="Sem nome";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Livro getLivro() {
return livro;
}
public void setLivro(Livro livro) {
this.livro = livro;
}
@Override
public String toString() {
return "id: " + id + ",Nome: " + nome + ", Livro: " + livro;
}
}
Código 6.8 Autor.java – Pojo Livro
Como você pode perceber, foi utilziado a anotação @Autowired, para realizar a
injeção, neste caso também poderíamos utilizar a anotação @Resource. Vamos ao
código que sobe o contexto do Spring e por fim ao teste desta aplicação.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-
2.5.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.blogspot.diegopacheco"/>
</beans>
Código 6.9 spring-annotation-beans.xml xml de configuração
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 12
package com.blogspot.diegopacheco.springframework25.annotations.spring;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestaInjecaoAnotacoes {
public static void main(String[] args) {
ApplicationContext ac = new
ClassPathXmlApplicationContext("classpath:spring-annotation*.xml");
Autor a =(Autor)ac.getBean("autor");
System.out.println(a);
}
}
Código 6.10 TestaInjecaoAnotacoes.java – Clase de testes
Você já deve ter reparado que esta abordagem tem todas as vantagens que
descrevi no início deste capítulo, mas ainda tem mais uma desvantagem, nós não
conseguimos definir vários beans com a mesma classe e com dados diferentes,
neste sentido a abordagem de xml é mais vantajosa.
Nós poderiamos deixar alguma injeção obrigatória e caso você não faça isso o
spring irá levantar uma exception. Para isso vamos utilizar a anotação @Required,
confira o código abaixo modificado do exemplo anterior.
package com.blogspot.diegopacheco.springframework25.annotations.spring;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.stereotype.Component;
@Component
public class Livro {
private String isbn;
private String titulo;
public Livro() {
isbn = "10ergregKL2";
titulo = "O código de Da vince";
}
public String getIsbn() {
return isbn;
}
@Required
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) {
this.titulo = titulo;
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 13
}
@Override
public String toString() {
return "[livro={isbn: " + isbn + ",titulo: " + titulo + "}]";
}
}
Código 6.11 Livro.java – Anotado
Perceba que a classe livro agora tem a anotação @Required no setter da
propriedade ISBN, logo, se você não injetar um valor, o spring vai levantar uma
exception e o contexto não irá subir.
O spring permite mesclarar informações de anotações com XML, confira a
configuração abaixo para injeção deste atributo obrigatório.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-
2.5.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.blogspot.diegopacheco"/>
<bean id="livro"
class="com.blogspot.diegopacheco.springframework25.annotations.spring.Liv
ro"
>
<property name="isbn" value="1000ISBN12" />
</bean>
</beans>
Código 6.12 spring-annotation-beans.xml xml de configuração
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 14
Testes Unitários com TestNG
Nos capitulos anteriores você aprendeu a integrar o Spring Framework com o
Junit, bem como utilizar as suas facilidades para testes unitários. Neste capítulo
você vai ver como utilizar o TestNG através de anotações tanto do TestNG como do
próprio Spring Framework.
Desenvolver aplicações utilizando os bons modelos de design como programação
para interfaces, baixo acoplamento e alta coesão, extensibilidade, di, ioc, através do
Spring framework nos trazem um benefício muito importante, um código que é
testável.
O Spring prove injeção para testes de forma diferenciada da injeção para a sua
aplicação utiliza este recurso. Vamos ver como utilizar alguns recursos de testes
unitários do Spring com anotações, confira o código abaixo:
package com.blogspot.diegopacheco.springframework25.testng;
public interface Calculadora {
public void dividir(Double va, Double vb, ResultadoCallback
callback);
}
Código 6.13 Calculadora.java – Interface de Contrato da Calculadora
package com.blogspot.diegopacheco.springframework25.testng;
public interface ResultadoCallback {
public void processar(Double resultado);
}
Código 6.14 ResultadoCallback.java – Interface de Callback
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 15
package com.blogspot.diegopacheco.springframework25.testng;
import org.springframework.stereotype.Service;
@Service
public class CalculadoraAsync implements Calculadora {
@Override
public void dividir(final Double va, final Double vb,
final
ResultadoCallback callback) {
new Runnable(){
public void run() {
callback.processar(va/vb);
}
}.run();
}
}
Código 6.15 ResultadoCallback.java – Interface de Callback
A classe acima implementa a interface de calculadora de modo assíncrono, ela
processa a divisão em outra thread. Quando o calculo é finalizado quem infocou o
serviço é notificado via um callback.
Vamos ver como testar este código integrando o Spring ao TestNG, para isso
confira a classe abaixo de testes.
package com.blogspot.diegopacheco.springframework25.testng;
import org.springframework.stereotype.Service;
@Service
public class CalculadoraAsync implements Calculadora {
@Override
public void dividir(final Double va, final Double vb,
final
ResultadoCallback callback) {
new Runnable(){
public void run() {
callback.processar(va/vb);
}
}.run();
}
}
Código 6.16 ResultadoCallback.java – Interface de Callback
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 16
Agora que já temos o que testar vamos criar um teste unitário com o TestNG,
confira o código de testes abaixo:
package com.blogspot.diegopacheco.springframework25.testng;
import junit.framework.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import
org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;
@Test(groups={"curso-spring"})
@ContextConfiguration(locations={"/spring-test-beans.xml"})
public class CalculadoraTest extends AbstractTestNGSpringContextTests {
private Calculadora calc;
@Test
public void testInjecaoSpring(){
Assert.assertNotNull("A calculadora não foi injetada.",calc);
}
@Autowired
@Test(enabled=false)
public void setCalc(Calculadora calc) {
this.calc = calc;
}
}
Código 6.17 ResultadoCallback.java – Interface de Callback
Neste código precisamos focar nos seguintes pontos:
• Extensão da classe AbstractTestNGSpringContextTests: Esta é a classe
abstrata do Spring que prove integração e facilidades para trabalhar com o
testNG.
• @Test: Indica que a classe é testável via TestNG e que a classe pertence ao
grupo de testes chamado curso-spring.
• @Test no método testInjecaoSpring indica que o método deve ser testado.
• @Autowired e @Test(enable=false): Indica que o Spring deve injetar a
instância do bean calculadora, como estamos indo por tipo ele vai injetar a
calculadora assíncrona chamada CalculadoraAsync.
• Assert.assertNotNull neste ponto estamos utilizando asserções para testar
se o código está fazendo o que deveria, caso isso não seja válido, uma
exception será levantada com a mensagem passada no primeiro argumento
do método.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 17
• @ContextConfiguration serve para indicar ao spring onde estão os xmls de
configuração para o contexto de testes que ele irá montar.
Agora vamos ver outros recursos do Spring com o TestNG, podemos utilizar
diversas anotações que nos provem diversas facilidades como:
• @Timed: Especifica um tempo em milisegundos para o método executar,
caso demore mais do que o tempo especificado uma exception é levantada e
o teste irá falhar.
• @Rollback: Especifica se o método irá dar um rollback na transação ou se
será permitido que a transação efetue um commit no banco de dados.
• @ExpectedException: Especifica que uma exception do tipo especificado
deve ser levantada, este recurso é ideal para testar cenários de erros.
• @IfProfileValue: Este recurso permite a execução do método de testes
apartir de um profile condicional. Este profile é definido por uma variavél de
ambiente e um valor, caso a váriavel do sistema tenha o valor que você
informou o método será executado.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 18
Integração com JSF
Java Server Faces vem se tornando muito popular no desenvolvimento de aplicações Web
com Java pela quantidade componentes prontos de riqueza visual dos seus componentes.
O Spring Framework 2.5 possui integração com o Java Server Faces 2.5, vamos ver como
configurar esta integração em uma aplicação Web utilizando o padrão MVC.
Figura 6.1 – Padrão MVC
O JSF é uma das implementações de um framework MVC, o propósito de um framework
MVC é separar a camada de apresentação(view) da camada de negócio(model), é comun
utilizar na parte do model EJB ou Spring Framework, o JSF se encarrega das camadas de
view e controller.
Este padrão é largamente utilizado em desenvolvimento de aplicação Web com Java, JSF é
uma das implementações, mas existem outras como o Strus, Webwork, Stripes, etc.
Para integrar o Contexto do Spring ao JSF é necessário registrar o listener do Spring no
web.xml para que o contexto do Spring suba automaticamente quando a aplicação inicia e
bem como registrar o org.springframework.web.jsf.el.SpringBeanFacesELResolver como
ElResolver do JSF. Depois disso você pode utilizar o Spring com o JSF normalmente.
Então vamos ver essas configurações na prática e bem como uma aplicação com todas as
camadas típicas da arquitetura MVC usando Spring Framework, JSF, Jboss RichFaces e
Annotations.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 19
<?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"
id="WebApp_ID" version="2.5">
<!-- Configurações da Aplicação -->
<display-name>Adendo-Curso-Spring-JSF</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!-- Configurações do Spring Framework -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-beans-core.xml</param-value>
</context-param>
<listener>
<listener-
class>org.springframework.web.context.ContextLoaderListener</listener-
class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener</lis
tener-class>
</listener>
<!-- Configurações para utilização de JSF -->
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config-beans.xml,/WEB-INF/faces-
config-nav.xml</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-
class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsp</param-value>
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 20
</context-param>
<listener>
<listener-
class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<context-param>
<param-name>com.sun.faces.verifyObjects</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<!-- Configurações do JBoss Richfaces -->
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>laguna</param-value>
</context-param>
</web-app>
Código 6.18 web.xml – Configurações da Aplicação
Como você pode perceber, as configurações de Spring, JSF e Jboss RichFaces estão
separadas por comentários, vamos ver o significado de cada configuração uma a uma,
começando com as configurações do Spring Framework.
O parametro para Servlets chamado contextConfigLocation serve para indicar aonde estão
as configurações em xml do spring para serem utilizadas na startup do contexto. Na
sequencia o listener do spring chamado
org.springframework.web.context.ContextLoaderListener é responsável por subir o
contexto do spring nesta aplicação web.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 21
Por fim é utilizado o org.springframework.web.context.request.RequestContextListener para
trabalhar a tecnologia de MVC do spring com JSF, no nosso caso vamos utiliza-lo apenas
para ver o que está trafegando nos cabeçalhos do http.
Depois vem as configurações do JSF e do Jboss RichFaces que são padrão o único ponto
mais importante a prestar atenção aqui é o parâmetro de servlet chamado
javax.faces.CONFIG_FILES que serve para informar onde estão os arquivos de configuração
do JSF.
No final do arquivo estamos registrando o filter do Jboss Richfaces, bem como a utilização
de um Skin plugável chamado laguna. Vamos ver as configurações do JSF agora, ou seja, os
faces-config.
<?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_1_2.xsd"
version="1.2">
<navigation-rule>
<navigation-case>
<from-outcome>sucesso</from-outcome>
<to-view-id>/Pages/lista-cao-pego.jsp</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
</faces-config>
Código 6.19 faces-config-nav.xml– Arquivo com Regras de Navegação
Neste arquivo estão as configurações de navegação dos beans. Vamos ver o arquivo de
configuração dos managed beans e do spring com o ElResolver.
<?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_1_2.xsd"
version="1.2">
<application>
<el-
resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-
resolver>
</application>
<managed-bean>
<managed-bean-name>carrocinhaBean</managed-bean-name>
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 22
<managed-bean-
class>com.blogspot.diegopacheco.springframework25.jsf.mb.CarrocinhaBean</
managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>carrocinhaService</property-name>
<property-
class>com.blogspot.diegopacheco.springframework25.jsf.service.CarrocinhaS
ervice</property-class>
<value>#{caveiraoService}</value>
</managed-property>
</managed-bean>
</faces-config>
Código 6.20 faces-config-beans.xml– Arquivo com os MB do JSF
O ponto mais importante deste arquivo é a configuração do SpringBeanFacesElResolver,
depois está sendo declarado o carrocinhaBean que é o controller desta aplicação. Vamos
ver as classes da aplicação neste momento então.
package com.blogspot.diegopacheco.springframework25.jsf.pojo;
import java.io.Serializable;
public class Cachorro implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String nome;
private String raca;
public Cachorro() { }
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getRaca() {
return raca;
}
public void setRaca(String raca) {
this.raca = raca;
}
@Override
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 23
public String toString() {
return "id: " + id + ",Nome: " + nome + ", Raça: " + raca;
}
}
Código 6.21 Cachorro.java– Pojo que representa um Cachorro
Este é um simples pojo com métodos getters e setters com o construtor vazio e que
implementa Serializable. Vamos ao componente responsável por persistir o objeto.
package com.blogspot.diegopacheco.springframework25.jsf.dao;
import java.io.Serializable;
import org.springframework.stereotype.Repository;
import com.blogspot.diegopacheco.springframework25.jsf.pojo.Cachorro;
@Repository(value="carrocinhaDao")
public class CarrocinhaDao {
public Serializable capturar(Cachorro c){
System.out.println("Cachorro: " + c + " persistido com
sucesso ");
return c;
}
}
Código 6.22 CarrocinhaDao.java– Repository de Carrocinha
Este repositório é resposável por acessar os dados referente ao serviço de carrocinha,
também é conhecido como o pattern DAO. Este código não acessa o banco de dados, mas
você poderia utilizar JPA ou Hibernate sem problema nenhum.
package com.blogspot.diegopacheco.springframework25.jsf.service;
import java.io.Serializable;
import com.blogspot.diegopacheco.springframework25.jsf.pojo.Cachorro;
public interface CarrocinhaService {
public Serializable catar(Cachorro c);
}
}
Código 6.23 CarrocinhaService.java– Serviço de Carrocinha
Esta é a interface de contrato do serviço de carrocinha, os cachorros devem ter cuidado
agora, senão, vão se dar mal. Vamos ver uma implementação deste serviço:
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 24
package com.blogspot.diegopacheco.springframework25.jsf.service;
import java.io.Serializable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import
com.blogspot.diegopacheco.springframework25.jsf.dao.CarrocinhaDao;
import com.blogspot.diegopacheco.springframework25.jsf.pojo.Cachorro;
@Service(value="caveiraoService")
public class CaveiraoCarrocinhaServiceImpl implements
CarrocinhaService {
@Autowired
private CarrocinhaDao dao;
public Serializable catar(Cachorro c) {
Serializable ser = dao.capturar(c);
System.out.println("Cão: "+ ser + " não tem vez!");
return ser;
}
public void setDao(CarrocinhaDao dao) {
this.dao = dao;
}
}
Código 6.24 CaveiraoCarrocinhaServiceImpl– Serviço de Carrocinha Impl
Este é o serviço implementado para carrocinha. Como você pode perceber, ele está
utilizando um dao que é injetado via anotação @Autowired. Este serviço retorna a instância do
Cachorro que foi capturado.
package com.blogspot.diegopacheco.springframework25.jsf.mb;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import com.blogspot.diegopacheco.springframework25.jsf.pojo.Cachorro;
import
com.blogspot.diegopacheco.springframework25.jsf.service.CarrocinhaService
;
@Controller(value="carrocinhaBean")
public class CarrocinhaBean {
private Integer id;
private String nome;
private String raca;
private String resultado;
@Resource
private CarrocinhaService carrocinhaService;
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 25
public CarrocinhaBean() {}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getRaca() {
return raca;
}
public void setRaca(String raca) {
this.raca = raca;
}
public String getResultado() {
return resultado;
}
public void setResultado(String resultado) {
this.resultado = resultado;
}
public CarrocinhaService getCarrocinhaService() {
return carrocinhaService;
}
public void setCarrocinhaService(CarrocinhaService
carrocinhaService) {
this.carrocinhaService = carrocinhaService;
}
public String catar(){
Cachorro c = new Cachorro();
c.setId(1);
c.setNome(nome);
c.setRaca(raca);
Cachorro caoCatadado = (Cachorro)carrocinhaService.catar(c);
resultado = "Cão: " + caoCatadado.getNome() + " - Catado! ";
return "sucesso";
}
}
Código 6.25 CarrocinhaBean– Controller da Aplicação
Esta classe é um controller, você pode reparar que ela tem as mesmas propriedades que o
pojo Cachorro tem, isto serve para separarmos objetos que trafegam na tela com os
objetos que trafegam nos serviços e nas regras de negócio.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 26
Uma instância de CarrocinhaService é injetada via a anotação @Resource e o método catar
tem a resposabilidade de criar o pojo Cachorro e invocar o serviço de Carrocinha e repassar
o resultado, caso dê tudo certo, o resultado é “sucesso” que irá cair nas regras de
navegação do JSF e levar a execução a outra página.Vamos ver o código das páginas desta
aplicação;
<%@ page contentType="text/html; charset=Cp1252"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Cp1252" />
<title></title>
</head>
<body>
<f:view>
<h:form>
<rich:panel>
<h:panelGrid>
<h:outputLabel value="Capturar um Cão sem
Sorte" />
<h:panelGroup>
<h:outputLabel id="nome" value="Nome do
Cão:" />
<h:inputText id="nomeTxt"
value="#{carrocinhaBean.nome}" />
</h:panelGroup>
<h:panelGroup>
<h:outputLabel id="raca" value="Raça do
Cão :" />
<h:inputText id="racaTxt"
value="#{carrocinhaBean.raca}" />
</h:panelGroup>
<h:panelGroup>
<a4j:commandButton value="Catar o Cão
agora!" action="#{carrocinhaBean.catar}" />
</h:panelGroup>
</h:panelGrid>
</rich:panel>
</h:form>
</f:view>
</body>
</html>
Código 6.26 main.jsp– Página de captura de cães
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 27
<%@ page contentType="text/html; charset=Cp1252"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Cp1252" />
<title></title>
</head>
<body>
<f:view>
<h:form>
<rich:panel>
<h:panelGrid>
<h:outputLabel value="Cão que se deu mal" />
<h:panelGroup>
<h:outputLabel id="result" value="Cão
Capturado:" />
<h:outputLabel id="resuktValue"
value="#{carrocinhaBean.resultado}" />
</h:panelGroup>
</h:panelGrid>
</rich:panel>
</h:form>
</f:view>
</body>
</html>
Código 6.27 lista-cao-pego.jsp.jsp– Página que mostra o cão pego
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 28
Ao rodar esta aplicação você irá precisar das seguintes dependências em termos de jars:
Figura 6.2 Dependências de Jars
A versão do Spring Framework utilizada foi a versão 2.5.6.SCE e a aplicação roda no Jetty
6.1.3, você pode obter a aplicação completa nos fontes que acompanham apostila.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 29
Expondo os seus beans via JMX
JMX é uma solução Java para monitoramento e parametrização do
comportamento da aplicações Java em tempo de runtime. Esta solução é
muito utilizada para o gerenciamento de aplicações Java. Para utilizar este
recurso você não precisar implementar e nem estender nenhum recurso do
Spring Framework. Vamos a um exemplo prático.
package com.blogspot.diegopacheco.springframework25.jmx;
public interface DateService {
public String getDate();
}
Figura 6.28 DateService.java contrato do serviço de dadas
Como você pode perceber esta é um interface como outa qualquer, sem
nada de mais, apenas existe um método chamado getDate que deve
retornar uma String. Vamos ver a sua implementação.
package com.blogspot.diegopacheco.springframework25.jmx;
import java.util.Date;
public class DateServiceImpl implements DateService{
public String getDate() {
return new Date().toString();
}
}
Figura 6.29 DateServiceImpl.java – Serviço de Datas
A implementação é bem simples, apenas retorna o método toString() de um
objeto Date recente, que irá ter a data e hora atual do sistema.
Vamos registrar este bean como um bean do Spring, utilizando xml como de
costume.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 30
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-
context-2.5.xsd">
<bean id="dateService"
class="com.blogspot.diegopacheco.springframework25.jmx.DateServiceImpl"
/>
</beans>
Figura 6.30 DateServiceImpl.java – Serviço de Datas
Declaração do bean no contexto do Spring como de costume é feito e sem
nada de novo, agora é possível apenas expor este bean via JMX, sem
esforço de programação, basta utilizar a configuração a baixo.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-
2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.blogspot" />
<bean id="dateService"
class="com.blogspot.diegopacheco.springframework25.jmx.DateServiceI
mpl" />
<bean id="exporter"
class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=DateService" value-
ref="dateService" />
</map>
</property>
</bean>
</beans>
Figura 6.30 DateServiceImpl.java – Serviço de Datas
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 31
O Código acima utiliza o recurso do spring chamado de
org.springframework.jmx.export.MbeanExporter que é resposável por expor
os beans via JMX, ele recebe um map com os beans que vão ser expostos,
logo é possível expor mais de um bean.
Existem outras estratégias para exposição de beans com JMX, esta é a mais
simples, caso queira saber mais, consulte a documentação oficial do spring
framework.
Você pode acessar este MBean via um utilitário que vem junto com o JDK do
java o Jconsole, você achar o utilitário na pasta bin do seu JDK, para utilizar
o JMX é comun ter que habilitar este recurso no seu container, cada
container tem uma configuração diferente, recomendo verificar a
documentação do container que você esteja utilizando para maiores
detalhes.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 32
Exercícios
1) Crie um beans Pessoa, AnimalDeEstimacao e Casa e injete um no outro usando as
anotaçõess do Spring. Você deve criar o método verifica animais, que deve retornar
um Map contendo o nome do animal e o tipo dele, exe.: mamífero, réptil, etc...
2) Adicione a anotação de ciclo de vida @PostConstruct e @PreDestroy no bean de
Pessoa e faça log do início e fim da aplicação.
3) Exponha o bean pessoa com o método listarAnimais() que deve retornar uma
Sring com todos os animais da pessoa separados por “ ; ”
4) Crie um teste unitário com TestNG para validar se o objeto através do método
verifica animais está correto.
5) Crie uma aplicação web com JSF que você possa cadastrar um animal preferido a
pessoa e depois tenha uma página que mostre o animal cadastrado, não é
necessário acessar banco de dados.
Spring Framework – Framework para desenvolvimento de aplicações java
Diego Pacheco – http://diego-pacheco.blogspot.com 33
Espaço para anotações