Você está na página 1de 168

Spring Framework (2.

0) Framework para Desenvolvimento de Aplicaes em Java

Diego Pacheco
Dez/2007

Apostila desenvolvida especialmente para a Crom Microsystems. Sua cpia ou reproduo livre.

Sobre o Autor

Diego Pacheco Tcnico em Processamento de Dados e graduando em Cincias da Computao(7 sem.) na Ulbra. J trabalhou com desenvolvimento de software em VB, ASP, .NET e PHP. Atualmente Arquiteto de Software, certificado pela Sun, atuo desenvolvendo solues corporativas em arquitetura JEE, provendo coaching/mentoring em software e processo de desenvolvimento de software. Gosto muito de msica, tocar guitarra, jogar PSP, Bloggar, Ler e principalmente as incrveis histrias do Conan. Mantenho o blog < http://diego-pacheco.blogspot.com/> a mais de 3 anos.

Spring Framework Framework para Desenvolvimento de Aplicaes Java

Sumrio
1. Introduo .................................................................................................................... 1-1
Objetivos ...................................................................................................................................1-2 Conceitos Bsicos .................................................................................................................1-3 Cenrios de uso ....................................................................................................................1-7 Portiflio ...............................................................................................................................1-10 Download ..............................................................................................................................1-12 Estrutura de Diretrios ..................................................................................................1-13 Exerccios ..............................................................................................................................1-15 Espao para anotaes ....................................................................................................1-16

2. Container IoC .............................................................................................................. 2-1


Objetivos ...................................................................................................................................2-2 IoC Inversion of control ...............................................................................................2-3 Registrando Beans .............................................................................................................2-13 Singletons e lazy Initialization .................................................................................2-15 Lazy Initialization ...........................................................................................................2-18 Scopos dos Beans ................................................................................................................2-20 Criando seu prprio scope ............................................................................................2-23 Injeo via setter.................................................................................................................2-27 Injeo via construtor ......................................................................................................2-29 Injeo de colees .............................................................................................................2-31 Injeo entre beans colaboradores ............................................................................2-36 Instanciando o contexto Web .......................................................................................2-40 Exerccios ..............................................................................................................................2-42 Espao para anotaes ....................................................................................................2-43

3. Manipulao de Beans .......................................................................................... 3-1


Objetivos ...................................................................................................................................3-2 Resource Loaders .................................................................................................................3-3 Init-Metohd e InitializingBean ...................................................................................3-4 Herana de Definies ......................................................................................................3-7 Validao ..............................................................................................................................3-10 Bean Wrapper......................................................................................................................3-13 BeanPostProcessors ............................................................................................................3-17
Diego Pacheco http://diego-pacheco.blogspot.com I

Spring Framework Framework para desenvolvimento de aplicaes Java

BeanFactoryPostProcessors ............................................................................................3-21 Property Editors .................................................................................................................3-25 Eventos ....................................................................................................................................3-30 PropertyPlaceholderConfigurer .................................................................................3-33 SingletonBeanFactoryLocator ......................................................................................3-36 Internacionalizao .........................................................................................................3-40 Exercicios ..............................................................................................................................3-44 Espao para anotaes ....................................................................................................3-45

Diego Pacheco http://diego-pacheco.blogspot.com

II

Spring Framework Framework para desenvolvimento de aplicaes Java

4. Persistncia .................................................................................................................. 4-1


Objetivos ...................................................................................................................................4-2 Hierarquia de Exceptions ...............................................................................................4-3 Acesso a dados usando JDBC ........................................................................................4-5 Trabalhando com DataSources ....................................................................................4-5 Trabalhando com JDBCTemplate ..............................................................................4-7 Session Factory Bean ........................................................................................................4-11 Hibernate Template..........................................................................................................4-13 Transaes Declarativas .................................................................................................4-18 Exerccios ..............................................................................................................................4-22 Espao para anotaes ....................................................................................................4-23

5. Facilitadores ................................................................................................................ 5-1


Objetivos ...................................................................................................................................5-2 Envio de E-mails ................................................................................................................5-3 Agendamento de tarefas com JDK Task .................................................................5-10 @Aspect Support .................................................................................................................5-16 Testing Support ...................................................................................................................5-23 AbstractDependencyInjectionSpringContextTests ..............................................5-24 AbstractAnnotationAwareTransactionalTests .....................................................5-27 AbstractTransactionalDataSourceSpringContextTests.....................................5-28 Remoting com RMI ...........................................................................................................5-29 Exerccios ..............................................................................................................................5-34 Espao para anotaes ....................................................................................................5-35

Diego Pacheco http://diego-pacheco.blogspot.com

III

Spring Framework Framework para Desenvolvimento de Aplicaes Java

1. Introduo

Diego Pacheco http://diego-pacheco.blogspot.com

Spring Framework Framework para desenvolvimento de aplicaes java

Objetivos
Conhecer os conceitos bsicos; Conhecer os principais cenrios de uso; Prover uma viso de todo o portiflio do Spring; Saber onde baixar o Spring; Conhecer a estrutura de diretrios dos fontes.

Diego Pacheco http://diego-pacheco.blogspot.com

1-2

Spring Framework Framework para desenvolvimento de aplicaes java

Conceitos Bsicos

Spring framework, garanto a voc que no nenhum produto de limpeza, at pode parecer pelo nome, mas no . Spring um dos frameworks lderes do mercado full-stack Java/JEE. Esse framework mantido pela empresa Interface21 que tem como presidente, Rod Johnson, o criador do Spring que simplesmente uma das maiores autoridades em Java. Spring prove diversos benefcios para muitos projetos, aumentando a produtividade de desenvolvimento e a performance em tempo de runtime em quanto ao mesmo tempo prove uma cobertura para testes e muita qualidade para a aplicao. O Spring prove solues light-weight para construes de aplicaes corporativas. Enquanto ainda suporta e prove a possibilidade de se usar: transaes declarativas, acesso remoto atravs de RMI ou Web Services e muitas opes para persistncia de dados. O Spring prove tambm uma soluo completa MVC Framework e maneiras transparentes e elegantes para integrao de AOP ao seu software. Esse framework extremamente modular, assim voc pode usar somente as partes que lhe interessam. possvel usar IoC com Struts ou por exemplo, voc pode optar por usar somente a camada de integrao com Hibernate ou a camada de abstrao para JDBC. Desenhado para no ser intrusivo, utilizando apenas ele mesmo ou o mnimo de dependncias para suas funcionalidades. Esse framework foi muito bem dividido, e isso pode ser observado com clareza na figura a baixo.

Diego Pacheco http://diego-pacheco.blogspot.com

1-3

Spring Framework Framework para desenvolvimento de aplicaes java

Figura 1.1 Viso Geral

Utilizando o Spring voc j ter um ganho excelente em qualidade de software em termos de design patterns, utilizando ele praticamente anula o uso de patterns como Factory e ServiceLocator. Todo Objeto componente de sua aplicao por default para o Spring um singleton, assim favorecendo as boas prticas e a performance. A Empresa Interface21 e com certeza o Spring tem como misso os seguintes valores: J2EE Deveria ser muito fcil de usar melhor programar para interfaces do que para classes, Spring reduz o custo e a complexidade de usar interfaces para zero. JavaBeans oferece uma maneira excelente para configurar uma aplicao.

Diego Pacheco http://diego-pacheco.blogspot.com

1-4

Spring Framework Framework para desenvolvimento de aplicaes java

O Design OO mais importante do que qualquer tecnologia de implementao como, por exemplo, J2EE. Exception checadas so mal utilizadas no Java. Um framework no deveria forar voc a capturar exceptions que voc no est apto a se recuperar. Testabilidade essencial, o Spring ajuda voc a testar seu cdigo mais facilmente. O Spring precisa ser prazeroso para quem desenvolve usando ele. O Cdigo de sua aplicao deveria no depender da API do Spring. O Spring no compete com as boas solues existentes, mas prove integrao dessas tecnologias, como exemplo o Hibernate, o Spring no pretende desenvolver outra, apenas integr-la e prover facilidades.

Algumas das funcionalidades do core do Spring so: O Mais completo lightweight container: Prove centralizao, automao de configurao e escrita para seus objetos de negocio. um container no intrusivo, capaz de suportar sistemas complexos de um conjunto de componentes (POJO) de baixo acoplamento, consistncia e transparncia. O Container traz agilidade ao desenvolvimento e tambm testabilidade e uma alta escalabilidade, permitindo que os componentes de software possam ser desenvolvidos e testados isoladamente. Pode ser utilizado em qualquer ambiente de desenvolvimento J2SE ou J2EE. Uma camada comum de abstrao para Transaes: Permite gerenciamento transacional plugvel com uma marcao transacional fcil, assim evitando pequenos problemas de baixo nvel. Estratgias para JTA e para um nico JDBC DataSource so includos. Em contraste com a JTA e o EJB CMT, as transaes do spring no esto disponveis s em ambientes J2EE, possvel utilizar em ambiente J2SE tambm. Uma Camada de Abstrao para JDBC: Prove uma hierarquia de exceptions a partir de SQLException de maneira totalmente significativa. Simplifica o tratamento de erros, e diminuiu muito a quantidade de cdigo a ser escrito. Nunca mais ser necessrio escrever um bloco finaly para usar JDBC. Integrao com Toplink, Hibernate, JDO, and iBATIS SQL Maps: Em termos de resource holders, suporte a implementaes de DAOs e estratgias transacionais. Existe um suporte de primeira classe para Hibernate com muitas facilidades providas pelo mecanismo de IoC.

Diego Pacheco http://diego-pacheco.blogspot.com

1-5

Spring Framework Framework para desenvolvimento de aplicaes java

Funcionalidade AOP: Totalmente integrado com o gerenciamento configuracional do Spring, voc pode utilizar AOP com qualquer objeto gerenciado pelo Spring, adicionando aspectos em gerenciamento transacional, por exemplo. Com Spring possvel ter transaes declarativas sem EJB e at mesmo sem JTA, caso voc esteja utilizando um nico banco de dados em um servidor tomcat, por exemplo.

Diego Pacheco http://diego-pacheco.blogspot.com

1-6

Spring Framework Framework para desenvolvimento de aplicaes java

Cenrios de uso

Podemos utilizar Spring nos mais diversos cenrios, desde um simples applet at mesmo nas mais complexas aplicaes corporativas. Um exemplo tpico de uso do Spring em uma aplicao completa Java EE onde teremos:

Figura 1.2 Cenrio completo de uso em JEE.

Diego Pacheco http://diego-pacheco.blogspot.com

1-7

Spring Framework Framework para desenvolvimento de aplicaes java

Uma camada de validaes de formulrios, solues em upload de arquivos, bind de objetos de domnio e claro, uma integrao com JSP, Velocity, XSLT, PDF e Excel. Aps isso o contexto web, gerenciado pelo Spring e utilizando o Spring MVC. No cerne das aplicaes o contexto principal do Spring com o container IoC e algumas funcionalidades, como envio de e-mails e acessos remotos atravs de RMI, SOAP, Burlap, etc. Seguindo da camada de regras de negcio, onde temos facilidades com o mdulo de AOP e a integrao com o mdulo de ORM, chegando finalmente na camada de persistncia atravs do suporte rico ao Hibernate ou via JDBC. Tudo isso rodando em um container JSP/Servlet como o Tomcat ou Jetty. No caso de sua aplicao precisar fazer algum acesso remoto o Spring prove isso de maneira transparente e elegante.

Figura 1.3 Cenrio remoto. normal uma aplicao necessitar fazer acesso remoto a alguma outra aplicao ou servio, nesse cenrio interessante usar spring tambm, pois alm de facilitar a abstrair muito a complexidade de fazer esses acessos, voc pode usar os seus componentes que j esto sendo gerenciados pelo spring obtendo assim uma mxima integrao entre seus componentes de negcios e os componentes remotos.

Diego Pacheco http://diego-pacheco.blogspot.com

1-8

Spring Framework Framework para desenvolvimento de aplicaes java

Podemos usar Spring tambm se for necessrio fazer integrao com EJB, possvel utilizar os recursos da camada de acesso e abstrao de EJB.

Figura 1.4 Cenrio EJB. O Spring permite voc reutilizar seus pojos existentes e empacotados em Stateless Session Beans, para serem usados em aplicaes web escalveis, que precisam de segurana declarativa.

Diego Pacheco http://diego-pacheco.blogspot.com

1-9

Spring Framework Framework para desenvolvimento de aplicaes java

Portiflio

O Spring possui um portiflio muito abrangente, que composto por uma srie de projetos Spring..., podemos dizer que um ecossistema muito diversificado, composto pelos seguintes projetos: Spring Framework: Principal projeto do portiflio da Interface21, esse o framework base de todos os outros. Contm recursos como container IoC, suporte a Hibernate, jdbc, aop, integrao com os principais frameworks do mercado. Spring Web Flow: framework web baseado em fluxos, prove a facilidade de desenvolver modelos de aes dos usurios em alto nvel de abstrao. possvel agrupar dois fluxos de controle e formar um modulo da juno dos dois. Spring Web Services: Facilita o desenvolvimento de services SOAP, permitindo a criao de web services flexveis, com suporte a segurana WS, permitindo ecriptao, decriptao. Possui integrao com segurana ACGI. Alm disso, o Spring Web Services faz as boas prticas serem fceis, ajudando voc desenvolver com baixo acoplamento entre o contrato e a implementao. Spring Acegi: Acegi uma soluo flexvel e poderosa para segurana de aplicaes Java. Dentre as principais facilidades esto: autenticao, autorizao, acesso baseado em instncia, canal de segurana e capacidades de deteco humana. Utiliza o contexto do Spring para suas configuraes, configurao de forma no intrusiva, utilizando filters. Spring LDAP: Ajuda nas operaes LDAP, baseada no pattern Springs JdbcTemplate. O Framework alivia o desenvolvedor de abrir e fechar contextos, fazer loopings atravs de NamingEnumerations, encoding/deconding de valores e filtros.

Diego Pacheco http://diego-pacheco.blogspot.com

1-10

Spring Framework Framework para desenvolvimento de aplicaes java

Spring Rich Client: Framework para desenvolvimento de aplicaes Rich Client, uma boa soluo para construes de aplicaes swing de maneira rpida e de qualidade. Possu um conjunto rico de UI Factories, o foco desse projeto e prover boas prticas de maneira vivel para o desenvolvimento swing, possui integrao com Jgoodies e layout managers ricos como o TableLayout. Spring IDE para eclipse: Plugin para o ide eclipse com facilidades para o uso de Spring. Preove auto complete para os xmls de configurao do Spring, mdulo visual para o Spring Web Flow, negao entre os beans do Spring, e visualizao de recursos AOP. Spring BeanDoc: uma ferramenta que facilita a documentao e desenho grfico dos beans do contexto do Spring. Desenhado para ser flexvel e simples de usar. BeanDoc pode facilitar a visualizao das camadas da aplicao e como os objetos interagem. Pode ser configurado por uma task ant. Spring OSGI: Facilita a criao de aplicaes Spring que iro rodar em um framework OSGI, uma aplicao escrita dessa forma tem uma separao melhor entre os mdulos, com isso ganha a habilitada de remover, adicionar, atualizar os mdulos em tempo de execuo. Spring JavaConfig: Projeto que prove algumas anotaes para efetuar o mapeamento de pojos com menos configuraes em XML. Esse projeto no substitui completamente o uso de XML, mas consegue reduzir bastante em algumas funcionalidades de injeo. Spring.NET: Implementao do Core do Spring, com o seu container de IoC, s que para a plataforma da Microsoft .NET, esse projeto no tem todas as funcionalidades do Spring para Java, mas conta com muitos recursos do Spring feitos em Java como AOP, gerenciamento transacional e integrao com Web. Spring Extensions: Projeto que uma coleo de ferramentas para estender as funcionalidades do Spring framework, prove facilidade de integrar o Spring com outros frameworks. Dentre os tantos frameworks que so integrados com esse projeto esto: ant, Lucene, cache declarativo com EHCache, Drools, Jakarta Commons, engines de tamplates como Velocity, jBPM, etc. Spring Batch: Prove suporte para execuo de tarefas muito longas. Suporte a programas batch os quais processam um volume muito grande de informaes de um banco de dados. Com suporte a agendamento automtico ou manual aps falhas, esse projeto promove suporte de execues batch para ambientes corporativos.

Diego Pacheco http://diego-pacheco.blogspot.com

1-11

Spring Framework Framework para desenvolvimento de aplicaes java

Download
O Spring Framework pode ser obtido atravs do site: http://www.springframework.org/download existe a possibilidade de baixar somente o framework ou baixar o framework e suas dependncias. A Verso do Spring que ser usada nessa apostila a 2.0.6 , mas muitos itens descritos aqui so vlido tambm para a verso 1.2.x do framework. O Spring framework necessita apenas uma verso do 1.5 JDK ou superior, no necessrio criar variveis de ambiente para o Spring. O Spring usa um conjunto de frameworks muito grande, ento recomendado fazer download da verso full com dependncia que tem por volta de 60Mb.

Diego Pacheco http://diego-pacheco.blogspot.com

1-12

Spring Framework Framework para desenvolvimento de aplicaes java

Estrutura de Diretrios

Agora ser detalhada a estrutura de diretrios da distribuio do Spring framework. Ao descompactar os binrios do Spring teremos uma estrutura de diretrios da seguinte forma:

Figura 1.4 Estrutura de Diretrios da distribuio do Spring.

aspectj: Fontes dos testes dos artefatos que utilizam aspectj, aqui temos alguns artefatos de transao feitos em aspectJ. dist: Distribuio binrias dos fontes do Spring, aqui voc encontrar os jars do Spring, bem como todos os jars de todos os mdulos separados. docs: Contem toda a documentao do Spring, nessa voc ir encontrar o JavaDoc, Reference Guide, documentao das taglibs do Spring. lib: Nesse diretrio esto todas as dependncias diretas e indiretas do Spring framework, aqui voc encontrar jars de diversos frameworks, como por exemplo hibernate, struts, junit, ant.

Diego Pacheco http://diego-pacheco.blogspot.com

1-13

Spring Framework Framework para desenvolvimento de aplicaes java

mock: Fontes do mecanismo de mock que so utilizados para testes unitrios, nesse diretrio voc encontra os fontes dos testes dos mocks tambm. samples: Nesse diretrio existem diversos exemplos de mini-aplicaes utilizando o Spring Framework, como por exemplo a Petclinic que uma clinica de animais. src: Contm todos os fontes do Spring framework, caso voc precise desses fontes para debugar o comportamento de algum cdigo do Spring. test: Nesse diretrio voc encontrar todos os fontes dos testes realizados com o Spring, til para aprender como utilizar algumas classes do Spring. tiger: Todos os fontes que utilizam recursos somente do Java 5.0 esto nesse diretrio, como por exemplo, annotations.

Dois arquivos que esto soltos no diretrio principal e so interessantes so o changelog.txt e o readme.txt. No arquivo changelog contm todas as mudanas dessa verso do Spring como, por exemplo: quais so as novas features e quais foram os bugs corrigidos. No arquivo readme ns temos a definio de cada modulo do Spring com suas dependncias, isso muito til se voc deseja utilizar somente alguns mdulos do Spring e precisa saber as dependncias.

Diego Pacheco http://diego-pacheco.blogspot.com

1-14

Spring Framework Framework para desenvolvimento de aplicaes java

Exerccios

1) Defina com suas palavras qual a utilidade do Spring Framework. 2) Cite trs vantagens de se usar Spring framework. 3) Diga um cenrio em que poderamos utilizar Spring. 4) Diga uma das utilidades do arquivo readme.txt.

Diego Pacheco http://diego-pacheco.blogspot.com

1-15

Spring Framework Framework para desenvolvimento de aplicaes java

Espao para anotaes

Diego Pacheco http://diego-pacheco.blogspot.com

1-16

Spring Framework Framework para Desenvolvimento de Aplicaes Java

2. Container IoC

Diego Pacheco http://diego-pacheco.blogspot.com

Spring Framework Framework para desenvolvimento de aplicaes java

Objetivos

Conhecer o conceito de IoC; Saber utilizar Lazy initialization e Singletons; Conhecer os escopos dos Beans; Saber registrar beans no container do Spring; Saber fazer injees com setters e construtores; Saber fazer injees com colees; Saber fazer injeo entre beans colaboradores; Saber instanciar o contexto do Spring.

Diego Pacheco http://diego-pacheco.blogspot.com

2-2

Spring Framework Framework para desenvolvimento de aplicaes java

IoC Inversion of control

Com a grande demanda de desenvolvimento para o Java corporativo (JEE), surgiu um problema comum, como ligar a camada de acesso a dados com a camada de regra de negcio e por ventura a camada de apresentao? Uma soluo um container de Ioc que tambm chamada de Dependency Injection(DI), o Spring framework possui um container de Ioc leve e implementa o pattern de setter injection. Esse container trabalha com servios definidos pelo programador. Servio um componente de software que foi projetado para ser reutilizado em muitos lugares sem a necessidade de alterao de cdigo, possvel alterar o seu comportamento estendendo-o de alguma forma. A Idia principal da injeo de dependncias separar os Objetos e principalmente o objeto que usa um outro objeto no instanciar diretamente esse objeto. Sendo assim, a principal vantagem da Dependency Injection separar uma interface de sua implementao concreta. So dois tipos de injeo que o Spring utiliza em seu container de Ioc, veja: Setter Injection: Nesse tipo de injeo de dependncias se utiliza de mtodos setters baseados em propriedades e padres de getters/setters da Sun. Voc no precisa ter a propriedade de fato em seu servio, mas o padro de nomenclatura deve estar correto. Constructor Injection: Nesse tipo de injeo de dependncias utilizado o construtor da prpria classe para fazer as injees necessrias. Esse construtor pode ter quantos parmetros forem necessrios. Principais vantagens do uso de IoC do Spring: Desacoplamento Viso fcil de dependncia Facilidade para testes Possibilita escrever aplicaes para terceiros (fora do seu controle) Para fixar melhor esse conceito considere o seguinte exemplo pratico: Imagine que um Autor escreveu muitos livros, ento considere os seguintes pojos:
Diego Pacheco http://diego-pacheco.blogspot.com 2-3

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.bad; import java.util.List; public class Autor { private String nome; private List<Livro> livros; public Autor() {} public Autor(String nome) { super(); this.nome = nome; } public void listarPorNome(){ Listar l = new Listar(); List ret = l.list(nome); System.out.println( (ret.size()==0) ? "NRE" : ret ); } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Livro> getLivros() { return livros; } public void setLivros(List<Livro> livros) { this.livros = livros; } }

Cdigo 2.1 Autor.java

Diego Pacheco http://diego-pacheco.blogspot.com

2-4

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.bad; public class Livro {

private private private private

Autor autor; String titulo; String editora; int ano;

public Livro() {} public Livro(Autor autor, String titulo, String editora, int ano) { super(); this.autor = autor; this.titulo = titulo; this.editora = editora; this.ano = ano; } public Autor getAutor() { return autor; } public void setAutor(Autor autor) { this.autor = autor; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public String getEditora() { return editora; } public void setEditora(String editora) { this.editora = editora; } public int getAno() { return ano; } public void setAno(int ano) { this.ano = ano; } @Override public String toString() { return "titulo: " + titulo + " editor: " + editora + " ano: " + ano; } }

Cdigo 2.2 Livro.java


Diego Pacheco http://diego-pacheco.blogspot.com 2-5

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.bad; import java.util.ArrayList; import java.util.List; public class Listar { public List list(String nome){ Autor a = new Autor("Diego Pacheco"); List<Livro> livros = new ArrayList<Livro>(); livros.add(new Livro(a,"Livro da Vida","Do Livro",2000)); livros.add(new Livro(a,"Spring for Dummies","O'really",2001)); livros.add(new Livro(a,"Bit ou no","Variados Editora",2002));

List<Livro> achados = new ArrayList<Livro>(); for(Livro l: livros){ if (l.getAutor().getNome().equals(nome)) achados.add(l); } return achados; } }

Cdigo 2.3 Listar.java

package com.targettrust.spring.bad; public class MainTest { public static void main(String[] args) { Autor autor = new Autor("Rod"); autor.listarPorNome(); autor.setNome("Diego Pacheco"); autor.listarPorNome(); } }

Cdigo 2.4 MainTest.java

Diego Pacheco http://diego-pacheco.blogspot.com

2-6

Spring Framework Framework para desenvolvimento de aplicaes java

Ns temos os seguintes objetos: Autor, Livro, Listar e MainTest. Nesse exemplo um Autor pode ter vrios livros por isso dentro do Pojo de Autor temos List<Livro> e a classe Listar se encarrega de armazenar os livros e autores e prover uma procura sobre esses dados. Como vocs devem ter percebido o pojo Autor contm um mtodo chamado: listarPorNome que instncia esse objeto Listar e procura pelos livros do autor. Esse exemplo por mais simplrio, serve para demonstrar que existe um forte acoplamento entre o pojo Autor e a classe que lista os Livros por Autor, outro grande problema nesse exemplo que no existem interfaces. O que aconteceria se um Autor pudesse ter outras coisas alm de livros como, por exemplo: artigos, co-autorias, vdeos? Nesse caso essa mudana iria implicar em um refactoring muito grande nessas classes, mas como poderamos resolver esse problema?

Diego Pacheco http://diego-pacheco.blogspot.com

2-7

Spring Framework Framework para desenvolvimento de aplicaes java

Soluo: Criar um interface Publicvel e o Livro ir implementar essa classe, no pojo de Autor mude de uma lista de Livros para uma List de Publicveis, assim criamos a possibilidade de um Autor ter diversos itens em seu portiflio como, por exemplo: Livros, Artigos, Co-autuaes. Para resolver o problema de forma de armazenamento e procura de livros, foi criada a interface Listavel e a classe Listar implementa essa interface, agora podemos criar outra classe que faa acesso base de dados, claro que esse classe deve implementar Listavel. No pojo do Autor precisamos colocar um atributo Listavel e atravs desse atributo que vamos acessar os dados. Essas novas classes iram ficar conforme os fontes a baixo.
package com.targettrust.spring.bad.ok; import java.util.List; public class Autor { private String nome; private List<Publicavel> publicaveis; private Listavel list; public Autor() {} public Autor(String nome) { super(); this.nome = nome; } public void listarPorNome(){ List ret = list.list(nome); System.out.println( (ret.size()==0) ? "NRE" : ret ); } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Publicavel> getPublicaveis() { return publicaveis; } public void setPublicaveis(List<Publicavel> publicaveis) { this.publicaveis = publicaveis; } public Listavel getList() { return list; } public void setList(Listavel list) { this.list = list; } }

Cdigo 2.5 Autor.java


Diego Pacheco http://diego-pacheco.blogspot.com 2-8

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.bad.ok; public class Livro implements Publicavel{ private private private private Autor autor; String titulo; String editora; int ano;

public Livro() {} public Livro(Autor autor, String titulo, String editora, int ano) { super(); this.autor = autor; this.titulo = titulo; this.editora = editora; this.ano = ano; } @Override public String getNome() { return getTitulo(); } @Override public String getTipo() { return "Livro"; } public String getAutor() { return autor.getNome(); } public void setAutor(Autor autor) { this.autor = autor; } public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } public String getEditora() { return editora; } public void setEditora(String editora) { this.editora = editora; } public int getAno() { return ano; } public void setAno(int ano) { this.ano = ano; } @Override

Diego Pacheco http://diego-pacheco.blogspot.com

2-9

Spring Framework Framework para desenvolvimento de aplicaes java

public String toString() { return "titulo: " + titulo + " editor: " + editora + " ano: " + ano; } }

Cdigo 2.6 Livro.java


package com.targettrust.spring.bad.ok; public interface Publicavel { public String getAutor(); public String getNome(); public String getTipo(); }

Cdigo 2.7 Publicavel.java


package com.targettrust.spring.bad.ok; import java.util.List; public interface Listavel { public List<Publicavel> list(String nome); }

Cdigo 2.8 Listavel.java

Diego Pacheco http://diego-pacheco.blogspot.com

2-10

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.bad.ok; import java.util.ArrayList; import java.util.List; public class Listar implements Listavel{ public List<Publicavel> list(String nome) { Autor a = new Autor("Diego Pacheco"); List<Publicavel> publicaveis = new ArrayList<Publicavel>(); publicaveis.add(new Livro(a,"Livro da Vida","Do Livro",2000)); publicaveis.add(new Livro(a,"Spring for Dummies","O'really",2001)); publicaveis.add(new Livro(a,"Bit ou no","Variados Editora",2002)); List<Publicavel> achados = new ArrayList<Publicavel>(); for(Publicavel p: publicaveis){ if (p.getAutor().equals(nome)) achados.add(p); } return achados; } }

Cdigo 2.9 Listar.java


package com.targettrust.spring.bad.ok; public class MainTest { public static void main(String[] args) { Autor autor = new Autor(); autor.setList(new Listar()); autor.setNome("Rod"); autor.listarPorNome(); autor.setNome("Diego Pacheco"); autor.listarPorNome(); } }

Cdigo 2.10 MainTest.java

Diego Pacheco http://diego-pacheco.blogspot.com

2-11

Spring Framework Framework para desenvolvimento de aplicaes java

Nesse exemplo conseguimos resolver os problemas citados acima, mas utilizamos a IoC na mo, ou seja, ns mesmos injetamos as dependncias, a soluo boa, mas isso em um sistema grande seria muito custoso de se fazer, nesse ponto entra o container de IoC do Spring. O Container possibilita de maneira fcil e simples a injeo dessas dependncias e reduz o custo de se trabalhar com essas interfaces quase zero.

Diego Pacheco http://diego-pacheco.blogspot.com

2-12

Spring Framework Framework para desenvolvimento de aplicaes java

Registrando Beans

Agora vamos ver como registrar essas classes no contexto do Spring. Esse registro muito simples, ele consiste em apontar para uma classe Java no seu classpath e dar um id a esse bean. Existem outras configuraes que podemos fazer sobre esses beans, mas vamos comear mostrando como declarar um bean no Spring.
<?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-2.0.xsd" > <bean id="autor" class="com.targettrust.spring.bad.ok.Autor" /> </beans>

Cdigo XML 2.1 Spring-beans.xml Para recuperarmos esse bean do Contexto do Spring, precisamos instanciar um contexto do Spring e solicitar o bean apartir do ID para o contexto, conforme exemplo a baixo.
package com.targettrust.spring.primeiro; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/primeiro/Springbeans.xml"); Object bean = bf.getBean("autor"); System.out.println("Autor: " + bean); } }

Cdigo 2.11 Obtendo um bean do Spring

Diego Pacheco http://diego-pacheco.blogspot.com

2-13

Spring Framework Framework para desenvolvimento de aplicaes java

A BeanFactory uma interface Java que representa o Container Ioc, essa BeanFactory precisa ser instanciada, nesse exemplo foi usado a factory ClassPathXmlApplicationContext que uma factory que leva em considerao xmls de configuraes que esto no classpath. Existem vrias factories no Spring, uma para cada situao, por exemplo, existe uma factory que utilizada para subir o contexto do Spring em um ambiente Servlet. Aps a inicializao do contexto do Spring podemos utilizar o mtodo getBean para recuperar um bean do Spring, nesse exemplo estamos passando o ID do bean que foi o mesmo que registramos no XML: Spring-beans.xml Outra forma de criarmos a BeanFactory seria utilizar um ClassPathResource que aponta para o Xml dos beans e depois utilizar a factory XmlBeanFactory. Conforme o exemplo de cdigo a baixo.
ClassPathResource resource = new ClassPathResource("/com/targettrust/spring/primeiro/Spring-beans.xml"); BeanFactory bf = new XmlBeanFactory(resource);

Cdigo 2.12 outra bean factory possvel registrar um Bean no contexto do Spring programaticamente, para isso necessrio utilizar um objeto BeanDefinition que o objeto que configura o bean no Spring.
BeanDefinition beanDefinition = new RootBeanDefinition(Livro.class, RootBeanDefinition.AUTOWIRE_NO); ((BeanDefinitionRegistry)bf).registerBeanDefinition("livro", beanDefinition); Object beanOutro = bf.getBean("livro"); System.out.println("Livro: " + beanOutro);

Cdigo 2.13 Registra um bean programaticamente

Diego Pacheco http://diego-pacheco.blogspot.com

2-14

Spring Framework Framework para desenvolvimento de aplicaes java

Singletons e lazy Initialization

Para aumentar a performance de sua aplicao com qualidade e aplicando design patterns o Spring por default transforma qualquer bean registrado nele em um singleton. Singleton um padro de projeto (Design Pattern) que consiste em manter apenas uma instncia de um determinado objeto por classloader. um pattern muito aplicado para conexes com banco de dados, por exemplo. Podemos ver isso atravs do seguinte teste.
package com.targettrust.spring.singleton; import java.util.ArrayList; import java.util.List; public class Uf { private String nome; private String sigla; private List<Uf> ufs; public Uf() { System.out.println("Inicio do processamento dos estados..."); initUfs(); } private Uf(String nome, String sigla) { this.nome = nome; this.sigla = sigla; } private void initUfs() { ufs = new ArrayList<Uf>(); ufs.add(new Uf("Acre","AC")); ufs.add(new Uf("Alagoas","AL")); ufs.add(new Uf("Amap","AP")); ufs.add(new Uf("Amazonas","AM")); ufs.add(new Uf("Bahia","BA")); ufs.add(new Uf("Cear","CE")); ufs.add(new Uf("Distrito Federal","DF")); ufs.add(new Uf("Gois","GO")); ufs.add(new Uf("Esprito Santo","ES")); ufs.add(new Uf("Maranho","MA")); ufs.add(new Uf("Mato Grosso","MT")); ufs.add(new Uf("Mato Grosso do Sul","MS")); ufs.add(new Uf("Minas Gerais","MG")); ufs.add(new Uf("Par","PA")); ufs.add(new Uf("Paraiba","PB")); ufs.add(new Uf("Paran","PR")); ufs.add(new Uf("Pernambuco","PE")); ufs.add(new Uf("Piau","PI")); ufs.add(new Uf("Rio de Janeiro","RJ")); ufs.add(new Uf("Rio Grande do Norte","RN")); ufs.add(new Uf("Rio Grande do Norte","RS")); ufs.add(new Uf("Rondnia","RO"));

Diego Pacheco http://diego-pacheco.blogspot.com

2-15

Spring Framework Framework para desenvolvimento de aplicaes java

ufs.add(new ufs.add(new ufs.add(new ufs.add(new ufs.add(new }

Uf("Rorima","RR")); Uf("So Paulo","SP")); Uf("Santa Catarina","SC")); Uf("Sergipe","SE")); Uf("Tocantins","TO"));

public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getSigla() { return sigla; } public void setSigla(String sigla) { this.sigla = sigla; } public List<Uf> getUfsBrazil(){ return ufs; } public void showInstance(){ System.out.println(super.toString()); } public String toString() { return sigla; } }

Cdigo 2.14 Bean Uf


<?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-2.0.xsd" > <bean id="uf" class="com.targettrust.spring.singleton.Uf" /> </beans>

Cdigo XML 2.2 Spring-beans.xml

Diego Pacheco http://diego-pacheco.blogspot.com

2-16

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.singleton; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUfs { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/singleton/Springbeans.xml"); Uf bean1 = (Uf)bf.getBean("uf"); System.out.println("ufs: " + bean1.getUfsBrazil()); bean1.showInstance(); Uf bean2 = (Uf)bf.getBean("uf"); System.out.println("ufs: " + bean2.getUfsBrazil()); bean2.showInstance(); Uf bean3 = (Uf)bf.getBean("uf"); System.out.println("ufs: " + bean3.getUfsBrazil()); bean3.showInstance(); } }

Cdigo 2.15 Teste Se executarmos esse programa, o resultado ser algo semelhante ao representado na figura abaixo.
Inicio do processamento dos estados... ufs: [AC, AL, AP, AM, BA, CE, DF, GO, ES, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SP, SC, SE, TO] com.targettrust.spring.singleton.Uf@3ecfff ufs: [AC, AL, AP, AM, BA, CE, DF, GO, ES, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SP, SC, SE, TO] com.targettrust.spring.singleton.Uf@3ecfff ufs: [AC, AL, AP, AM, BA, CE, DF, GO, ES, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SP, SC, SE, TO] com.targettrust.spring.singleton.Uf@3ecfff

Cdigo 2.16 Resultado da Execuo Perceba que a criao dos estados ocorre somente na primeira vez, mas nas outras vezes j est em memria, logo alm, se no fizer duas vezes o mesmo processamento, existe um ganho de performance.

Diego Pacheco http://diego-pacheco.blogspot.com

2-17

Spring Framework Framework para desenvolvimento de aplicaes java

Tambm possvel desativar esse comportamento, ou seja, possvel configurar no spring para que o bean em questo no seja criado como um Singleton. Para isso, basta alterar o registro do bean no Spring, conforme no XML 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" > <bean id="uf" class="com.targettrust.spring.singleton.Uf" scope="prototype" /> </beans>

Cdigo XML 2.3 Spring-beans.xml Neste mesmo captulo sero explicados e exemplificados melhor os possveis escopos de beans no Spring.

Lazy Initialization
Outro recurso importante o Lazy Initialization, com ele podemos fazer com que o Spring s carregue os beans que forem solicitados, ou seja, se temos 50 beans declarados no contexto do Spring e apenas 10 so utilizados, os outros 40 beans no vo ser instanciados, e assim evitamos um processamento desnecessrio e ganhamos em desempenho.

Diego Pacheco http://diego-pacheco.blogspot.com

2-18

Spring Framework Framework para desenvolvimento de aplicaes java

Para fazer tal configurao necessrio configurar no XML de beans do Spring o atributo lazy-init="true". Veja o exemplo de como faz isso no XML 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >

<bean id="uf" class="com.targettrust.spring.singleton.Uf" scope="prototype" lazy-init="true" /> </beans>

Cdigo XML 2.4 Spring-beans.xml um exemplo lazy initialization. sempre vlido configurar esse comportamento do framework. O Default do Spring comear com lazy-init=false, configurao para true. Podemos configurar no Spring que todos os beans de um determinado arquivo XML de configuraes por default assumam o mesmo valor, podemos fazer isso atravs do atributo default-lazy-init esse atributo s pode ser setado no modo beans que a raiz de configuraes.
<?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-2.0.xsd" default-lazy-init="true" > <bean id="uf" class="com.targettrust.spring.singleton.Uf" scope="prototype" /> </beans>

ento sempre que possvel altere essa

Cdigo XML 2.4 Spring-beans.xml um exemplo de default lazy initialization.

Diego Pacheco http://diego-pacheco.blogspot.com

2-19

Spring Framework Framework para desenvolvimento de aplicaes java

Scopos dos Beans

Scopo se refere visibilidade de um objeto gerenciado pelo Spring e tambm est relacionado ao seu tempo de vida. Existem os seguintes scopos de beans no Spring.

Scopo
singleton prototype request *

Descrio
Uma nica instncia de objeto para todo o contexto do Spring. Mltiplas instncias de um objeto para o container do Spring. Escopo relacionado ao ciclo de vida HTTP Request, a cada request teremos outra instncia de bean no Spring

session *

Escopo relacionado ao ciclo de vida HTTP Session, uma nica instncia do Bean por session.

global session *

Escopo relacionado ao ciclo de vida global HTTP Session, bean vlido em uma session global. Utilizado para portlets.

* Escopos que s so vlidos em um contexto web-aware, ou seja, em uma aplicao JSP/Servlet ou JEE. Criados por uma factory especfica para Web, como por exemplo: XmlWebApplicationContext.

Diego Pacheco http://diego-pacheco.blogspot.com

2-20

Spring Framework Framework para desenvolvimento de aplicaes java

Podemos ver na prtica a diferena entre singleton e prototype no exemplo abaixo. Nesse exemplo o mesmo bean registrado de maneiras diferentes, isso perfeitamente possvel.
package com.targettrust.spring.scope; public class SimpleBean { private Long id = 0L; public SimpleBean() {} public SimpleBean(Long id) { super(); this.id = id; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override public String toString() { return super.toString() + " id: " + id; } }

Cdigo 2.17 SimpleBean.java.


<?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-2.0.xsd" > <bean id="beanA" class="com.targettrust.spring.scope.SimpleBean" scope="singleton" /> <bean id="beanB" class="com.targettrust.spring.scope.SimpleBean" scope="prototype" /> </beans>

Cdigo XML 2.5 Spring-beans.xml xml de configurao.

Diego Pacheco http://diego-pacheco.blogspot.com

2-21

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.scope; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestScope { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/scope/Springbeans.xml"); SimpleBean SimpleBean SimpleBean SimpleBean beanA beanA1 beanB beanB1 = = = = (SimpleBean)bf.getBean("beanA"); (SimpleBean)bf.getBean("beanA"); (SimpleBean)bf.getBean("beanB"); (SimpleBean)bf.getBean("beanB"); : : : : " " " " + + + + beanA); beanA1); beanB); beanB1);

System.out.println("BeanA System.out.println("BeanA1 System.out.println("BeanB System.out.println("BeanB1 } }

Cdigo 2.18 Teste de Scopes.

Diego Pacheco http://diego-pacheco.blogspot.com

2-22

Spring Framework Framework para desenvolvimento de aplicaes java

Criando seu prprio scope


No Spring framework 2.0.X podemos criar nosso prprio scope e ainda mais, podemos redefinir os scopos baseados em web-aware. Os nicos scopos que so intocveis so: prototype e singleton, se tentarmos reescrev-los o Spring ir levantar uma IllegalArgumentException. Imagine que em sua aplicao surgiu a necessidade de ter controle sobre todos os objetos Pessoa criados, como poderamos fazer isso sem reescrever toda a aplicao? Criando o nosso prprio scopo de bean seria uma forma.
package com.targettrust.spring.scope.myscope; public class Pessoa { private String nome; public Pessoa() { } public Pessoa(String nome) { super(); this.nome = nome; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((nome == null) ? 0 : nome.hashCode()); return result; } @Override public boolean equals(Object obj) { return (obj == null) ? false : nome.equals(((Pessoa) obj).getNome()); } @Override public String toString() { return "nome: " + nome; } }

Cdigo 2.19 Pessoa.java.


Diego Pacheco http://diego-pacheco.blogspot.com 2-23

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.scope.myscope; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; @SuppressWarnings("unused") public class TestScopes { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/scope/myscope/Spri ng-beans.xml"); Pessoa p1 = (Pessoa)bf.getBean("pessoa1"); Pessoa p2 = (Pessoa)bf.getBean("pessoa2"); Pessoa p3 = (Pessoa)bf.getBean("pessoa3"); Pessoa p4 = (Pessoa)bf.getBean("pessoa4"); System.out.println("Todas as pessoas: " + ThreadLocalScope.tl.get()); p3.setNome("Spider-Pig"); System.out.println("Todas as pessoas: " + ThreadLocalScope.tl.get()); } }

Cdigo 2.20 Classe de testesTestScopes.java.


<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd" default-lazy-init="false" > <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="threadLocal"> <bean class="com.targettrust.spring.scope.myscope.ThreadLocalScope"/> </entry> </map> </property> </bean> <bean id="pessoa1" class="com.targettrust.spring.scope.myscope.Pessoa" scope="threadLocal" > <property name="nome" value="Diego Pacheco"/> </bean> <bean id="pessoa2" class="com.targettrust.spring.scope.myscope.Pessoa"

Diego Pacheco http://diego-pacheco.blogspot.com

2-24

Spring Framework Framework para desenvolvimento de aplicaes java

scope="threadLocal" > <property name="nome" value="Rod Johnson"/> </bean> <bean id="pessoa3" class="com.targettrust.spring.scope.myscope.Pessoa" scope="threadLocal" > <property name="nome" value="Juergen Hoeller"/> </bean> <bean id="pessoa4" class="com.targettrust.spring.scope.myscope.Pessoa" scope="singleton" > <property name="nome" value="Ninguem me viu!!!"/> </bean> </beans>

Cdigo XML 2.6 Spring-beans.xml scope customizado.


package com.targettrust.spring.scope.myscope; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.Scope; public class ThreadLocalScope implements Scope{ public static ThreadLocal<Map<String, Object>> tl; public ThreadLocalScope() { tl = new ThreadLocal<Map<String,Object>>(); tl.set(new HashMap<String, Object>()); } @Override public Object get(String name, ObjectFactory objectFactory) { synchronized(tl){ Object realTarget = objectFactory.getObject(); if (realTarget instanceof Pessoa){ tl.get().put(realTarget.hashCode() + ";", realTarget); return realTarget; } throw new RuntimeException("Esse scopo s pode ser utilizado para objetos Pessoa "); } } @Override public Object remove(String name) { synchronized(tl){ Object obj = tl.get().remove(name);

Diego Pacheco http://diego-pacheco.blogspot.com

2-25

Spring Framework Framework para desenvolvimento de aplicaes java

return obj; } } @Override public void registerDestructionCallback(String name, Runnable callback){ throw new UnsupportedOperationException("Essa operao de registerDestructionCallback, no suportada!"); } @Override public String getConversationId() { return null; } }

Cdigo 2.21 ThreadLocalScope.java classe de scope customizada.

Para criar um scopo personalizado no Spring necessrio implementar a interface org.springframework.beans.factory.config.Scope, a implementao dessa interface simples, basicamente s precisamos nos preocupar com os mtodos get e remove. Aps a implementao dessa interface s ser necessrio registrar no spring o seu novo scopo, isso feito com a seguinte configurao em xml:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="threadLocal"> <bean class="com.targettrust.spring.scope.myscope.ThreadLocalScope"/> </entry> </map> </property> </bean>

Cdigo XML 2.7 Definio de scope customizado.

Diego Pacheco http://diego-pacheco.blogspot.com

2-26

Spring Framework Framework para desenvolvimento de aplicaes java

Injeo via setter

Essa uma das duas formas que o Spring faz injeo de dependncias, ele utiliza um mtodo setter conforme padro da Sun e atravs desse mtodo setta os valores no objeto em questo.
package com.targettrust.spring.setter; public class Aluno { private private private private String nome; Integer idade; boolean desconto; Character sexo;

public Aluno() {} public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public Integer getIdade() { return idade; } public void setIdade(Integer idade) { this.idade = idade; } public boolean isDesconto() { return desconto; } public void setDesconto(boolean desconto) { this.desconto = desconto; } public Character getSexo() { return sexo; } public void setSexo(Character sexo) { this.sexo = sexo; } @Override public String toString() { return "nome: " + nome + " idade: " + idade + " desconto: " + desconto + " sexo: " + sexo; } }

Cdigo 2.22 Aluno.java.


Diego Pacheco http://diego-pacheco.blogspot.com 2-27

Spring Framework Framework para desenvolvimento de aplicaes java

<?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-2.0.xsd" default-lazy-init="true" > <bean id="aluno" class="com.targettrust.spring.setter.Aluno" > <property name="nome" value="Diego" /> <property name="idade" value="22" /> <property name="desconto" value="true" /> <property name="sexo" value="M" /> </bean> </beans>

Cdigo XML 2.8 Configurao de injeo via setter


package com.targettrust.spring.setter; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSetter { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/setter/Springbeans.xml"); System.out.println(bf.getBean("aluno")); } }

Cdigo 2.23 TestSetter.java

No existe nada de mgico na injeo via setter, simples, basta ter o mtodo setter e o tipo de dado injetado ser o mesmo.

Diego Pacheco http://diego-pacheco.blogspot.com

2-28

Spring Framework Framework para desenvolvimento de aplicaes java

Injeo via construtor


Esta a outra forma de injeo de dependncia do Spring. As dependncias so injetadas atravs de um construtor. Considere a seguinte classe Java:
package com.targettrust.spring.constructor; public class Pessoa { private String nome; private Integer idade; private boolean cartaMorotista; public Pessoa(String nome, Integer idade, boolean cartaMorotista) { super(); this.nome = nome; this.idade = idade; this.cartaMorotista = cartaMorotista; } @Override public String toString() { return " nome: " + nome + " idade: " + idade + " morotista: " + cartaMorotista; } }

Cdigo 2.24 Pessoa.java Para injetarmos nome, idade, cartaMotorista, s efetuar essa injeo via construtor no XML de configurao do Spring, conforme cdigo XML 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" > <bean id="pessoa" class="com.targettrust.spring.constructor.Pessoa" > <constructor-arg value="Diego Pacheco" /> <constructor-arg value="22" /> <constructor-arg value="false" /> </bean> </beans>

Cdigo XML 2.9 Configurao de injeo via construtor

Diego Pacheco http://diego-pacheco.blogspot.com

2-29

Spring Framework Framework para desenvolvimento de aplicaes java

Para ver a injeo funcionando considere a classe de testes abaixo:


package com.targettrust.spring.constructor; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestConstructor { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/constructor/Spring -beans.xml"); System.out.println(bf.getBean("pessoa")); } }

Cdigo 2.25 TestConstructor.java Teste de construtor

Ao rodar esses cdigos voc ter um retorno semelhante a este:

nome: Diego Pacheco idade: 22 motorista: false

Caso voc tenha um construtor que receba uma String e um nmero, o Spring pode acabar sentando valores indesejados, para resolver esse tipo de situao, podemos especificar o tipo do argumento do construtor, conforme exemplo de XML abaixo.
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>

Cdigo XML 2.10 Exemplo de tipo de argumento para construtor.

Diego Pacheco http://diego-pacheco.blogspot.com

2-30

Spring Framework Framework para desenvolvimento de aplicaes java

Uma outra opo seria informar qual a posio do parmetro no construtor, isso ns chamamos de index, comea em zero(0), como segue o exemplo:
<bean id="animal" class="com.targettrust.spring.constructor.Animal" > <constructor-arg index="1" <constructor-arg index="0" </bean> value="Black" /> value="Dog" />

Cdigo XML 2.11 Exemplo de tipo de argumento para construtor com index.

Injeo de colees
Por deafult o Spring possui tags especficas para injeo de colees, possvel injetar: Map, List, Properties e Set. De fato podemos injetar qualquer Collection, mas para injetar uma coleo que no seja uma das citadas, ser necessrio usar um Custon Property Editor. Para fazer as injees das colees nativas do Spring, utilizamos as tags: <map/>, <list/>, <set/> e <props/>. Considerando o seguinte exemplo:
<?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-2.0.xsd" > <bean id="estadio" class="com.targettrust.spring.collection.Estadio" > <property name="pessoas"> <set> <value>Diego</value> <value>Rod</value> <value>Alef</value> </set> </property> <property name="cadeiras"> <map> <entry> <key><value>1</value></key> <value>diego</value> </entry> <entry> <key><value>2</value></key> <value>Rod</value>

Diego Pacheco http://diego-pacheco.blogspot.com

2-31

Spring Framework Framework para desenvolvimento de aplicaes java

</entry> </map> </property> <property name="vededoresPipoca"> <list> <value>Ze</value> <value>JoZe</value> <value>MaisEh</value> </list> </property>

<property name="detalhes"> <value> estadio.luz=forte estadio.taman.hq.full=grande estadio.fundac.since=10/10/2001 estadio.status.now=ativo </value> </property> </bean> </beans>

Cdigo XML 2.12 Exemplo de injeo de collections.

Para esse cdigo de injees de colees em XML precisamos de uma classe Java, conforme a definida a baixo:
package com.targettrust.spring.collection; import import import import java.util.List; java.util.Map; java.util.Properties; java.util.Set;

public class Estadio { private private private private Set<String> pessoas; Map<Integer, String> cadeiras; List<String> vededoresPipoca; Properties detalhes;

public Estadio() {} public Set<String> getPessoas() { return pessoas; } public void setPessoas(Set<String> pessoas) { this.pessoas = pessoas; }

Diego Pacheco http://diego-pacheco.blogspot.com

2-32

Spring Framework Framework para desenvolvimento de aplicaes java

public Map<Integer, String> getCadeiras() { return cadeiras; } public void setCadeiras(Map<Integer, String> cadeiras) { this.cadeiras = cadeiras; } public List<String> getVededoresPipoca() { return vededoresPipoca; } public void setVededoresPipoca(List<String> vededoresPipoca) { this.vededoresPipoca = vededoresPipoca; } public Properties getDetalhes() { return detalhes; } public void setDetalhes(Properties detalhes) { this.detalhes = detalhes; } @Override public String toString() { return " pessoas: " + pessoas + "\n" + " cadeiras: " + cadeiras + "\n" + " Vededores de Pipoca: " + vededoresPipoca + "\n" + " detalhes: " + detalhes; } }

Cdigo 2.26 Estadio.java Classe que usa Collections.

Podemos testar esses recursos atravs do teste abaixo:


package com.targettrust.spring.collection; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestCollections { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/collection/Springbeans.xml"); System.out.println(bf.getBean("estadio")); } }

Cdigo 2.26 TestCollections.java Classe de testes.

Diego Pacheco http://diego-pacheco.blogspot.com

2-33

Spring Framework Framework para desenvolvimento de aplicaes java

Existem outras vriaveis para a injeo de properties, no exemplo acima foi utilizada a forma mais simplificada, mas poderamos fazer da forma completa, conforme exemplo abaixo:
<property name="detalhes"> <props> <prop key="estadio.luz">forte</prop> <prop key="estadio.taman.hq.full">grande</prop> <prop key="estadio.fundac.since">10/10/2001</prop> <prop key="estadio.status.now">ativo</prop> </props> </property>

Cdigo XML 2.13 Outra forma de injeo de Properties.

Dica: Se for explicitamente necessrio injetar uma coleo nula, ou settar null em alguma propriedade de algum bean do Spring, podemos utilizar a tag <null/>.

Podemos injetar qualquer tipo de coleo atravs do uso de property editors, essa uma soluo muito elegante do Spring. Quando registramos um editor do tipo Class, por exemplo, toda vez que o Spring for injetar um valor em um objeto que a propriedade seja Class ele vai invocar esse property editor. Veja como usar a Collection do Tipo LinkedList no exemplo abaixo:
package com.targettrust.spring.collection; import java.util.LinkedList; public class Cidade { private LinkedList<String> ruas; public Cidade() {} public LinkedList<String> getRuas() { return ruas; } public void setRuas(LinkedList<String> ruas) { this.ruas = ruas; } }

Cdigo 2.27 Cidade.java Classe que usa LinkedList.

Diego Pacheco http://diego-pacheco.blogspot.com

2-34

Spring Framework Framework para desenvolvimento de aplicaes java

<?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-2.0.xsd" > <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer" > <property name="customEditors"> <map> <entry key="java.lang.Class"> <bean class="org.springframework.beans.propertyeditors.ClassEditor" /> </entry> <entry key="java.util.LinkedList"> <bean class="org.springframework.beans.propertyeditors.CustomCollectionEditor"> <constructor-arg index="0"><value>java.util.LinkedList</value></constructor-arg> <constructor-arg index="1"><value>true</value></constructor-arg> </bean> </entry> </map> </property> </bean> <bean id="cidade" class="com.targettrust.spring.collection.Cidade" > <property name="ruas"> <list> <value>1</value> <value>2</value> <value>3</value> </list> </property> </bean> </beans>

Cdigo XML 2.14 Uso de PropertyEditors.

Nesse exemplo foi registrado um property editor de class, chamado: org.springframework.beans.propertyeditors.ClassEditor, que est associado ao tipo Class. Esse property editor necessrio para o property editor de Collections: org.springframework.beans.propertyeditors.CustomCollectionEditor. O Property editor de Collections tem dois parmetros no construtor, o primeiro a classe que a collection deve ser, e o segundo um boolean indicando se deve ser convertido para null uma coleo vazia.
Diego Pacheco http://diego-pacheco.blogspot.com 2-35

Spring Framework Framework para desenvolvimento de aplicaes java

Injeo entre beans colaboradores

No Spring so chamados de beans colaboradores todo objeto que criado por voc, como por exemplo, um objeto de negcio e que deve ser injetado em outro objeto, em sntese o ato de injetar um pojo em outro. No existe nada de mgico nisso, alm de simples muito usual, talvez a funcionalidade mais simples do container IoC do Spring, porm a mais utilizada junto com as injees por setter. A injeo de colaboradores feita atravs de setters ou construtor como as outras injees vistas anteriormente.
package com.targettrust.spring.colaboradores; public class Cidade { private String nome; public Cidade() {} public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } @Override public String toString() { return nome; } }

Cdigo 2.28 Cidade.java Classe colaboradora.


package com.targettrust.spring.colaboradores; import java.util.List; public class Estado { private String sigla; private List<Cidade> cidades; public Estado() {} public String getSigla() { return sigla; } public void setSigla(String sigla) { this.sigla = sigla; }

Diego Pacheco http://diego-pacheco.blogspot.com

2-36

Spring Framework Framework para desenvolvimento de aplicaes java

public List<Cidade> getCidades() { return cidades; } public void setCidades(List<Cidade> cidades) { this.cidades = cidades; } @Override public String toString() { return sigla + " cidades: " + cidades; } }

Cdigo 2.28 Estado.java Classe que utiliza a colaboradora.

Diego Pacheco http://diego-pacheco.blogspot.com

2-37

Spring Framework Framework para desenvolvimento de aplicaes java

<?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-2.0.xsd" > <bean id="cidA" class="com.targettrust.spring.colaboradores.Cidade" > <property name="nome"><value>Porto Alegre</value></property> </bean> <bean id="cidB" class="com.targettrust.spring.colaboradores.Cidade" > <property name="nome"><value>Gravata</value></property> </bean> <bean id="estado" class="com.targettrust.spring.colaboradores.Estado" > <property name="sigla" value="RS" /> <property name="cidades"> <list> <ref bean="cidA" /> <ref local="cidB" /> <bean class="com.targettrust.spring.colaboradores.Cidade"> <property name="nome" value="Canoas" /> </bean> </list> </property> </bean> </beans>

Cdigo XML 2.15 Injees de colaboradores.

Diego Pacheco http://diego-pacheco.blogspot.com

2-38

Spring Framework Framework para desenvolvimento de aplicaes java

Nesse exemplo foi injetado uma java.util.List de Cidades no objeto Estado. Podemos reutilizar injees com a tag ref. Quando usamos ref com bean estamos criando a possibilidade de acessar qualquer bean do contexto do Spring em qualquer XML de configurao. Quando utilizado o atributo local s podemos utilizar os beans que esto no mesmo XML, se o bean em questo estiver em outro XML, um erro ser levantado. Podemos ver o resultado dessas classes em ao no teste abaixo:
package com.targettrust.spring.colaboradores; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestColaboradores { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/colaboradores/Spri ng-beans.xml"); System.out.println(bf.getBean("estado")); } }

Cdigo 2.29 TestColaboradores.java Teste de colaboradores.

Diego Pacheco http://diego-pacheco.blogspot.com

2-39

Spring Framework Framework para desenvolvimento de aplicaes java

Instanciando o contexto Web


O Spring tem uma factory especfica para a utilizao do framework em ambiente servlet/JEE. possvel utilizar o listener org.springframework.web.context.ContextLoaderListener ou o Servlet org.springframework.web.context.ContextLoaderServlet. Basta configurar isso no web.xml de sua aplicao, conforme exemplo abaixo:
<?xml version="1.0" encoding="UTF-8"?> <web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/Spring-beans.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- ou use o ContextLoaderServlet ou invs de usar o listener acima. <servlet> <servlet-name>context</servlet-name> <servletclass>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> --> </web-app>

Cdigo XML 2.16 web.xml. Agora s criar um bean no Spring para podermos utilizar esse contexto web. Nesse exemplo ser criado o DateService que um service que ir prover a data atual. Observe o cdigo abaixo:
package com.targettrust.spring.web; public class DateService { public String getDate(){ System.out.println("Provendo servio de data"); return new java.util.Date().toString(); } }

Cdigo 2.23 DateService.java.

Agora necessrio fazer as configuraes desse bean no contexto do Spring, confira isso no XML abaixo:

Diego Pacheco http://diego-pacheco.blogspot.com

2-40

Spring Framework Framework para desenvolvimento de aplicaes java

<?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-2.0.xsd" > <bean id="dateService" class="com.targettrust.spring.web.DateService" /> </beans>

Cdigo XML 2.17 Spring-beans.xml.

Para testar, vamos empacotar essa aplicao em um arquivo war. Para fazer esse teste vamos chamar o servio do Spring atravs de uma pgina jsp. Confira o cdigo abaixo:
<%@page language="java" contentType="text/html; charset=ISO-8859-1"%> <%@page import="org.springframework.web.context.support.WebApplicationContextUtils "%> <%@page import="com.targettrust.spring.web.DateService"%> <html> <title>Spring WEB</title> <body> <center><h2>Exemplo de Spring com WEB-Tier</h2></center><br> A Data atual : <%=((DateService)WebApplicationContextUtils.getWebApplicationContext(getSe rvletConfig().getServletContext()).getBean("dateService")).getDate()%> </body> </html>

Cdigo 2.23 index.jsp.

usado um utilitrio do Spring para acessar o contexto dele atravs de uma pgina jsp. Atravs da classe org.springframework.web.context. support.WebApplicationContextUtils ns obtemos o contexto do Spring. Utilizamos o mtodo getWebApplicationContext passando como parmetro o ServletContext.

Diego Pacheco http://diego-pacheco.blogspot.com

2-41

Spring Framework Framework para desenvolvimento de aplicaes java

Exerccios

1. Faa a injeo de um objeto Cliente em um Objeto Vendedor. 2. Faa a injeo de uma Lista de Alunos em um Objeto Turma. 3. Faa a injeo de um Mapa de UF com uma Lista de Cidades. 4. Faa a injeo de um UF em um objeto Pas atravs de constructor injection. 5. Faa um Servio de Calculadora e injete funes matemticas nesse bean.

Diego Pacheco http://diego-pacheco.blogspot.com

2-42

Spring Framework Framework para desenvolvimento de aplicaes java

Espao para anotaes

Diego Pacheco http://diego-pacheco.blogspot.com

2-43

Spring Framework Framework para Desenvolvimento de Aplicaes Java

3. Manipulao de Beans

Diego Pacheco http://diego-pacheco.blogspot.com

Spring Framework Framework para desenvolvimento de aplicaes java

Objetivos

Conhecer os Resource Loaders do Spring; Saber utilizar o init-method; Saber utilizar a herana de definies de beans; Saber fazer classes de validaes; Saber utilizar Bean Wrapper; Conhecer os PostProcessors do Spring; Conhecer os principais property editors; Conhecer os Eventos do container; Saber utilizar o PropertyPlaceholderConfigurer; Saber utilizar SingletonBeanFactoryLocator; Conhecer os recursos de Internacionalizao.

Diego Pacheco http://diego-pacheco.blogspot.com

3-2

Spring Framework Framework para desenvolvimento de aplicaes java

Resource Loaders

Quando usamos arquivos de configuraes como, por exemplo, xml, txt, arquivos de imagem, properties, etc fortemente recomendado o uso de ResourceLoader que uma interface do Spring que define a estratgia para carregar arquivos. O Spring prove uma especializao dessa interface que a classe ResourcePatternResolver que adiciona facilidades como patterns de estilo ant, podemos usar wild cards como, por exemplo: WEB-INF/*-context.xml. Podemos utilizar a classe ServletContextResourceLoader que faz a busca de recursos no ServletContext. As BeanFactorys do Spring como, por exemplo: ClassPathXmlApplicationContext implementa ResourceLoader atravs de classes em sua hierarquia superior. Em sntese, as outras Beans factories do Spring tambm implementam essa interface ResourceLoader. Considerando a injeo do seguinte bean. <property name="arquivo" value="classpath:caminho/completo/dados.txt"> Cdigo XML 3.1 injeo de resource Nesse cdigo XML acima utilizando um facilitador o classpath: atravs dessa diretiva, instrumos o ResourceLoader a carregar esse arquivo que esteja em qualquer lugar no classpath. Poderamos utilizar o facilitador file: para carregar arquivos que no esto no classpath da aplicao. Exemplo:

<property name="arquivo" value="file:/dados/caminho/completo/da dos.txt"> Cdigo XML 3.2 injeo de resource fora do classpath Esse facilitador tambm pode ser utilizado para carregar arquivos que esto no classpath, mas para esse caso mais recomendado o uso de classpath:. Nesse tipo de cenrio se utiliza file: quando existem mais de um arquivo com o mesmo nome.

Podemos utilizar wild cards no stilo ant, segue alguns exemplos:


/WEB-INF/*-context.xml com/mycompany/**/applicationContext.xml file:C:/some/path/*-context.xml classpath:com/mycompany/**/applicationContext.xml

Cdigo de exemplos wild cards

Diego Pacheco http://diego-pacheco.blogspot.com

3-3

Spring Framework Framework para desenvolvimento de aplicaes java

Init-Metohd e InitializingBean
O Spring prove alguns mecanismos de call back aps a inicializao de um bean. Aps o container de IoC do Spring resolver as injees de dependncias ele prove um Call Back, ou seja, ele pode estar invocando um mtodo em sua classe e a partir desse mtodo voc realiza algum processamento. Essa operao pode ser configurada atravs da propriedade init-method. Essa soluo elegante, pois no gera acoplamento entre o cdigo do Spring e seu cdigo. Veja isso na prtica no exemplo abaixo:
package com.targettrust.spring.init; import java.util.Date; public class HoraCertaService { private Date data; private String pais; public HoraCertaService() { System.out.println("Criando Bean de HoraCertaService "); } public void preparar(){ data = new Date(); System.out.println("Ajustado a hora para o pais: " + pais); } @SuppressWarnings("deprecation") public String getHoraCerta(){ return pais + " -> " + data.getHours() + ":" + data.getMinutes() + ":" + data.getSeconds(); }

public void setPais(String pais) { this.pais = pais; } }

Cdigo 3.1 HoraCertaService.java


<?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-2.0.xsd" > <bean id="horaCertaService" class="com.targettrust.spring.init.HoraCertaService" init-method="preparar" > <property name="pais" value="Brasil" /> </bean>

Diego Pacheco http://diego-pacheco.blogspot.com

3-4

Spring Framework Framework para desenvolvimento de aplicaes java

</beans>

Cdigo XML 3.2 injeo com uso de init-method


package com.targettrust.spring.init; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/init/Springbeans.xml"); HoraCertaService bean = (HoraCertaService)bf.getBean("horaCertaService"); System.out.println("Hora: " + bean.getHoraCerta()); } }

Cdigo 3.2 Testjava

Existem outras formas de utilizar Call back no Spring, porm menos elegantes, pois acoplam o cdigo do Spring com o de sua aplicao. Uma possibilidade seria utilizar a interface org.springframework.beans. factory.InitializingBean essa interface possui o mtodo afterPropertiesSet(). Esse mtodo invocado pela BeanFactory do Spring aps todas as dependncias serem resolvidas.

Assim como existe a propriedade init-method existe a propriedade destroymethod que um Call Back para quando o container destrudo. possvel utilizar uma interface para esse Call Back, a interface org.springframework.beans.factory. DisposableBean essa interface contm o

Diego Pacheco http://diego-pacheco.blogspot.com

3-5

Spring Framework Framework para desenvolvimento de aplicaes java

mtodo destroy(). Esse mtodo ser invocado no momento da destruio do contexto do Spring.

Diego Pacheco http://diego-pacheco.blogspot.com

3-6

Spring Framework Framework para desenvolvimento de aplicaes java

Herana de Definies

Em uma aplicao orientada a objetos utilizamos com freqncia os recursos de herana, a partir de um objeto pai nasce um objeto filho que herda os mtodos e propriedades de seu pai. O Spring framework prove mecanismos para herana de injees. Considere o seguinte Service:
package com.targettrust.spring.extend; public abstract class PessoaService { private String nome; private String telefone; private String email; public PessoaService() {} public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getTelefone() { return telefone; } public void setTelefone(String telefone) { this.telefone = telefone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

Cdigo 3.3 PessoaService.java

Essa uma Service (Classe de regra de negcios) que representa operao sobre uma pessoa, aqui temos um exemplo simplrio, no usual ter propriedades como nome e telefone em um Service, normalmente se utiliza isso em pojos. Mas como exemplo de herana de definies valido.
package com.targettrust.spring.extend; public class PessoaFisicaService extends PessoaService {

Diego Pacheco http://diego-pacheco.blogspot.com

3-7

Spring Framework Framework para desenvolvimento de aplicaes java

private String cpf; public PessoaFisicaService() {} public boolean validaCpf(){ return CpfUtils.validaCPF(cpf); } public void mostraPessoa(){ if (validaCpf()){ System.out.println("nome: " + getNome() + " telefone: " + getTelefone() + " email: " + getEmail() + " cpf: " + cpf); }else{ System.out.println("Essa pessoa no tem um CPF Valido."); } } public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } }

Cdigo 3.4 PessoaFisicaService.java

Em PessoaFisicaService adicionamos a propriedade cpf e mtodos como validaCpf e mostra pessoa, que ira mostrar a pessoa com seus dados caso o cpf seja vlido. Foi utilizada a classe CpfUtils para fazer a validao do CPF, voc pode verificar os fontes no projeto do eclipse que acompanha a apostila.

Para fazer a herana de definies no Spring necessrio existir uma estrutura de herana. Utilizamos as propriedades abstract e parent para fazer a herana. Veja isso na prtica no XML de configuraes seguinte:
<?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-2.0.xsd" > <bean id="pessoaService" class="com.targettrust.spring.extend.PessoaService" abstract="true" > <property name="nome" value="Diego" /> <property name="email"

Diego Pacheco http://diego-pacheco.blogspot.com

3-8

Spring Framework Framework para desenvolvimento de aplicaes java

value="pacheco@diego.com.spring" /> <property name="telefone" value="455-55-55" /> </bean> <bean abstract="false" id="pessoaFisicaService" class="com.targettrust.spring.extend.PessoaFisicaService" parent="pessoaService" > <property name="cpf" value="47888971210" /> </bean> </beans>

Cdigo XML 3.3 injeo com uso de herana.

Para testar podemos utilizar a classe de testes a baixo:


package com.targettrust.spring.extend; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/extend/Springbeans.xml"); PessoaFisicaService bean = (PessoaFisicaService)bf.getBean("pessoaFisicaService"); bean.mostraPessoa(); } }

Cdigo 3.5 Teste.java

OBS: o atributo abstract=true apenas uma demarcao no Spring e no obrigatorio que sua classe seja abstrata.

Diego Pacheco http://diego-pacheco.blogspot.com

3-9

Spring Framework Framework para desenvolvimento de aplicaes java

Validao

Em uma aplicao ter injees de dependncias pode no ser suficiente, necessrio validar. O spring prove mecanismos de validao atravs da interface org.springframework.validation. Validator. Essa interface trabalha com um objeto de erro e podemos ver um relatrio de erros posteriormente. Essa interface pode ser usada em conjunto com um outro framework do portiflio do Spring, o Spring MVC, atravs de uma tag, pode mostrar os erros de validao de forma elegante em uma pagina JSP. A Interface Validator tem os seguintes mtodos: boolean supports(Class clazz); void validate(Object target, Errors errors); No mtodo supports deve-se retornar true se o validador que estamos construindo tem suporte para o Class passado por parmetro. Normalmente se faz um equals aqui com o parmetro e a classe que o validador ser responsvel. O mtodo validate ir validar os dados de fato, caso seja necessrio retornar error, isso ser feito atravs do objeto de errors. Veja o exemplo prtico a seguir:
package com.targettrust.spring.validate; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; public class Pessoa implements Validator{ private String nome; private Integer idade; public Pessoa() {} @Override @SuppressWarnings("unchecked") public boolean supports(Class clazz) { return Pessoa.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "nome", "nome.vazio"); Pessoa p = (Pessoa) target; if (p.getIdade() < 0) { errors.rejectValue("idade", "valor negativo"); } else if (p.getIdade() > 120) { errors.rejectValue("idade", "velho demais"); } } public String getNome() {

Diego Pacheco http://diego-pacheco.blogspot.com

3-10

Spring Framework Framework para desenvolvimento de aplicaes java

return nome; } public void setNome(String nome) { this.nome = nome; } public Integer getIdade() { return idade; } public void setIdade(Integer idade) { this.idade = idade; } }

Cdigo 3.6 Pessoa.java e classe de validao


<?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-2.0.xsd" default-lazy-init="true" > <bean id="pessoa" class="com.targettrust.spring.validate.Pessoa" > <property name="nome" value="Fulano" /> <property name="idade" value="-1" /> </bean> </beans>

Cdigo XML 3.4 injeo com uso de validator


package com.targettrust.spring.validate; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.Errors; public class Teste { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext( "/com/targettrust/spring/validate/Spring-beans.xml"); Pessoa p = (Pessoa) bf.getBean("pessoa"); System.out.println("Nome: " + p.getNome() + " idade: " + p.getIdade()); Errors e = new BeanPropertyBindingResult(p,"Pessoa"); p.validate(p, e);

Diego Pacheco http://diego-pacheco.blogspot.com

3-11

Spring Framework Framework para desenvolvimento de aplicaes java

for(Object es: e.getAllErrors()){ System.out.println(es); } } }

Cdigo 3.7 Teste.java

Nesse exemplo, a partir de uma classe Pessoa foi construdo um Validator para validar o objeto. Esse validator est na mesma classe Pessoa, seria possvel colar esse cdigo de validao em outra classe tambm. Foi utilizado uma classe utilitria do Spring que a ValidateUtils que j tem alguns mtodos que facilitam a validao. Para o teste foi instanciado um objeto de Erro e passado esse objeto para o mtodo de validao, e no final foi iterado todos os erros e mostrado no console as mensagens de erros. Nos prximos captulos essa questo ser abordada com outra roupagem na questo dos interceptors do Spring.

Diego Pacheco http://diego-pacheco.blogspot.com

3-12

Spring Framework Framework para desenvolvimento de aplicaes java

Bean Wrapper

Bean Wrapper um recurso do Spring que funciona com Java beans como o prprio nome j diz, Java beans um especificao da Sun que define se um determinado objeto deve ter um construtor vazio e mtodos getters e setters de acordo com o padro da Sun camelCase. Essa funcionalidade na verdade um pattern do GOF que se chama decorator. Que tambem conhecido como Wrapper que significa empacotar, no caso ns temos uma camada de adiciona um funcionalidade adicional a algo existente.

BeanWrapper uma interface do Spring que prove funcionalidades de get e set em propriedades e propriedades de consulta que podem determinar se a propriedade pode ser escrita ou lida. Tambm possibilita setar propriedades e subpropriedades de uma profundidade ilimitada. Outra funcionalidade adicionar listeners para quando alguma propriedade mudar de valor.

Esse recurso pode ser utilizado para fazer manipulaes com propriedades de objetos de maneira elegante. Tambm usual para fazer algum tipo de bind em sua aplicao. Confira como codificar abaixo:
package com.targettrust.spring.beanwrapper; public class Funcionario { private String nome; private Long salario; public Funcionario() {} public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public Long getSalario() { return salario; } public void setSalario(Long salario) { this.salario = salario; } @Override public String toString() { return "Funcionario[ nome: " + nome + " , salario: " + salario + " ]";

Diego Pacheco http://diego-pacheco.blogspot.com

3-13

Spring Framework Framework para desenvolvimento de aplicaes java

} }

Cdigo 3.8 Funcionario.java


package com.targettrust.spring.beanwrapper; public class Empresa { private String nome; private Funcionario gestor; public Empresa() {} public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public Funcionario getGestor() { return gestor; } public void setGestor(Funcionario gestor) { this.gestor = gestor; } @Override public String toString() { return "Empresa [ " + nome + " | " + gestor.toString() + " ]"; } }

Cdigo 3.9 Empresa.java


<?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-2.0.xsd" > <bean id="gestor" class="com.targettrust.spring.beanwrapper.Funcionario" > <property name="nome" value="Joo" /> <property name="salario" value="100" /> </bean> <bean id="empresa" class="com.targettrust.spring.beanwrapper.Empresa" > <property name="nome" value="CromFactory" /> <property name="gestor" ref="gestor" />

Diego Pacheco http://diego-pacheco.blogspot.com

3-14

Spring Framework Framework para desenvolvimento de aplicaes java

</bean> </beans>

Cdigo XML 3.5


package com.targettrust.spring.beanwrapper; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { BeanFactory bf = new ClassPathXmlApplicationContext("/com/targettrust/spring/beanwrapper/Sprin g-beans.xml"); System.out.println(bf.getBean("empresa")); BeanWrapper company = new BeanWrapperImpl((Empresa)bf.getBean("empresa")); company.setPropertyValue("nome", "Target Trust"); // ou pode ser algo assim PropertyValue value = new PropertyValue("nome", "Some Company Inc."); company.setPropertyValue(value); BeanWrapper diego = new BeanWrapperImpl((Funcionario)bf.getBean("gestor")); diego.setPropertyValue("nome", "Diego Pacheco"); company.setPropertyValue("gestor", diego.getWrappedInstance()); Long sal = (Long) company.getPropertyValue("gestor.salario"); System.out.println("Salrio: " + sal); System.out.println(company); System.out.println(company.getWrappedInstance()); // verifica o tipo da propriedade salario System.out.println(((BeanWrapperImpl)company).getPropertyDescriptor ("gestor.salario").getPropertyType()); diego.setPropertyValue("salario",200L); System.out.println(diego.getPropertyValue("salario")); } }

Cdigo 3.10 Teste.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-15

Spring Framework Framework para desenvolvimento de aplicaes java

No exemplo acima criado uma instncia de BeanWrapperImpl a partir do bean empresa e outra BeanWrapperImpl a partir do bean gestor. Com os mtodos getPropertyValue e setPropertyValue podemos modificar os valores dos objetos. Para acessar objeto real utilizamos o mtodo getWrappedInstance. Outra maneira de acessar as propriedades do objeto atravs do objeto PropertyValue, porm ainda precisamos de uma instncia de BeanWrapper.

As propriedades desse objeto podem ser acessadas com infinita profundidade, por exemplo: supondo que temos um objeto Pessoa que tem um objeto Brinquedo que tem uma propriedade tamanho, poderamos acessar essa propriedade da seguinte maneira: beanWrapperInstancePessoa.getPropertyValue("brinquedo.tamanho"), supondo que temos uma instncia de BeanWrapper com a varivel beanWrapperInstancePessoa. Outros exemplos de acesso com propriedades:

Expresso nome conta.valor

Descrio Corressponde a propriedade nome do objeto empacotado, ir tentar executar um getNome() ou isNome() Indica que no objeto corrente existe uma propriedade conta que tem uma propriedade valor, executa algo como: getConta().getValor() Acessa a segunda posio da propriedade filhos sendo que filhos pode ser um array ou List ou qualquer outra collection ordenada. Indica que est sendo acessado a entrada poa em uma Map chamado estado.

filhos[2]

estado[poa]

Diego Pacheco http://diego-pacheco.blogspot.com

3-16

Spring Framework Framework para desenvolvimento de aplicaes java

BeanPostProcessors

Esse um recurso para customizar beans atravs de call-backs. Que nada mais so do que mtodos a serem invocados aps determinada operao ser executada, tambm conhecidos na literatura computacional como ganchos. Voc pode utilizar esse recurso para estender as operaes padro do Spring para: lgica de instanciao, lgica de resoluo de dependncias e tambm se necessrio para operaes aps o container do Spring finalizar suas criaes de objetos. Voc pode configurar mltiplos BeanPostProcessors se desejar assim, possvel configurar a ordem que cada um ir rodar a partir da propriedade order, mas isso s ser possvel se voc implementar a interface Ordered. Existe uma forte recomendao por parte dos criadores do Spring que voc faa essa implementao. A atuao do BeanPostProcessors aps a criao do bean do Spring, se desejarmos mudar sua definio necessrio utilizar BeanFactoryPostProcessor que ser abordado no prximo tpico. Aps cada criao de um bean no container o Spring estar invocando o BeanPostProcessor, isso significa que ser executado antes de qualquer mtodo initbean. Existe uma diferena de se usar BeanPostProcessor com BeanFactory e com ApplicationContext, por que no caso da ApplicationContex o Spring ir descobrir todos os BeanPostProcessors e registrar automaticamente para voc, j em outra linha, a Bean Factory no far nada disso, devemos registr-los manualmente. Conforme o cdigo abaixo:
ConfigurableBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml")); MeuBeanPostProcessor postProcessor = new MeuBeanPostProcessor(); factory.addBeanPostProcessor(postProcessor);

Cdigo 3.11 Exemplo de registro de BeanPostProcessor.

Diego Pacheco http://diego-pacheco.blogspot.com

3-17

Spring Framework Framework para desenvolvimento de aplicaes java

Esse tipo de Registro no conveniente, por causa disso que para muitas aplicaes as pessoas preferem utilizar ApplicationContex ao invs de BeanFactory. Classes que implementam BeanPostProcessor so classes especiais, logo so tratadas de maneira diferente pelo container. Todas as BenPostProcessors e aqueles beans que estejam diretamente referenciados por eles sero instanciados ao startup do Spring. Os recursos de AOP auto-proxing so implementados como BeanPostProcessor, nenhum BeanPostProcessor ou beans diretamente referenciados sero elegveis para auto-proxy, ou seja, no haver aspectos sobre eles. O Spring ir lhe alertar sobre essa situao com uma mensagem semelhante a essa: Bean 'foo' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Veja um exemplo prtico de como utilizar este recurso:
package com.targettrust.spring.beanpostprocessors; public class ObjetoA { }

Cdigo 3.12 ObjetoA.java


package com.targettrust.spring.beanpostprocessors; public class ObjetoB { }

Cdigo 3.13 ObjetoB.java


package com.targettrust.spring.beanpostprocessors; public class ObjetoC { }

Cdigo 3.14 ObjetoC.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-18

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.beanpostprocessors; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class LogCreationBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("Craindo bean: " + beanName); return bean; } }

Cdigo 3.15 LogCreationBeanPostProcessor.java


<?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-2.0.xsd" default-lazy-init="false" > <bean id="a" class="com.targettrust.spring.beanpostprocessors.ObjetoA" /> <bean id="b" class="com.targettrust.spring.beanpostprocessors.ObjetoB" /> <bean id="c" class="com.targettrust.spring.beanpostprocessors.ObjetoC" /> <bean class="com.targettrust.spring.beanpostprocessors.LogCreationBeanPostProce ssor" /> </beans>

Cdigo XML 3.6 Xml de configuraes

Diego Pacheco http://diego-pacheco.blogspot.com

3-19

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.beanpostprocessors; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { new ClassPathXmlApplicationContext("/com/targettrust/spring/beanpostprocessor s/Spring-beans.xml"); } }

Cdigo 3.16 Teste.java

A interface BeanPostProcessor possui dois mtodos, so eles: postProcessBeforeInitialization postProcessAfterInitialization

Um dos mtodos serve para efetuar operaes antes da inicializao e outro aps a inicializao do bean no contexto do Spring. Ambos os mtodos recebem o objeto e seu nome por parmetro, assim podemos aplicar algum proxy ou regra de negcio. Aqui poderamos utilizar um Validator conforme visto nos tpicos anteriores e forar a validao de determinadas propriedades. Outra possibilidade que temos aqui graas a esse extraordinrio recurso do Spring que podemos criar annotations personalizadas ou fazer os componentes implementarem interfaces e com esse gancho do BeanPostProcessor podemos ler essas informaes e efetuar diversas operaes que nos desperte interesse.

Diego Pacheco http://diego-pacheco.blogspot.com

3-20

Spring Framework Framework para desenvolvimento de aplicaes java

BeanFactoryPostProcessors
Similar ao BeanPostProcessor, porm o BeanFactoryPostProcessor consegue ler os metadados de configurao do Spring e tambm mudar esses dados antes que o Spring crie seus beans. Voc pode configurar muitos BenFactoryPostProcessor. possvel configurar a ordem de execuo dessa classe implementando a interface Ordered. Se voc deseja mudar a instncia de um bean j criado voc deve utilizar o BeanPostProcessor conforme apresentando no tpico anterior. O Prprio Spring utiliza beanFactoryPostProcessor como: PropertyResourceConfigurer e PropertyPlaceholderConfigurer. Se estamos utilizando ApplicationContext o registro feito de forma automtica, se estivermos utilizando uma BeanFactory precisamos fazer isso de forma manual. A Forma de fazer isso est exemplificada logo abaixo:
XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml")); PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); cfg.setLocation(new FileSystemResource("jdbc.properties")); cfg.postProcessBeanFactory(factory);

Cdigo 3.17 Exemplo de registro de BeanPostProcessor. No cdigo acima criando um PropertyPlaceHolderConfigurer que uma implementao de BeanFactoryPostProcessor e ser detalhada nos prximos tpicos. Veja agora um exemplo concreto de como poderia ser utilizado o BeanFactoryPostProcessor:
package com.targettrust.spring.beanfactorypostprocessors; import java.text.SimpleDateFormat; import java.util.Date; public class DataService { private String pattern; public String getPattern() { return pattern; } public void setPattern(String pattern) { this.pattern = pattern; } public String showSysDate(){ SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.format(new Date());

Diego Pacheco http://diego-pacheco.blogspot.com

3-21

Spring Framework Framework para desenvolvimento de aplicaes java

} }

Cdigo 3.18 DataService.java


package com.targettrust.spring.beanfactorypostprocessors; import import import import java.io.FileInputStream; java.util.Map; java.util.Properties; java.util.Map.Entry;

import org.springframework.beans.BeansException; import org.springframework.beans.FatalBeanException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class DatePatternRouterBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override @SuppressWarnings("unchecked") public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Properties p = new Properties(); try { p.load(new FileInputStream("./src/com/targettrust/spring/beanfactorypostprocessors/p atterns.properties")); System.out.println("Patterns: " + p); } catch (Exception e) { throw new FatalBeanException("Erro ao buscar patterns!",e); } Map<Object,Object> beans = beanFactory.getBeansOfType(DataService.class); for(Entry<Object, Object> e: beans.entrySet()){ System.out.println("Aplicando pattern em service: " + e); DataService service = ((DataService)e.getValue()); service.setPattern(p.getProperty("pattern." + service.getPattern().replace("#", ""))); } } }

Cdigo 3.19 DatePatternRouterBeanFactoryPostProcessor.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-22

Spring Framework Framework para desenvolvimento de aplicaes java

<?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-2.0.xsd" default-lazy-init="false" > <bean id="brasilDateService" class="com.targettrust.spring.beanfactorypostprocessors.DataService" > <property name="pattern" value="#brasil" /> </bean> <bean id="usDateService" class="com.targettrust.spring.beanfactorypostprocessors.DataService" > <property name="pattern" value="#us" /> </bean> <bean class="com.targettrust.spring.beanfactorypostprocessors.DatePatternR outerBeanFactoryPostProcessor" /> </beans>

Cdigo XML 3.7 Xml de configuraes


package com.targettrust.spring.beanfactorypostprocessors; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { ApplicationContext ap = new ClassPathXmlApplicationContext("/com/targettrust/spring/beanfactorypostpro cessors/Spring-beans.xml"); System.out.println("Data Brasil pattern : " + ((DataService)ap.getBean("brasilDateService")).showSysDate()); System.out.println("Data Us pattern : " + ((DataService)ap.getBean("usDateService")).showSysDate()); } }

Cdigo 3.20 Teste.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-23

Spring Framework Framework para desenvolvimento de aplicaes java

A Interface BeanFactoryPostProcessor s tem um mtodo: postProcessBeanFactory Que recebe por parmetro um ConfigurableListableBeanFactory que a bean factory que est sendo configurada.Com esse parmetro podemos manipular as informaes da BeanFactory.

Diego Pacheco http://diego-pacheco.blogspot.com

3-24

Spring Framework Framework para desenvolvimento de aplicaes java

Property Editors

Esse recurso utilizado largamente no Spring framework. Property Editors tm a capacidade de converter informaes em seus tipos de dados corretos, por exemplo, imagine que gostaramos de injetar um uma propriedade do tipo File em um bean do Spring para tal necessidade teriamos de fazer o seguinte procedimento:
<bean id="txt" class="java.io.File" > <constructor-arg index="0" value="C:/BOOTSECT.BAK" /> </bean>

Cdigo XML 3.8 Injeo de File Aps isso seria possvel injetar esse bean txt no bean que necessita de um File. Porm isso muito doloroso e nada produtivo. No seria mais fcil se o Spring detectar-se automaticamente uma propriedade de um bean que um File e criasse o File para ns? O Spring j faz isso para ns se injetarmos um caminho para uma File ele automaticamente faz isso para ns, por que ele j tem um PropertyEditor default que est registrado para tal trabalho. Esse Property Editor default chama-se FileEditor. Confira os PropertyEditor disponveis no Spring:
Property Editor ByteArrayPropertyEditor Explicao Editor para arrays de bytes. Strings vo ser convertidas em suas correspondentes representaes de bytes. ClassEditor Faz parte de String representando classes. Quando a classe no encontrada levantado um IllegalArgumentException. No registrado por default. CustomBooleanEditor Esse property editor para propriedades booleans. Trabalha com os valores [ true, false, on, off, yes, no, 0, 1]

Diego Pacheco http://diego-pacheco.blogspot.com

3-25

Spring Framework Framework para desenvolvimento de aplicaes java

CustomCollectionEditor

Editor para qualquer tipo de coleo, til quando precisamos alguma coleo especifica.

CustomDateEditor

Editor para java.util.Date esse editor no est registrado por default. Precisa ser registrado com um formato de data especifico.

CustomNumberEditor

Editor para qualquer subclass de Number como por exemplo: Integer, Long, Float, Double. registrado por default.

FileEditor

Capaz de criar arquivos do tipo java.io.File e registrado por default.

InputStreamEditor

Atravs do ResouerceDitor e Resource pode instanciar um InputStream, mas o Spring no ir fechar o Stream para voc, utilizado por default.

LocaleEditor

Capaz de materializar objetos do tipo Locale, a partir de uma String no formato ling_pais. Registrado por default

PatternEditor PropertiesEditor

Resolve String para o Objeto Pattern, conforme jdk 1.5. Converte Strings em objetos java.lang.Properties. registrado por default.

StringTrimmerEditor

Property Editor que aplica um trim nas Strings, opcionalmente pode transformar uma String vazia em null. No registrado por default.

URLEditor

Capaz de converter uma String em um objeto URL. Registrado por default.

Diego Pacheco http://diego-pacheco.blogspot.com

3-26

Spring Framework Framework para desenvolvimento de aplicaes java

O Springframework utiliza java.beans.PropertyEditorManager para gerenciar e procurar os property editor que so necessrios a ele. Esse path de procura tem tambm sun.bean.editors que conta com editores como: Font, Color e a maioria dos tipos primitivos. A Implementao padro dos javabeans da Sun ir automaticamente descobrir property editor para voc, mesmo que no tenha ocorrido um registro prvio. Mas isso s ir ocorrer se o seu Property Editor estiver na mesma package que o tipo que ele cobre e tendo o mesmo nome da Classe + o sufixo Editor. Exemplo:
com chank pop Foo FooEditor

// PropertyEditor para a Classe Foo

Voc pode criar seu prprio Property Editor, para isso voc precisar estender a classe PropertyEditorSupport e registrar esse custom editor criado por voc no XML do Spring. Veja o exemplo a seguir:
package com.targettrust.spring.propertyeditor; public class Aluno { private String nome; public Aluno() {} public Aluno(String nome) { super(); this.nome = nome; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } @Override public String toString() { return nome; } }

Cdigo 3.21 Aluno.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-27

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.propertyeditor; import java.util.List; public class Turma { private String nome; private List<Aluno> alunos; public Turma() {} public Turma(String nome, List<Aluno> alunos) { super(); this.nome = nome; this.alunos = alunos; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public List<Aluno> getAlunos() { return alunos; } public void setAlunos(List<Aluno> alunos) { this.alunos = alunos; } @Override public String toString() { return nome + " alunos: " + alunos.toString(); } }

Cdigo 3.22 Turma.java


package com.targettrust.spring.propertyeditor; import java.beans.PropertyEditorSupport; public class AlunoEditor extends PropertyEditorSupport{ @Override public void setAsText(String text) throws IllegalArgumentException { Aluno a = new Aluno(text); setValue(a); } }

Cdigo 3.23 AlunoEditor.java


<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"

Diego Pacheco http://diego-pacheco.blogspot.com

3-28

Spring Framework Framework para desenvolvimento de aplicaes java

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-2.0.xsd"> <bean id="turma" class="com.targettrust.spring.propertyeditor.Turma"> <property name="nome" value="Curso-Spring" /> <property name="alunos"> <list> <value>Rod</value> <value>Joe</value> <value>Bart</value> <value>Homer</value> <value>Hammer</value> </list> </property> </bean> <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigu rer"> <property name="customEditors"> <map> <entry key="com.targettrust.spring.propertyeditor.Aluno"> <bean class="com.targettrust.spring.propertyeditor.AlunoEditor" /> </entry> </map> </property> </bean> </beans>

Cdigo XML 3.9 Registro do property editor

Com os property editors a injeo de propriedades fica muito mais simples e mais rpida de ser efetuada. Nesse exemplo, como o pojo Aluno est no mesmo package do seu Editor possivel apagar o bean customEditorCon- figurer, porque o mecanismo padro da Sun de java beans ir detectar para ns.

Diego Pacheco http://diego-pacheco.blogspot.com

3-29

Spring Framework Framework para desenvolvimento de aplicaes java

Eventos
A escuta de eventos em um objeto ApplicationContext feita atravs dos objetos ApplicationEvent e ApplicationListener. Se um bean implementa a interface ApplicationListener publicado no contexto do Spring toda vez que for publicado um evento do tipo ApplicationEvent o seu bean vai ser notificado. Confira alguns dos eventos disponveis por padro na ApplicationContext.
Evento ContextRefreshedEvent Descrio Publicado quando a ApplicationContext inicializado ou atualizado, isso significa quando todos os beans foram carregados e o Spring est pronto para ser usado(container IoC) ContextClosedEvent Publicado quando a ApplicationContext fechada, usando o mtodo close. RequestHandleEvent Um evento Especfico da Web referente a uma requisio HTTP, evento publicado aps a requisio HTTP se finalizar. Esse evento s pode ser utilizado para aplicaes Web que utilizam o DispatcherServlet do Spring.

Os eventos no Spring so resolvidos de forma sncrona, ou seja, o Spring ir bloquear at que todos os listeners tenham terminado suas operaes. Veja como criar um evento personalizado em sua aplicao:
package com.targettrust.spring.event; import org.springframework.context.ApplicationEvent; public class FeriadoEvent extends ApplicationEvent{ private String data; private static final long serialVersionUID = 1L; public FeriadoEvent(Object source,String data) { super(source); this.data = data; } public String getData() { return data; }

Diego Pacheco http://diego-pacheco.blogspot.com

3-30

Spring Framework Framework para desenvolvimento de aplicaes java

Cdigo 3.24 FeriadoEvent.java


package com.targettrust.spring.event; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; public class FeriadoListener implements ApplicationListener { public void onApplicationEvent(ApplicationEvent event) { if (event instanceof FeriadoEvent){ FeriadoEvent fe = (FeriadoEvent)event; System.out.println("Viva! Dia: " + fe.getData() + " feriado. Uhhuu!!!" ); } } }

Cdigo 3.25 FeriadoListener.java


package com.targettrust.spring.event; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class RH implements ApplicationContextAware { private ApplicationContext ac; public void pulicarFeriados(){ ac.publishEvent(new FeriadoEvent(this,"01/01/08")); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { ac = applicationContext; } }

Cdigo 3.26 RH.java


<?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-2.0.xsd" > <bean id="rh" class="com.targettrust.spring.event.RH" /> <bean

Diego Pacheco http://diego-pacheco.blogspot.com

3-31

Spring Framework Framework para desenvolvimento de aplicaes java

id="funcionarioEsperto" class="com.targettrust.spring.event.FeriadoListener" /> </beans>

Cdigo XML 3.10 Registro do listener


package com.targettrust.spring.event; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/event/Springbeans.xml"); RH rh = (RH)ac.getBean("rh"); rh.pulicarFeriados(); } }

Cdigo 3.27 Teste.java

Nesse exemplo foi utilizado o FeridoEvent que uma classe que estende ApplicationEvent do Spring. Para tratar o evento foi criada a classe FeriadoListener que implementa ApplicationListener com um if parta saber se o evento disparado foi o FeriadoEvent. A Classe RH uma ApplicationContextAware para poder publicar o evento atravs do mtodo publishEvent.

Diego Pacheco http://diego-pacheco.blogspot.com

3-32

Spring Framework Framework para desenvolvimento de aplicaes java

PropertyPlaceholderConfigurer

PropertyPlaceHolderConfigurer uma forma de externalizar informao na bean factory. Esse objeto implementa BeanFactoryPostProcessor para poder efetuar suas modificaes nos metadados do Spring. A vantagem que podemos externalizar nossas configuraes em arquivos.proprerties e o Spring ir buscar nesses arquivos as configuraes. Muito til para informaes de ambientes como conexes de bancos de dados, usurios, senhas e listas de e-mails, com a vantagem de no precisar mexer no XML de definies do Spring, reduzindo assim o risco de outros possveis erros. possvel procurar tambm nas propriedades do sistema, para isso necessrio setar o modo systemPropertiesMode. Pode ser utilizado para substituir classes, por exemplo, podemos fazer uma lgica que escolhe em tempo de runtime qual classe ser utilizada para um determinado bean, muito til para fazer determinados roteamentos, para esse tipo de situao til utilizar o escopo de prototype. Para utilizar o PropertyPlaceHolderConfigurer necessrio registr-lo no Spring e informar a localizao dos arquivos properties. Veja um exemplo concreto abaixo:
package com.targettrust.spring.propertyplaceholderconfigurer; public class Instrutor { private private private private String nome; int idade; String time; float altura;

public Instrutor() {} public Instrutor(String nome, int idade, String time, float altura) { super(); this.nome = nome; this.idade = idade; this.time = time; this.altura = altura; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public int getIdade() { return idade;

Diego Pacheco http://diego-pacheco.blogspot.com

3-33

Spring Framework Framework para desenvolvimento de aplicaes java

} public void setIdade(int idade) { this.idade = idade; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } public float getAltura() { return altura; } public void setAltura(float altura) { this.altura = altura; } @Override public String toString() { return " nome: " + nome + " idade: " + idade + " altura : " + altura+ " time: " + time ; } }

Cdigo 3.28 Instrutor.java


nome=deigo idade=22 altura=1.85

Cdigo 3.28 config.properties


<?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-2.0.xsd" > <bean class="org.springframework.beans.factory.config.PropertyPlaceholder Configurer"> <property name="location"> <value>classpath:com/targettrust/spring/propertyplaceholderconfigur er/config.properties</value> </property> <property name="properties"> <value>time=Grmio</value> </property> </bean> <bean id="i"

Diego Pacheco http://diego-pacheco.blogspot.com

3-34

Spring Framework Framework para desenvolvimento de aplicaes java

class="com.targettrust.spring.propertyplaceholderconfigurer.Instrut or" > <property <property <property <property </bean> </beans> name="nome" name="idade" name="time" name="altura" value="${nome}" /> value="${idade}" /> value="${time}" /> value="${altura}" />

Cdigo XML 3.11 Registro do PropertyPlaceHolderConfigurer


package com.targettrust.spring.propertyplaceholderconfigurer; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "/com/targettrust/spring/propertyplaceholderconfigurer/Springbeans.xml"); Instrutor i = (Instrutor)ac.getBean("i"); System.out.println("Instrutor: " + i); } }

Cdigo 3.29 Teste.java

Na definio do bean PropertyPlaceHolderConfigigurer alm de um conjunto de arquivos properties possvel passar um objeto Property para ser definido no prprio Spring em linha, como foi feito no exemplo, assim podemos mesclar informaes vindas do file system com as informaes definidas nos prprios metadados do spring. Existe outro PropertyPlaceHolderConfigurer que o PropertyOverride Configurer, esse por sua vez ir saber escrever as informaes dos beans, mas o arquivo de properties deve ter o seguinte formato:

nomeBean.propriedade=valor outronomeBean.outrapropriedade=outrovalor maisumnomeBean.maisumapropriedade=maisumvalor

Cdigo 3.29 config.properties para PropertyOverrideConfigurer

Diego Pacheco http://diego-pacheco.blogspot.com

3-35

Spring Framework Framework para desenvolvimento de aplicaes java

SingletonBeanFactoryLocator

Recurso do Spring Framework para podermos carregar mltiplos arquivos de configuraes de uma s vez. normal termos uma aplicao dividida em camadas como persistncia, negcio, utilitrios, telas, testes, etc. Neste cenrio dividimos as configuraes do Spring em diversos arquivos de configuraes, possvel gerenciar uma bean factory do Spring e parametrizar os arquvios de configurao que ela ir carregar. Esse recurso deve ser utilizado somente quando necessrio, pois pode acabar provendo acoplamento e perda de performance. Evite utiliz-lo em pequenas aplicaes. O cenrio ideal de utilizao um aplicao JEE com mltiplas camadas (layers) onde cada camada uma bean factory distinta, nesse caso o SingletonBeanFactoryLocator pode ser utilizado para criar uma bean factory hierrquica com suas diversas bean factories. Os Criadores do Spring Framework recomendam que esse recurso seja utilizado com cautela. Para utilizar tal recurso necessrio ter um XML na raiz de seu classptah com o seguinte nome: beanRefFactory.xml, e nesse arquivo vai estar linkado as diversas beans factories com seus diversos XMLs. Veja o exemplo a baixo.
package com.targettrust.spring.singletonbeanfactorylocator; public class ObjetoA {}

Cdigo 3.29 ObjetoA.java


<?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-2.0.xsd" default-lazy-init="true" > <bean id="A1" class="com.targettrust.spring.singletonbeanfactorylocator.ObjetoA" /> </beans>

Cdigo XML 3.12 Spring-beans-A.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-2.0.xsd"

Diego Pacheco http://diego-pacheco.blogspot.com

3-36

Spring Framework Framework para desenvolvimento de aplicaes java

default-lazy-init="true" > <bean id="A2" class="com.targettrust.spring.singletonbeanfactorylocator.ObjetoA" /> </beans>

Cdigo XML 3.13 Spring-beans-B.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-2.0.xsd" default-lazy-init="true" > <bean id="A3" class="com.targettrust.spring.singletonbeanfactorylocator.ObjetoA" /> </beans>

Cdigo XML 3.13 Spring-beans-C.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-2.0.xsd" default-lazy-init="true" > <bean id="A4" class="com.targettrust.spring.singletonbeanfactorylocator.ObjetoA" /> </beans>

Cdigo XML 3.14 Spring-beans-D.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-2.0.xsd" default-lazy-init="false" > <bean id="beanFactoryBean" class="org.springframework.context.support.ClassPathXmlApplicationC ontext" >

Diego Pacheco http://diego-pacheco.blogspot.com

3-37

Spring Framework Framework para desenvolvimento de aplicaes java

<constructor-arg> <list> <value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-A.xml</value> <value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-B.xml</value> <value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-C.xml</value> </list> </constructor-arg> </bean> <bean id="beanFactoryBean2" class="org.springframework.context.support.ClassPathXmlApplicationC ontext" > <constructor-arg> <list> <value>com/targettrust/spring/singletonbeanfactorylocator/Springbeans-D.xml</value> </list> </constructor-arg> </bean> </beans>

Cdigo XML 3.15 beanRefFactory.xml.xml


package com.targettrust.spring.singletonbeanfactorylocator; import org.springframework.beans.factory.access.BeanFactoryLocator; import org.springframework.beans.factory.access.BeanFactoryReference; import org.springframework.beans.factory.access.SingletonBeanFactoryLocator; public class Teste { public static void main(String[] args) { BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance(); BeanFactoryReference bf = bfl.useBeanFactory("beanFactoryBean"); ObjetoA a1 = (ObjetoA)bf.getFactory().getBean("A1"); ObjetoA a2 = (ObjetoA)bf.getFactory().getBean("A2"); ObjetoA a3 = (ObjetoA)bf.getFactory().getBean("A3"); bf = bfl.useBeanFactory("beanFactoryBean2"); ObjetoA a4 = (ObjetoA)bf.getFactory().getBean("A4"); System.out.println("ObjetoA System.out.println("ObjetoA System.out.println("ObjetoA System.out.println("ObjetoA a1: a2: a3: a4: " " " " + + + + a1); a2); a3); a4);

Diego Pacheco http://diego-pacheco.blogspot.com

3-38

Spring Framework Framework para desenvolvimento de aplicaes java

} }

Cdigo 3.30 Teste.java

Nesse exemplo existem duas bean factories: beanFactoryBean e beanFactoryBean2 que so definidas no arquivo BeanRefFactory.xml. A primeira bean factory tem trs XMLs de configuraes e a segunda tem 1 XML de configurao. Na classe de testes instanciado um BeanFactoryLocator que um singleton e est sob o pattern de ServiceLocator. utilizado o mtodo useBeanFactory para obtermos um objeto BeanFactoryReference que atravs do mtodo getFactory ir retornar a bean factory real. Quando necessrio acessar o bean A4 que est em outra Bean Factory necessrio trocar de bean factory para isso usamos o mtodo useBeanFactory novamente. Se for necessrio trabalhar com Application context devemos utilizar outro Locator que o SingletonBeanFactoryLocator.

Diego Pacheco http://diego-pacheco.blogspot.com

3-39

Spring Framework Framework para desenvolvimento de aplicaes java

Internacionalizao

O Spring framework tem suporte a internacionalizao que a funcionalidade de prover suporte a aplicaes multi-idiomas. O objeto ApplicationContext implementa a interfcace MessageSource atravs do qual prove mensagens ou suporte i18n. Quando um ApplicationContext levantada automaticamente ela procura por uma fonte de mensagens (MessageSource) definida em seu contexto, o bean que representa essa fonte de mensagem deve ter o nome messageSource, se nenhum objeto messageSource for localizado o Spring ir usar um MessageSource default: StaticMessageSource vazio somente para garantir o funcionamento de outros componentes. Atualmente o Spring prove duas implementaes de messageSource, so elas: StaticMessageSource: utilizada programaticamente mensagens de forma dinmica sua aplicao. para adicionar

ResourceBundleMessageSource: Mais interessante pois possui suporte a parte de TextFormat e carrega arquivos atravs dos nomes base. Para facilitar o acesso a mensagens podemos utilizar a interface MessageSourceAware que o Spring ir utilizar para injetar o messageSource corrente em seu bean. Quando utilizamos esses recursos, devemos ter mltiplos arquivos de idiomas, por exemplo, ns informaramos o arquivo base como: mensagens no contexto do Spring, supondo que estamos com o Locale setado para pt_BR deve existir no file system um arquivo com o nome: mensagems_pt_BR.properties. Veja como usar esses recursos na prtica conforme mostra o exemplo a seguir:

Diego Pacheco http://diego-pacheco.blogspot.com

3-40

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.i18n; import java.util.Locale; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; public class Pessoa implements MessageSourceAware{ private String nome; private int idade; private MessageSource ms; public Pessoa() {} public Pessoa(String nome, int idade) { super(); this.nome = nome; this.idade = idade; } @Override public void setMessageSource(MessageSource messageSource) { ms = messageSource; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public int getIdade() { return idade; } public void setIdade(int idade) { if( idade<=0 || idade >= 120 ) throw new IllegalArgumentException(ms.getMessage("idade.invalida",new Object[]{idade},Locale.getDefault())); this.idade = idade; } @Override public String toString() { return "nome: " + nome + " idade: " + idade; } }

Cdigo 3.31 Pessoa.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-41

Spring Framework Framework para desenvolvimento de aplicaes java

idade.invalida=The Age: {0} is not allowed becouse is too older or is less them 1!

Cdigo 3.32 mensagems_en.properties


idade.invalida=A idade: {0} no aceitvel por que muito velha ou menor do que 1

Cdigo 3.33 mensagems_pt_BR.properties


<?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-2.0.xsd" > <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSou rce"> <property name="basenames"> <list> <value>mensagems</value> </list> </property> </bean> <bean id="pessoa" class="com.targettrust.spring.i18n.Pessoa" /> </beans>

Cdigo XML 3.16 Spring-beans.xml


package com.targettrust.spring.i18n; import java.util.Locale; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Teste { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/i18n/Springbeans.xml"); Locale.setDefault(Locale.ENGLISH); setIdade(ac); Locale.setDefault(new Locale("pt","BR")); setIdade(ac);

Diego Pacheco http://diego-pacheco.blogspot.com

3-42

Spring Framework Framework para desenvolvimento de aplicaes java

} private static void setIdade(ApplicationContext ac){ Pessoa p = (Pessoa)ac.getBean("pessoa"); p.setNome("Crom"); try{ p.setIdade(200); }catch(RuntimeException re){ re.printStackTrace(); } } }

Cdigo 3.34 Teste.java

Diego Pacheco http://diego-pacheco.blogspot.com

3-43

Spring Framework Framework para desenvolvimento de aplicaes java

Exercicios

1) Crie um objeto pessoa com nome, idade e telefone. 2) Crie um validador para pessoa. 3) Invoque o validador de pessoa em um BeanPostProcessor 4)Externalize as mensagens de erro em um arquivo property e mostre mensagens i18n caso a idade da pessoa esteja invlida. 5) Crie um property editor que seja possvel passar o nome, idade e telefone da pessoa apenas na propriedade nome e o property editor espalhar as informaes em suas propriedades corretas.

Diego Pacheco http://diego-pacheco.blogspot.com

3-44

Spring Framework Framework para desenvolvimento de aplicaes java

Espao para anotaes

Diego Pacheco http://diego-pacheco.blogspot.com

3-45

Spring Framework Framework para Desenvolvimento de Aplicaes Java

4. Persistncia

Diego Pacheco http://diego-pacheco.blogspot.com

Spring Framework Framework para desenvolvimento de aplicaes java

Objetivos

Conhecer a hierarquia de exceptions de banco do Spring; Saber criar DataSource; Conhecer os principais recursos do JDBCTemplate; Saber utilizar o SessionFactoryBean; Conhecer os principais recursos do HibernateTemplate; Saber como utilizar transaes declarativas.

Diego Pacheco http://diego-pacheco.blogspot.com

4-2

Spring Framework Framework para desenvolvimento de aplicaes java

Hierarquia de Exceptions

O Spring framework prov uma camada de acesso a dados chamada DAO support que prove diversas facilidades para trabalhar com JDBC, Hibernate, JDO, JPA. Esse recurso permite trocar a tecnologia de persistncia com mais facilidade e menos esforo, sem a necessidade de se preocupar com as execptions que variam de tecnologia para tecnologia. O Spring tem sua prpria rvore de exceptions traduzindo as exceptions de tecnologias especficas como SQLException para sua prpria rvore de exceptions, onde sua exception raiz a DataAccessException. Esses exceptions empacotam a exception raiz, assim voc no perde nenhuma mensagem original. O Spring pode encapsular uma exception do Hibernate, por exemplo, em uma outra exception de sua rvore, isso igual para as exceptions do JDO e da JPA tambm. Este mecanismo do Spring lhe evita a irritao de ter que tratar exceptions que voc no pode se recuperar. Confira a rvore de exceptions do Spring na figura abaixo:

Cdigo 4.1 Hierarquia de Exceptions do Spring

Classes abstratas do modelo de abstrao DAO do Spring: Para prover um modelo de trabalho mais fcil com todas essas tecnologias de acesso a dados (JDO, JDBC, Hibernate, JPA) o Spring prove uma srie de classes DAOs abstratas que voc pode estender. Dentre essas classes temos:

Diego Pacheco http://diego-pacheco.blogspot.com

4-3

Spring Framework Framework para desenvolvimento de aplicaes java

JdbcDaoSupport: Super classe para accesso via JDBC, necessita um DataSource, prove um instncia de JDBCTemplate. HibernateDaoSupport: Super classe de acesso via Hibernate, necessita uma SessionFactory, prove uma instncia de HibernateTemplate. JdoDaoSupport: Super classe de accesso via JDO, necessita uma

PersistenceManagerFactory, prove uma instncia de JdoTemplate. JpaDaoSupport: Super classe de accesso via JDO, necessita uma

EntityManagerFactory, prove uma instncia de JpaTemplate.

Diego Pacheco http://diego-pacheco.blogspot.com

4-4

Spring Framework Framework para desenvolvimento de aplicaes java

Acesso a dados usando JDBC

O Spring framework se encarrega de executar as tarefas de baixo nvel da API de JDBC. O Spring realiza as seguintes operaes: Define os parmetros da conexo Abre a conexo Especifica um Statement Prepara e executa o Statement Interam os resultados (se existirem) Faz o trabalho a cada iterao Processa as exceptions Gerencia as transaes Fecha a conexo Dessa forma o desenvolvedor pode trabalhar com uma camada de mais alto nvel e mais produtivas. Essa camada est dividida basicamente em quatro pacotes, core, datasource, object e suppport que provem objetos de acesso a dados e call backs alm de datasources e facilidades para acessar stored procedures e functions de bancos.

Trabalhando com DataSources


Quando desejamos manipular dados que esto em algum banco de dados precisamos de uma conexo com o banco, o Spring realiza essa tarefa atravs de um DataSource. DataSource parte da especificao JDBC e pode ser visto em forma de uma connection factory. Isso permite o container esconder os problemas de controle transacionais e pools de conexes da API do desenvolvedor. Dessa forma possvel isolar as conexes com os bancos dos cdigos dos desenvolvedores.

Diego Pacheco http://diego-pacheco.blogspot.com

4-5

Spring Framework Framework para desenvolvimento de aplicaes java

No Spring possvel configurar sua fonte de dados de forma que seja possvel obter o DataSource de uma fonte JNDI. Podemos utilizar um DriverManagerDataSource que uma simples implementao de DataSource que devemos informar o driver a ser utilizado, conforme exemplo 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" > <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" > <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:hsql://C:/db" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> </beans>

XML 4.1 DriverManagerDataSource

Para criarmos esse objeto necessrio informar o driver, a url de conexo para o banco, usurio e a senha. Nesse caso est sendo utilizado uma conexo com o banco de dados HSQLDB. Esse DataSource no disponibiliza pools de conexes, a cada chamada ser criada uma conexo nova. Se voc deseja uma soluo de connection pool out-of-the-box, deve considerar a soluo da apache o Apache DBCP, possvel utilizar esses framework em conjunto com o Spring. Dica: O Spring framework faz a traduo de erros de SQL Genricos para Exceptions mais especficas, se voc desenvolve alguma regra ou processamento em stored procedures ou functions de bancos e lavanta exceptions personalizadas no banco, podemos traduzir essas exceptions personalizadas para exceptions do Java. Para fazer isso necessrio herdar a classe SQLErrorCodeSQLExceptionTranslator e implementar o mtodo custom translate onde voc ir traduzir as exceptions.

Diego Pacheco http://diego-pacheco.blogspot.com

4-6

Spring Framework Framework para desenvolvimento de aplicaes java

Trabalhando com JDBCTemplate

Agora vamos ver como executar querys apartir de uma DataSource e um JDBCTemplate. JDBTemplate um template para acesso a dados via JDBC a classe prove vrias facilidades de acesso e mtodos que j entregam os dados mais lapidados. Veja como configurar e executar um cdigo ddl, no exemplo 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" > <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" > <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:file:///C:\\target\\spring\\db" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" lazy-init="false" > <property name="dataSource" ref="dataSource" /> <property name="lazyInit" value="false" /> </bean> </beans>

XML 4.2 Configurao de injeo do JDBCTemplate e DataSource.

A Classe JdbcTemplate tem uma srie de mtodos utilitrios, dentre eles podemos destacar: Execute (String sql): utilizado para executar comandos ddl. Update (String sql,Object[] args): utilizado para executar inserts e updates esse mtodo recebe um Object[] por que ele cria um PreparedStatement. Esse mtodo pode ser utilizado para efetuar operaes de delete tambm.

Diego Pacheco http://diego-pacheco.blogspot.com

4-7

Spring Framework Framework para desenvolvimento de aplicaes java

queryForObject (String sql,Class requiredType): Esse mtodo executa uma query e retorna um objeto, especificamos o tipo passando o class do tipo. queryForObject (String sql,RowMapper rowMapper): Essa sobre escrita desse mtodo possibilita buscar dados na base e converte-los j para objetos. queryForInt (String sql): Mtodo que j retorna um int primitivo a partir de uma query SQL, muito til quando temos que buscar apenas um valor no banco em alguma tabela de configurao. queryForList (String sql): Mtodo que executa uma query SQL e trs um java.util.List como resultado da consulta. A Classe JdbcTemplate possui vrios overrides dos mtodos de acesso a dados para as mais diversas situaoes como SQL simples, PreparedStatements, RowMapper, SQL Types. Veja um exemplo completo de acesso a dados com os principais mtodos do JdbcTemplate no cdigo 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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" > <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" > <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:file:///C:\\target\\spring\\db" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" lazy-init="false" > <property name="dataSource" ref="dataSource" /> <property name="lazyInit" value="false" /> </bean> </beans>

XML 4.3 Configurao de injeo do JDBCTemplate e DataSource.

Diego Pacheco http://diego-pacheco.blogspot.com

4-8

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.jdbc; import import import import import org.springframework.context.ApplicationContext; org.springframework.context.support.ClassPathXmlApplicationContext; org.springframework.jdbc.UncategorizedSQLException; org.springframework.jdbc.core.JdbcTemplate; org.springframework.jdbc.core.RowMapper;

public class TesteCriaTabela { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/jdbc/Springbeans.xml"); JdbcTemplate jt = (JdbcTemplate)ac.getBean("jdbcTemplate"); try{ jt.execute("create table _teste (nome varchar(50), numerox integer); "); }catch(UncategorizedSQLException e){ System.out.println("A Tabela j existe! "); jt.update("delete from teste "); } jt.update("insert into teste (nome) values (?) ", new Object[]{"p1"}); jt.update("insert into teste (nome) values (?) ", new Object[]{"p3"}); jt.update("insert into teste (nome) values (?) ", new Object[]{"p4"}); jt.update("update teste set nome = ? where nome = ?", new Object[]{"p2","p1"}); jt.update("delete from teste where nome = 'p4' "); System.out.println( jt.queryForObject("select nome from teste where nome = 'p3' ", String.class) ); ObjetoTeste ot = (ObjetoTeste) jt.queryForObject("select nome from teste where nome = 'p2' ", new RowMapper(){ public Object mapRow(java.sql.ResultSet rs, int rowNum) throws java.sql.SQLException { return new ObjetoTeste(rs.getString("nome")); } }); System.out.println(jt.queryForList("select * from teste")); System.out.println(ot); } }

Cdigo 4.1 TesteCriaTabela.java


Diego Pacheco http://diego-pacheco.blogspot.com 4-9

Spring Framework Framework para desenvolvimento de aplicaes java

No Exemplo acima foram definidos dois beans no contexto do Spring, o dataSource e o jdbcTemplate, no programa java de testes foi requisitado ao Spring o bean jdbcTemplate e a partir dele foi possivel criar tabelas com o mtodo execute, manipular dados com o mtodo update e acessar dados com os mtodos queryForXXX.

Diego Pacheco http://diego-pacheco.blogspot.com

4-10

Spring Framework Framework para desenvolvimento de aplicaes java

Session Factory Bean

O Spring prove suporte para gerenciar uma SessionFactory do Hibernate. Essa tarefa pode ser feita atravs do LocalSessionFactoryBean. Esse bean necessita de uma DataSource e de recursos de mapeamentos podendo ser um hibernate mappings ou configuraes de mapeamento feitas no prprio Spring que seram repassadas ao Hibernate. muito comum utilizar esse tipo de recurso em uma aplicao JEE ou desktop. O Seguinte exemplo mostra como configurar uma SessionFactoryBean de forma que o Spring gerencia a SessionFactory do Hibernate com o Banco de dados HSQLDB.
<?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-2.0.xsd" > <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" > <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:file:///C:\\target\\spring\\db" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" lazy-init="false" > <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>com/targettrust/spring/hibernate/Pessoa.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.PointbaseDialect </prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> </bean> </beans>

XML 4.4 Configurao de injeo do SessionFactoryBean


Diego Pacheco http://diego-pacheco.blogspot.com 4-11

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.hibernate; import org.hibernate.SessionFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TesteSessionFactory { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/hibernate/Springbeans.xml"); SessionFactory sf = (SessionFactory)ac.getBean("sessionFactory"); System.out.println(sf.openSession()); } }

Cdigo 4.2 TesteSessionFactory.java

Para podermos utilizar a integrao do Spring com o Hibernate, so necessrios os seguintes jars no classpath da aplicao: hibernate3.jar jta.jar dom4j-1.6.1.jar commons-logging.jar commons-collections.jar antlr-2.7.6.jar hsqldb.jar

Nesse exemplo foi necessrio utilizar o hsqldb.jar, pois nesse jar que esto os drivers de acesso ao banco de dados hsqldb, se voc quiser utilizar outro banco de dados em sua aplicao, voc dever trocar esse jar pelo jar apropriado para seu banco de dados.

Diego Pacheco http://diego-pacheco.blogspot.com

4-12

Spring Framework Framework para desenvolvimento de aplicaes java

Hibernate Template

Assim como o JdbcTemplate o template de acesso a dados via jdbc do Spring, o HibernateTemplate o template de acesso a dados via Hibernate do Spring. Antes do Spring 2, o Spring provia em seu core suporte para Hibernate 2 e Hibernate 3, a partir de agora e das novas verses, o Spring s prove acesso ao Hibernate 3 em seu core . No Projeto Spring Modules existe o suporte para Hibernate 2 para as aplicaes mais antigas. O HibernateTamplate prove uma srie de comodidades para a utilizao da API do Hibernate, mas sempre que for necessrio voc pode acessar a prpria API do Hibernate atravs do Spring. Hibernate template vai cuidar para abrir e fechar a SessionFactory do Hibernate para ns e automaticamente participar das transaes. importante destacar alguns mtodos importantes do HibernateTemplate como: find (String hql): Esse mtodo faz uma busca atravs de um HQL e retorna uma List. findByCriteria (DetachedCriteria dt): Esse mtodo realiza uma busca no banco de dados atravs de um objeto DetachedCriteria do Hibernate e retorna uma List. Delete (String hql): Mtodo que deleta dados no banco a partir de uma query hsql. saveOrUpdate (Object entity): Mtodo que persiste um objeto no banco de dados. Esse mtodo realizar um insert se a chave primria (id) for null, do contrrio ele realizar um update. Get (Object entity,Serializable id): Mtodo que busca um objeto na base a partir do Class que representa o objeto e o id do objeto.

Voc pode utilizar os call backs disponibilizados pelo Spring se quiser ter acesso prpria SessionFactory do Hibernate, porm, com as facilidades do Spring de abrir/fechar a Session Factory, isso pode ser feito no mtodo execute que recebe um HibernateCallBack que uma interface do Spring. Veja no exemplo abaixo a utilizao desses mtodos citados acima:

Diego Pacheco http://diego-pacheco.blogspot.com

4-13

Spring Framework Framework para desenvolvimento de aplicaes java

package com.targettrust.spring.hibernate; public class Pessoa { private Long id; private String nome; private String email; public Pessoa() {} public Pessoa(String nome, String email) { super(); this.nome = nome; this.email = email; } public Pessoa(Long id, String nome, String email) { super(); this.id = id; this.nome = nome; this.email = email; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "nome: " + nome + ", email: " + email; } }

Cdigo 4.3 Pessoa.java

Diego Pacheco http://diego-pacheco.blogspot.com

4-14

Spring Framework Framework para desenvolvimento de aplicaes java

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="com.targettrust.spring.hibernate.Pessoa" table="pessoa"> <id name="id" column="id" type="java.lang.Long" unsaved-value="0"> <generator class="increment"/> </id> <property name="nome" column="nome" type="java.lang.String"/> <property name="email" column="email" type="java.lang.String"/> </class> </hibernate-mapping>

XML 4.5 Pessoa.hbm.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-2.0.xsd" > <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" > <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:file:///C:\\target\\spring\\db" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" lazy-init="false" > <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>com/targettrust/spring/hibernate/Pessoa.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.PointbaseDialect</prop> <!--<prop key="hibernate.hbm2ddl.auto">create</prop> -> </props> </property> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"

Diego Pacheco http://diego-pacheco.blogspot.com

4-15

Spring Framework Framework para desenvolvimento de aplicaes java

lazy-init="false" > <property name="sessionFactory" ref="sessionFactory" /> </bean> </beans>

XML 4.6 Configurao dos beans do Spring.


package com.targettrust.spring.hibernate; import java.util.List; import import import import import org.hibernate.criterion.DetachedCriteria; org.springframework.context.ApplicationContext; org.springframework.context.support.ClassPathXmlApplicationContext; org.springframework.dao.DataAccessException; org.springframework.orm.hibernate3.HibernateTemplate;

public class HibernateTemplateTest { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/hibernate/Springbeans.xml"); HibernateTemplate ht = (HibernateTemplate)ac.getBean("hibernateTemplate"); testeFind(ht); testeDetachedCriteria(ht); testeSave(ht); testeDelete(ht); testeGet(ht); } private static void testeFind(HibernateTemplate ht){ Object result = ht.find(" from " + Pessoa.class.getName()); System.out.println("Pessoas: " + result); } private static void testeDetachedCriteria(HibernateTemplate ht){ DetachedCriteria dt = DetachedCriteria.forClass(Pessoa.class); List dtResult = ht.findByCriteria(dt); System.out.println(dtResult); } private static void testeSave(HibernateTemplate ht){ Pessoa p = new Pessoa(); String nome = "PessoaHora" + System.currentTimeMillis(); p.setNome(nome); p.setEmail("noreplay@gmail.com"); ht.saveOrUpdate(p); ht.flush(); System.out.println(ht.find(" from where nome = '" + nome + "'")); } " + p.getClass().getName() + "

Diego Pacheco http://diego-pacheco.blogspot.com

4-16

Spring Framework Framework para desenvolvimento de aplicaes java

private static void testeDelete(HibernateTemplate ht){ Pessoa p = new Pessoa(); p.setNome("Ze Moleza"); p.setEmail("zemoleza@moleza.mesmo.br"); try{ ht.saveOrUpdate(p); ht.flush(); System.out.println("Pessoa: " + ht.find(" from " + Pessoa.class.getName() + " where nome = ?","Ze Moleza")); ht.delete(p); ht.flush(); System.out.println("Pessoa: " + ht.find(" from " + Pessoa.class.getName() + " where nome = ?","Ze Moleza")); }catch(DataAccessException e){ System.out.println(e.getMessage()); } } private static void testeGet(HibernateTemplate ht){ System.out.println("Pessoa carregada com get: " + ht.get(Pessoa.class, 3L)); } }

Cdigo 4.4 HibernateTemplateTeste.java

Neste exemplo foi configurado um DataSource para o banco de dados hsqldb e mais dois beans gerenciados pelo Spring a SessionFactoryBean e o HibernateTemplate. A partir dessas definies foi requisitado um HibernateTemplate ao Spring pela classe de testes.

Diego Pacheco http://diego-pacheco.blogspot.com

4-17

Spring Framework Framework para desenvolvimento de aplicaes java

Transaes Declarativas
Para ter esse tipo de recurso necessrio ter um servidor de aplicao como, por exemplo, JBOSS ou ORACLE IAS, mas se estou em uma aplicao java que roda fora de uma servidor JEE? Estou fadado a trabalhar com o gerenciamento de transaes em baixo nvel programaticamente? Se voc usa Spring framework a resposta no! O Spring capaz de fazer isso por ns e ainda mais, com Spring possvel ter transaes declarativas com aplicaes JDBC. De forma programtica podemos ter controle transacional atravs do TransactionTemplate do Spring que pode ser utilizado com o Hibernate. HibernateTransactionManager o TransactionManager do Spring para hibernate 3, esse objeto necessita de uma SessionFactory. Com o transactionTemplate podemos executar um cdigo atravs do mtodo execute que pode receber um TransactionCallBackWithoutResult para realizarmos alguma operao no banco. Apesar de o Spring facilitar esse trabalho, ainda assim essa abordagem custosa e pouco produtiva. A alternativa para esse problema pode ser o suporte de transaes declarativas do Spring framework. Esse mecanismo substitui as chamadas programticas por interceptor AOP aliados a proxys para adicionar o controle transacional. Dessa forma o componente pode se focar nas regras de negcio e o controle transacional ficar isolado de forma que poderemos trocar essa implementao sem afetar as regras de negcio da aplicao. Com o mecanismo de transaes declarativas do Spring possvel utilizar um contexto de transao gerenciado pelo HibernateTransactionManager com uma nica SessionFactory em uma ThreadLocal e depois trocar para transaes distribudas com JPA apenas trocando o manager de transao, sem afetar nada no seu cdigo j escrito. Antes do Spring 2.0 nos Springs 1.X.X era utilizado o TransactionProxyFactoryBean, ainda possvel utilizar esse recurso, o Spring prove total compatibilidade com isso. Existe uma grande vantagem em utilizar o HibernateTransactionManager por que ele ir expor a transao a nvel de conexo JDBC por DataSource, ou seja, se criarmos um JdbcTemplate com o mesmo DataSource da SessionFactory do Transactionanager teremos controle transacional entre Hibernate e JDBC de forma declarativa.

Diego Pacheco http://diego-pacheco.blogspot.com

4-18

Spring Framework Framework para desenvolvimento de aplicaes java

Para criarmos um controle transacional declarativo com Hibernate precisamos: DataSource SessionFactoryBean HibernateTransactionManager AOP Config TxAdvice

Primeiro vamos configurar o DataSource para acesso ao banco de dados, nesse exemplo vamos utilizar o HSQLDB.
<!-- Definio do Dataource para acesso ao banco HSQLDB --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="false" > <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:file:///C:\\target\\spring\\db" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean>

XML 4.7 DataSource

Apartir desse DataSource vamos cirar a SessionFactory do Hibernate.


<!-- Definio da SessionFactory do Hibernate --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" lazy-init="false" > <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>com/targettrust/spring/transaction/Produto.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </prop> </props> </property></bean>

XML 4.7 SessionFactoryBean

Diego Pacheco http://diego-pacheco.blogspot.com

4-19

Spring Framework Framework para desenvolvimento de aplicaes java

Agora o Gerente de Transaes, nesse caso ser o HibernateTransactionManager. Esse objeto depende da SessionFactory criada anteriormente.
<!-- Definio do TransactionManager, nesse caso o escolhido para a tarefa de gerenciar as transaes foi o org.springframework.orm.hibernate3.HibernateTransactionManager que gerncia transaes entre Hibernate e JDBC pelo DataSource --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>

XML 4.7 HibernateTransactionManager

Agora a configurao AOP para indicar como as classes devem ser interceptadas pela transao declarativa e quando interceptadas que advice elas devem utilizar. Aqui informamos que queremos interceptar todos os mtodos da classe ProdutoService, no importando o mtodo e os parmetros passados. Nessa configurao foi informado para utilizar um Advice.
<!-- Definio da configurao AOP, aqui criado um pointcut que define os pontos do sistema que sero interceptados, nesse caso a execuo de quaisquer mtodos do ProdutoService. Depois ele vincula essas classes interceptadas com um advice o txAdvice; --> <aop:config> <aop:pointcut id="produtoServiceMtodos" expression="execution(* com.targettrust.spring.transaction.ProdutoService.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="produtoServiceMetodos" /> </aop:config>

XML 4.7 AOP Config

No Advice estamos definindo que mtodos devem ter escopo transacional de fato. Os mtodos definidos so: findAll que necessitar de uma transao ativa, se essa transao no estiver ativa ele ir criar uma nova, esse mtodo est marcado como somente leitura, ou seja, ele s faz consultas na base. O outro mtodo o salvar* , significa que todos os mtodos que comecem com salvar sero transacionados e tero comportamento igual ao findAll, porm esses mtodos salvar podem fazer modificaes na base de dados.
<!-- Definio do Advide AOP que casa o gerente de transaes com os mtodos Esse beans informa que mtodos e como esses mtodos devem ser tratados pela transao --> <tx:advice id="txAdvice" transaction-manager="txManager">

Diego Pacheco http://diego-pacheco.blogspot.com

4-20

Spring Framework Framework para desenvolvimento de aplicaes java

<tx:attributes> <tx:method name="salvar*" propagation="REQUIRED" /> name="findAll" propagation="REQUIRED" read-only="true"/> </tx:attributes></tx:advice>

<tx:method

XML 4.7 TxAdvice

Quando o mtodo salvar do ProdutoService for invocado, o Spring ir criar uma nova transao se no existir nenhuma ativa, poderamos trocar essa forma de isolamento transacional. Poderamos usar REQUIRED_NEW que fora a criao de uma nova transao a cada chamada ao mtodo.

O Spring faz o controle de commit e rollback baseado em exceptions, toda exception unchecked levantada pelo componente transacionado ir demarcar a transao para rollback, essa uma maneira simples e eficiente de controlar commit/rollback. Se no fim da execuo de um mtodo transacionado nenhuma exception for levantada o Spring ira commitar. Caso alguma exception unchecked, leia-se, por exemplo, RuntimeException for levantada o Spring ir marcar para Rollback a transao e no final sempre executar um rollback. Podemos informar exceptions uncheckeds para o Spring e essas eceptions que ns informarmos sero ignoradas pelo mecanismo de demarcao transacional e o Spring no ir fazer rollback automtico para essas exceptions. Essa configurao feita no TxAdvice dentro do TxMethod na propriedade norollback-for onde podemos informar as exceptions.

Diego Pacheco http://diego-pacheco.blogspot.com

4-21

Spring Framework Framework para desenvolvimento de aplicaes java

Exerccios

1) Crie um Data Source para o banco de dados HSQLDB. 2) Defina um Bean JDBCTemplate. 3) Utilize o mtodo queryForObject e liste todos os produtos. 4) Faa um DAO que grave produtos utilizando transaes declarativas e caso o produto a ser gravado tenha valor <= 0 levante uma exception para invalidar a operao, aps salveo.

Diego Pacheco http://diego-pacheco.blogspot.com

4-22

Spring Framework Framework para desenvolvimento de aplicaes java

Espao para anotaes

Diego Pacheco http://diego-pacheco.blogspot.com

4-23

Spring Framework Framework para Desenvolvimento de Aplicaes Java

5. Facilitadores

Diego Pacheco http://diego-pacheco.blogspot.com

Spring Framework Framework para desenvolvimento de aplicaes java

Objetivos

Saber configurar e enviar e-mails; Saber agendar tarefas com JDK Task; Saber interceptar mtodos com o AOP; Saber montar um context de test com Junit; Saber expor um servio via RMI.

Diego Pacheco http://diego-pacheco.blogspot.com

5-2

Spring Framework Framework para desenvolvimento de aplicaes java

Envio de E-mails

O Spring framework prove facilidades para envio de e-mails. Para utilizar os recursos de envio de e-mail do Spring devemos ter duas bibliotecas adicionais em nosso classpath, essas bibliotecas so: Java Mail (mail.jar) JAF (activation.jar) Java Mail a implementao padro da SUN para envio de emails e JAF um framework do Java para trabalhar com imagem JPEG. Se voc baixou a distribuio completa do Spring na pasta lib voc encontrar essas bibliotecas. A interface central para o envio de e-mails no Spring a interface MailSender, na classe SimpleMailMessage temos um objeto simples com getters e setters para servir de formulrio de mensagens. O Spring prove uma hierarquia de exceptions para e-mail, facilitando e padronizando o controle de erros sobre o envio de e-mail, as exceptions pertencentes a esse mecanismo so: MailException: Exception base que todas as exceptions de envio de e-mails estendem. MailAuthenticationException: Exception que levantada se ocorer algum erro ao fazer a autenticao no servidor. MailParseException: Exception que levantada se ocorrer algum erro ao fazer parte de alguma propriedade da mensagen. MailPreparationException: Exception que levantada se ocorrer algum erro e no for possvel preparar a mensagem de e-mail, essa exception levantada normalmente se voc est utilizando velocity e no conseguiu iniciar a engine do velocity ou algo do gnero. MailSendException: Exception que levantada se ocorrer algum erro no momento de enviar o e-mail. A interface JavaMailSender adiciona funcionalidades especializadas ao envio de e-mails como por exemplo suporte a MINE para o MailSender. JavaMailSender
Diego Pacheco http://diego-pacheco.blogspot.com 5-3

Spring Framework Framework para desenvolvimento de aplicaes java

tambm prove um suporte em forma de call back para a preparao de MINE chamada MineMessagePreparator. Agora vamos ver um exemplo prtico de como enviar e-mails com Spring. Primeiro vamos configurar um MailSender, nesse caso ser o JavaMailSender, ao definir esse bean precisamos setar as propriedades: host, password, username, onde host o servidor de e-mail e username e password so usurio e senha.
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" > <property name="host" value="host.url.com.br" /> <property name="password" value="senha" /> <property name="username" value="username@host.com.br" /> </bean>

XML 5.1 Definio do bean JavaMailSender

Agora vamos definir o template de mensagens de email padro, aqui nesse bean que o SimpleMailMessage definimos para onde vai os e-mails atravs da propriedade from e definimos o titulo do e-mail na propriedade subject.
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage" > <property name="from" value= "user@host.com.br" /> <property name="subject" value="Teste e-mails com Spring" </bean>

/>

XML 5.2 Definio do bean templateMessage

Diego Pacheco http://diego-pacheco.blogspot.com

5-4

Spring Framework Framework para desenvolvimento de aplicaes java

Nesse bean definimos uma mensagem de e-mail especifica, nesse caso um email apenas de testes, esse bem construdo a partir de um template que um outro SimpleMailMessage isso feito via injeo de construtor, nesse bean configuramos para onde vai o e-mail e configuramos tambm o texto de mensagem, colocar esse tipo de configurao no Spring interessante pois fica fcil de manter e podemos reaproveitar para vrios trechos do sistema que necessite enviar esse e-mail.
<bean id="simpleMailMessage" class="org.springframework.mail.SimpleMailMessage" > <constructor-arg index="0" ref="templateMessage" /> <property name="to" value="dmetallica@gmail.com" /> <property name="text" value=" 123 Testando... " /> </bean>

XML 5.3 Definio do bean simpleMailMessage

Agora vem o programa Java, que faz o envio do e-mail de fato. requisitado no contexto do Spring um SimpleMailMessage que a mensagem e um MailSender para o envio.
package com.targettrust.spring.email; import import import import import org.springframework.context.ApplicationContext; org.springframework.context.support.ClassPathXmlApplicationContext; org.springframework.mail.MailException; org.springframework.mail.MailSender; org.springframework.mail.SimpleMailMessage;

public class TesteEnviaEmail { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/email/Springbeans.xml"); SimpleMailMessage msg = (SimpleMailMessage)ac.getBean("simpleMailMessage"); MailSender ms = (MailSender)ac.getBean("mailSender"); try{ ms.send(msg); } catch(MailException ex) { ex.printStackTrace(); } } }

Diego Pacheco http://diego-pacheco.blogspot.com

5-5

Spring Framework Framework para desenvolvimento de aplicaes java

Cdigo 5.1 TesteEnviaEmail.java

Uma outra alternativa seria o uso de MimeMessagePreparator. Que uma interface de call cack utilizada para facilitar o envio de mensagem MIME. Veja como poderamos usar no cdigo abaixo:
package com.targettrust.spring.email; import javax.mail.Message; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import import import import import org.springframework.context.ApplicationContext; org.springframework.context.support.ClassPathXmlApplicationContext; org.springframework.mail.MailException; org.springframework.mail.javamail.JavaMailSender; org.springframework.mail.javamail.MimeMessagePreparator;

public class TesteMimeMessagePreparetor { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "/com/targettrust/spring/email/Spring-beans.xml"); JavaMailSender ms = (JavaMailSender)ac.getBean("mailSender"); MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("to@server.com")); mimeMessage.setFrom(new InternetAddress("from@server.com.br")); mimeMessage.setText("Esse um email de teste!"); } }; try { ms.send(preparator); } catch (MailException e) { System.out.println(e.getMessage()); } } }

Cdigo 5.2 TesteMimeMessagePreparator.java

Outra soluo interessante seria o uso da MimeMessageHelper que abstrai e facilita a criao de mensagens. Veja no cdigo abaixo:
package com.targettrust.spring.email; import javax.mail.internet.MimeMessage; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;

Diego Pacheco http://diego-pacheco.blogspot.com

5-6

Spring Framework Framework para desenvolvimento de aplicaes java

import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; public class TesteMimeMessageHelper { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "/com/targettrust/spring/email/Spring-beans.xml"); JavaMailSender ms = (JavaMailSender)ac.getBean("mailSender"); try{ MimeMessage message = ms.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message); helper.setFrom("form@server.com.br"); helper.setTo("dest@server.com"); helper.setText("Email MimeMessageHelper"); ms.send(message); }catch(Exception e){ e.printStackTrace(); } } }

Cdigo 5.3 TesteMimeMessageHelper.java

Para enviarmos anexos com o MimeMessageHelper bem simples, basta que quando criarmos o objeto MimeMessageHelper passemos a MimeMessage e true para indicar que o e-mail multipart. Depois s adicionar os arquivos atravs do mtodo addAttachment.
package com.targettrust.spring.email; import java.io.File; import javax.mail.internet.MimeMessage; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.FileSystemResource; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; public class TesteMimeMessageHelperAtt { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "/com/targettrust/spring/email/Spring-beans.xml"); JavaMailSender ms = (JavaMailSender)ac.getBean("mailSender");

try{ MimeMessage message = ms.createMimeMessage();

Diego Pacheco http://diego-pacheco.blogspot.com

5-7

Spring Framework Framework para desenvolvimento de aplicaes java

MimeMessageHelper helper = new MimeMessageHelper(message,true); helper.setFrom("from@server.com.br"); helper.setTo("to@server.com"); helper.setText("Email MimeMessageHelper"); FileSystemResource file = new FileSystemResource(new File(".").getCanonicalPath() + "/build.xml"); helper.addAttachment("build.xml", file); ms.send(message); }catch(Exception e){ e.printStackTrace(); } } }

Cdigo 5.4 TesteMimeMessageHelper.java com envio de anexos.

Poderamos ainda mostrar mandar um e-mail em formato html, isso nos possibilitaria um leque muito maior de possibilidades em termos de recursos visuais. Nesse caso poderamos anexar uma imagem e mostrar ela no corpo do email ao invs de estar anexada a mensagem. Para isso devemos utilizar o mtodo addInLine e relacionar o id do in line com o id cid html. Veja no exemplo abaixo:
package com.targettrust.spring.email; import java.io.File; import javax.mail.internet.MimeMessage; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.FileSystemResource; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; public class TesteMimeMessageHelperAttImg { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext( "/com/targettrust/spring/email/Spring-beans.xml"); JavaMailSender ms = (JavaMailSender)ac.getBean("mailSender");

try{ MimeMessage message = ms.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message,true); helper.setFrom("form@server.com.br"); helper.setTo("dest@server.com"); helper.setText("<html><body><img src='cid:img1'><br>Email MimeMessageHelper com suporte a imagems em linha!</body></html>",true);

Diego Pacheco http://diego-pacheco.blogspot.com

5-8

Spring Framework Framework para desenvolvimento de aplicaes java

FileSystemResource file = new FileSystemResource(new File(".").getCanonicalPath() + "/imagem.jpg"); helper.addInline("img1", file); ms.send(message); }catch(Exception e){ e.printStackTrace(); } } }

Cdigo 5.5 TesteMimeMessageHelper.java com envio de anexos em linha html.

Importante: Para que a adio de recursos em linha funcione, voc deve adicionar primeiro o text e depois o recurso respeitando o cid. Se no, pode ser que no funcione corretamente.

Diego Pacheco http://diego-pacheco.blogspot.com

5-9

Spring Framework Framework para desenvolvimento de aplicaes java

Agendamento de tarefas com JDK Task

O Spring framework prov facilidades para agendamento de tarefas utilizando JDK Task ou se voc tiver necessidades mais profundas, como manter o agendamento mesmo que a maquina se desligue e outros recursos mais avanados voc deve utilizar o suporte do Spring ao Quartz. Nesse tpico vamos ver o mecanismo de agendamento de tarefas com JDK Task, que pode ser utilizado em regras de negcio ou algum requisito sistmico como, por exemplo, envio de emails ou checagem de arquivos. Agora voc ver duas maneiras de trabalhar com Jdk Task. A primeira envolve menos configurao XML, mas gera um acoplamento maior com o Spring. A segunda no gera acoplamento com o Spring, porm tem mais configurao XML. Vamos comear com o exemplo da forma que envolve menos configurao XML. Imagine que precisamos saber a hora a todo segundo na sada padro, para isso criamos um service. Esse Service deve implementar a interface TimerTask e sobrescrever o mtodo run.
package com.targettrust.spring.jdktask; import java.util.Date; import java.util.TimerTask; public class HoraCertaService extends TimerTask{ @Override @SuppressWarnings("deprecation") public void run() { System.out.println(new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds() ); } }

Cdigo 5.6 HoraCertaService.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-10

Spring Framework Framework para desenvolvimento de aplicaes java

Agora precisamos de um ScheduledTimerTask para o agendamento da tarefa e configuraes como, atraso inicial e intervalo de tempo que a tarefa deve rodar novamente.
<?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-2.0.xsd" > <bean id="horaCertaService" class="com.targettrust.spring.jdktask.HoraCertaService" /> <bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask" lazy-init="false" > <!-- Espera 0 ms antes de iniciar --> <property name="delay" value="0" /> <!-- roda de 1 em 1 segundo --> <property name="period" value="1000" /> <!-- Ira executar a TimerTask horaCertaService --> <property name="timerTask" ref="horaCertaService" /> </bean> </beans>

XML 5.4 ScheduledTimerTask bean

Voc pode ver que atravs da propriedade timerTask ligamos o nosso service de HoraCerta com esse agendamento de tarefa. Agora s falta injetarmos essa configurao em uma factory de agendamento de tempo.
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean" > <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask" /> </list> </property> </bean>

XML 5.5 TimerFactoryBean bean

Diego Pacheco http://diego-pacheco.blogspot.com

5-11

Spring Framework Framework para desenvolvimento de aplicaes java

Agora o XML completo do Spring ficar assim:


<?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-2.0.xsd" > <bean id="horaCertaService" class="com.targettrust.spring.jdktask.HoraCertaService" /> <bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask" lazy-init="false" > <!-- Espera 0 ms antes de iniciar --> <property name="delay" value="0" /> <!-- roda de 1 em 1 segundo --> <property name="period" value="1000" /> <!-- Ira executar a TimerTask horaCertaService --> <property name="timerTask" ref="horaCertaService" /> </bean> <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean" > <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask" /> </list> </property> </bean> </beans>

XML 5.6 Spring-beans.xml

Diego Pacheco http://diego-pacheco.blogspot.com

5-12

Spring Framework Framework para desenvolvimento de aplicaes java

Para testar basta rodar a classe de testes a baixo:


package com.targettrust.spring.jdktask; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestJdkTask { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/jdktask/Springbeans.xml"); System.out.println(ac); } }

Cdigo 5.7 TestJdkTask.java Porm essa abordagem gera acoplamento da nossa regra de negcios (HoraCertaService) com os recursos de agendamento de tarefas(TimerTask). Agora veremos uma abordagem que acaba com esse acoplamento, utilizando o MethodInvokingTimerTaskFactory Bean. Primeiro vamos refazer o HoraCertaService retirando o acoplamento com o Spring, o cdigo fica assim:
package com.targettrust.spring.jdktask; import java.util.Date; public class HoraCertaServiceNaoAcoplada { @SuppressWarnings("deprecation") public void showTime() { System.out.println(new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds() ); } }

Cdigo 5.8 HoraCertaServiceNaoAcoplada.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-13

Spring Framework Framework para desenvolvimento de aplicaes java

Perceba que o nome da classe foi alterado para enfatizar que esse um outro artefato e seu cdigo foi modificado de fato. Agora veja como ficam as injees do Spring:
<?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-2.0.xsd" > <bean id="horaCertaServiceNaoAcoplada" class="com.targettrust.spring.jdktask.HoraCertaServiceNaoAcoplada" /> <bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask" lazy-init="false" > <!-- Espera 0 ms antes de iniciar --> <property name="delay" value="0" /> <!-- roda de 1 em 1 segundo --> <property name="period" value="1000" /> <!-- Ir executar a TimerTask horaCertaService --> <property name="timerTask" ref="executor" /> </bean> <bean id="executor" class="org.springframework.scheduling.timer.MethodInvokingTimerTask FactoryBean" > <property name="targetObject" ref="horaCertaServiceNaoAcoplada" /> <property name="targetMethod" value="showTime" /> </bean> <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean" > <property name="scheduledTimerTasks"> <list> <ref bean="scheduledTask" /> </list> </property> </bean> </beans>

XML 5.7 Spring-beans-2.xml

Diego Pacheco http://diego-pacheco.blogspot.com

5-14

Spring Framework Framework para desenvolvimento de aplicaes java

O Que foi feito? Foi definido um bean chamado executor e esse bean um MethodInvokingTimerTaskFactoryBean, onde a propriedade targetObject define qual objeto ser invocado e a propriedade targetMethod define qual mtodo ser chamado. Depois esse bean timerTask=executor. associado ao scheduledTask pela propriedade

Agora o teste. Basta rodar a classe Java abaixo:


package com.targettrust.spring.jdktask; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestJdkTaskNaoAcoplado { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/jdktask/Springbeans-2.xml"); System.out.println(ac); } }

Cdigo 5.9 TestJdkTaskNaoAcoplado.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-15

Spring Framework Framework para desenvolvimento de aplicaes java

@Aspect Support

O Spring tem suporte a recursos AOP, no Spring 2.0 os recurso de aspectos so feitos utilizando AspectJ, isso significa que os comandos/syntax AspectJ funciona nas definies de pointcuts. O Mecanismo de AOP do Spring bastante rico, por que usa AspectJ e por que prove mais facilidades para o uso de aspectos. Se quisermos utilizar AspectJ teramos que criar artefatos .aj, com os recurso do Spring, basta criarmos uma classe Java normal, que ser a classe que executar aes com os objetos interceptados e utilizarmos o conjunto de annotations do Spring. Agora vamos definir alguns conceitos centrais de AOP, esses termos no so termos especficos do Spring, como a tecnologia AOP no to intuitiva valido formalizar algumas coisas. Aspect: Paradigma de programao que permite separar e organizar o cdigo conforme a importncia. Um aspecto pode modificar o comportamento de um objeto pela adio de comportamento (Advice) sobre um ponto de execuo (Join Point). Join Point: Representa um mtodo em execuo, as informaes de um Join Point so acessveis no corpo de um Advice. Advice: Ato de pegar um Aspect em um Join Point. uma forma de adicionar comportamento. Existem trs tipos de Advices: Before: Ser executado antes da execuo do mtodo. After: Ser executado depois da execuo do mtodo. Around: Ter poder de controlar a execuo do mtodo, podendo proceder a execuo do mtodo ou retornar o qualquer coisa. Point Cut: Ato de math bater um Aspect com um Join Point, os Advices so associados com Point Cuts. Target Object: Objeto Real. Objeto que tem um ou mais advices sobre seus joins points. AOP Proxy: Objeto criado pelo framework AOP a fim de executar contratos de aspectos, como Advices. No Spring os proxys AOP podem ser de dois tipos: Jdk Dynamic Proxy ou CGLib proxy. Isso transparente para o usurio. Weaving: a forma de misturar os aspectos com o cdigo target, essa poltica pode ser feita em tempo de compilao com o AspectJ Compiler ou em tempo de runtime, o Spring faz weaving em tempo de runtime.

Diego Pacheco http://diego-pacheco.blogspot.com

5-16

Spring Framework Framework para desenvolvimento de aplicaes java

A Compilao de AOP em Java puramente Java, no necessrio estender a hierarquia de class loader ou fazer qualquer configurao especial para utilizar aspectos. O Spring prove uma soluo eficiente para a maioria dos problemas corporativos com AOP, se voc necessita de um funcionalidade de math muito profundo ou interceptar fields a melhor escolha utilizar AspectJ diretamente. Para utilizarmos os recursos de @AspectJ support do Spring necessrio que os beans estejam sobre um proxy aop, existe uma forma de fazer isso automtico, basta colocar <aop:aspectj-autoproxy/> no xml de configurao do Spring. Isso assume que voc est utilizando o schema xsd correto. Se voc estiver utilizando o schema antigo em forma de dtd por usar a seguinte configurao: <beanclass="org.springframework.aop.aspectj. annotation.AnnotationAwareAspectJAutoProxyCreator" />. A Utilizao de DTD no Spring 2 no recomendada, use os recursos de xsd ao invs de dtd. Para que voc utilize esses recursos necessrio ter os seguintes jars no seu classpath: aspectjweaver.jar aspectjrt.jar Agora vamos a um exemplo completo de uso de @Aspect Support. Primeiro vamos criar trs Services. Cada um com um propsito distinto, neste exemplo eles s servem para ilustrar a interceptao de objetos distintos.

Vamos criar uma interface Service, que define o que os Services devem fazer.
package com.targettrust.spring.aop; public interface Service { public void fazAlgo(); }

Cdigo 5.10 Service.java Agora as implementaes dos trs services:


package com.targettrust.spring.aop; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ServiceA implements Service{ private static final Log log = LogFactory.getLog(ServiceA.class); @Override public void fazAlgo() {

Diego Pacheco http://diego-pacheco.blogspot.com

5-17

Spring Framework Framework para desenvolvimento de aplicaes java

log.info("Fiz algo do tipo A"); } }

Cdigo 5.11 ServiceA.java


package com.targettrust.spring.aop; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ServiceB implements Service{ private static final Log log = LogFactory.getLog(ServiceB.class); @Override public void fazAlgo() { log.info("Fiz algo do tipo B"); } }

Cdigo 5.12 ServiceB.java


package com.targettrust.spring.aop; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ServiceC implements Service{ private static final Log log = LogFactory.getLog(ServiceC.class); @Override public void fazAlgo() { log.info("Fiz algo do tipo C"); } }

Cdigo 5.13 ServiceC.java

Agora vamos registrar os beans no Spring, esse registro normal, bean id, classe e o proxy aop.
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd" >

Diego Pacheco http://diego-pacheco.blogspot.com

5-18

Spring Framework Framework para desenvolvimento de aplicaes java

<aop:aspectj-autoproxy/> <bean id="aspecto" class="com.targettrust.spring.aop.Aspecto" lazy-init="false" /> <bean id="sa" class="com.targettrust.spring.aop.ServiceA" /> <bean id="sb" class="com.targettrust.spring.aop.ServiceB" /> <bean id="sc" class="com.targettrust.spring.aop.ServiceC" /> <bean id="services" class="java.util.ArrayList" > <constructor-arg index="0"> <list> <ref bean="sa" /> <ref bean="sb" /> <ref bean="sc" /> </list> </constructor-arg> </bean> </beans>

XML 5.8 Spring-beans.xml Agora a classe Aspecto. Essa classe possui a annotation @AspectJ e possui advices de before, after e around.
package com.targettrust.spring.aop; import import import import import import import org.apache.commons.logging.Log; org.apache.commons.logging.LogFactory; org.aspectj.lang.ProceedingJoinPoint; org.aspectj.lang.annotation.After; org.aspectj.lang.annotation.Around; org.aspectj.lang.annotation.Aspect; org.aspectj.lang.annotation.Before;

@Aspect public class Aspecto { private static final Log log = LogFactory.getLog(Aspecto.class);

Diego Pacheco http://diego-pacheco.blogspot.com

5-19

Spring Framework Framework para desenvolvimento de aplicaes java

@Before("execution(* com.targettrust.spring.aop.Service.*(..))") public void execucaoDeFazAlgoAntes() { log.info("To sabendo antes da execuo de Service"); } @After("execution(* com.targettrust.spring.aop.Service.*(..))") public void execucaoDeFazAlgoDepois() { log.info("To sabendo depois da execuo de Serice"); } @Around("execution(* com.targettrust.spring.aop.ServiceB.faz*(..)))") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { Object retVal = pjp.proceed(); log.info("To sabendo around SericeB"); return retVal; } }

Cdigo 5.14 Aspecto.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-20

Spring Framework Framework para desenvolvimento de aplicaes java

Agora vamos classe de testes:


package com.targettrust.spring.aop; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TesteAop { @SuppressWarnings("unchecked") public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/aop/Springbeans.xml"); List<Service> services = (List<Service>)ac.getBean("services"); for(Service s: services){ s.fazAlgo(); } } }

Cdigo 5.15 TesteAop.java

Se rodarmos esses artefatos java, teremos um retorno semelhante ao seguinte:


[INFO 16/09/2007 16:09:00.173 Aspecto.execucaoDeFazAlgoAntes(18) ] To sabendo antes da execuo de Service [INFO 16/09/2007 16:09:00.173 ServiceA.fazAlgo(11) ] Fiz algo do tipo A [INFO 16/09/2007 16:09:00.173 Aspecto.execucaoDeFazAlgoDepois(23) ] To sabendo depois da execuo de Serice [INFO 16/09/2007 16:09:00.174 Aspecto.execucaoDeFazAlgoAntes(18) ] To sabendo antes da execuo de Service [INFO 16/09/2007 16:09:00.174 ServiceB.fazAlgo(12) ] Fiz algo do tipo B [INFO 16/09/2007 16:09:00.174 Aspecto.execucaoDeFazAlgoDepois(23) ] To sabendo depois da execuo de Serice [INFO 16/09/2007 16:09:00.175 Aspecto.doBasicProfiling(29) ] To sabendo around SericeB [INFO 16/09/2007 16:09:00.175 Aspecto.execucaoDeFazAlgoAntes(18) ] To sabendo antes da execuo de Service [INFO 16/09/2007 16:09:00.175 ServiceC.fazAlgo(12) ] Fiz algo do tipo C [INFO 16/09/2007 16:09:00.175 Aspecto.execucaoDeFazAlgoDepois(23) ] To sabendo depois da execuo de Serice

Cdigo 5.16 Retorno da execuo do TesteAop.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-21

Spring Framework Framework para desenvolvimento de aplicaes java

Perceba que primeiro executado um Advice antes de um Service(a, b ou c) depois executado o prprio service e por ltimo um outro advice de after. Isso valido para os trs services, mas repare que o service b retorna Sabendo around B aps o advice after e o retorno da execuo via proceed(). O Spring ainda suporta os seguintes PointCuts: execution: faz math com uma determinada execuo de mtodo. within: faz math com mtodos limitados por tipos, exemplo: execuo de somente tipos DAO within(com.xyz.app.dao..*) this: limita o math para quando o proxy aop de um determinado tipo, por exemplo this(com.xyz.app.Serializable) para pegar somente aop proxies que implementem Serializable target: limita o math para quando o real target de um determinado tipo, semelhante ao this s que para o real target. args: limita o math para quando o join point tem argumentos dos tipos especificados. @target: quando o real target tem uma annotation do tipo da especificada aqui o math feito. @args: quando o real target tem uma annotation e essa annotation tem os tipos passados aqui o math feito. @annotation: quando o mtodo a ser executado tem a annotation especificada aqui. @within: quando qualquer tipo de target tem a annotation especificada aqui o math feito. O Spring framework tambm tem outros advices disponveis, alm de before, after e around. So eles: @AfterReturning: Advice que roda quando o mtodo em execuo faz math e retorna normalmente. @AfterThrowing: Advice que roda quando o mtodo em execuo faz math e retorna uma exception do mesmo tipo da informada.

Diego Pacheco http://diego-pacheco.blogspot.com

5-22

Spring Framework Framework para desenvolvimento de aplicaes java

Testing Support
O Spring framework prove integrao com frameworks de teste unitrio como por Junit e o TestNG. Dentre os recursos mais importantes podemos destacar auto-wire automtica para propriedades protected e rollback no final da execuo. Esse ltimo recurso importantssimo, pois podemos rodar um test e no final ele sempre dar rollback, assim no iremos sujar a base de dados. O Spring framerwork permite o uso de frameworks de mock objects como, por exemplo, o easy mock. Isso muito til, pois dessa forma podemos testar apenas a camada de services sem persistir na camada DAO, sendo que a camada DAO pode ser composta de mocks. Assim isolando o teste dos Services e deixando o teste rpido e funcional. possvel rodar testes integrados sem a necessidade de se fazer deploy no servidor de aplicao. Assim podemos testar recursos de SQL, Hibernate e transao sem o servidor de aplicao, isso d melhor desempenho aos testes. O mecanismo de test do Spring prove gerenciamento do contexto e cache, para promover a performance.

Diego Pacheco http://diego-pacheco.blogspot.com

5-23

Spring Framework Framework para desenvolvimento de aplicaes java

AbstractDependencyInjectionSpringContextTests
Essa classe do Spring prove as facilidades de gerenciamento de contexto do Spring, assim o primeiro mtodo de test a ser executado ser mais lento, porm os outros vo ser muito mais rpidos pois utilizaram o contexto que j foi iniciado. Para utilizar esse recurso necessrio implementar o mtodo: protected String[] getConfigLocations() que deve retornar um array de String com os arquivos de configuraes do Spring. O Spring utiliza seus recursos de autoWire by type para dar produtividade aos testes. Basta declarar um objeto e prover um setter que o Spring ir injetar automaticamente esse objeto para voc.
package com.targettrust.spring.testing; import java.util.Date; public class DataService { public Date getSysDate(){ return new Date(); } }

Cdigo 5.17 DataService.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-24

Spring Framework Framework para desenvolvimento de aplicaes java

<?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-2.0.xsd" default-lazy-init="true" > <bean id="dataService" class="com.targettrust.spring.testing.DataService" /> </beans>

XML 5.9 Spring-beans.xml


package com.targettrust.spring.testing; import java.util.Date; import junit.framework.Assert; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; public class TestDataService extends AbstractDependencyInjectionSpringContextTests { private DataService dataService; public void setDataService(DataService dataService) { this.dataService = dataService; } @Override protected String[] getConfigLocations() { return new String[]{"classpath:com/targettrust/spring/testing/Spring-beans.xml"}; } @SuppressWarnings("deprecation") public void testDataDoDataService(){ Date d = dataService.getSysDate(); Date l = new Date(); Assert.assertEquals(d.getDay(),l.getDay()); Assert.assertEquals(d.getMonth(),l.getMonth()); Assert.assertEquals(d.getYear(),l.getYear()); } }

Cdigo 5.18 TesteDataService.java classe de teste de fato.

Diego Pacheco http://diego-pacheco.blogspot.com

5-25

Spring Framework Framework para desenvolvimento de aplicaes java

Podemos utilizar os recursos de injees para testes em propriedades, assim no necessrio mtodos setters. Para isso precisamos fazer duas operaes. 1 No construtor da classe super.setPopulateProtectedVariables(true). de testes executar

2 O nome da varivel deve ser o mesmo nome do id do bean no Spring. E deve ser protected. Veja o cdigo de exemplo seguinte. Esse cdigo utiliza o mesmo service e o mesmo arquivo xml do exemplo anterior.
package com.targettrust.spring.testing; import java.util.Date; import junit.framework.Assert; import org.springframework.test.AbstractDependencyInjectionSpringContextTests; public class TestDataServiceWithProtected extends AbstractDependencyInjectionSpringContextTests { protected DataService dataService; public TestDataServiceWithProtected() { super.setPopulateProtectedVariables(true); } @Override protected String[] getConfigLocations() { return new String[]{"classpath:com/targettrust/spring/testing/Spring-beans.xml"}; } @SuppressWarnings("deprecation") public void testDataDoDataService(){ Date d = dataService.getSysDate(); Date l = new Date(); Assert.assertEquals(d.getDay(),l.getDay()); Assert.assertEquals(d.getMonth(),l.getMonth()); Assert.assertEquals(d.getYear(),l.getYear()); } }

Cdigo 5.19 TesteDataServiceWithProtected.java classe de teste de fato.

Diego Pacheco http://diego-pacheco.blogspot.com

5-26

Spring Framework Framework para desenvolvimento de aplicaes java

AbstractAnnotationAwareTransactionalTests

Essa classe possibilita o uso de testes transacionais e em conjunto com annotations para os testes. As annotations suportadas so: @DirtiesContext: Annotation que faz o mesmo que o mtodo setDirty isso far que o contexto seja recarregado nesse mtodo. @ExpectedException: Annotation que sinaliza que o mtodo deve retornar um exception especfica, se ele no retornar o teste ir falhar. @NotTransactionl: Indica que esse mtodo roda fora do contexto de transaes do Spring. @Repeat: Essa annotation recebe um nmero, por exemplo, 5. O Spring ir repetir esse teste cinco vezes.

Diego Pacheco http://diego-pacheco.blogspot.com

5-27

Spring Framework Framework para desenvolvimento de aplicaes java

AbstractTransactionalDataSourceSpringContextTests
Essa classe de testes utilizada para adicionar o suporte a transaes, e no final do teste ir fazer roll back automaticamente. Se existir a necessidade de efetuar o commit por causa de seu banco de dados, voc pode executar o mtodo super.setComplete() no construtor, isso far com que o commit seja executado ao invs do rollback. Veja como utilizar esse recurso na prtica com esse teste abaixo:
package com.targettrust.spring.testing;

import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTest s; import com.targettrust.spring.transaction.Produto; import com.targettrust.spring.transaction.ProdutoService; public class TesteTransactionWithRollBack extends AbstractTransactionalDataSourceSpringContextTests { protected ProdutoService produtoService; protected JdbcTemplate jdbcTemplate; public TesteTransactionWithRollBack() { //super.setComplete(); super.setDefaultRollback(true); super.setPopulateProtectedVariables(true); } @Override protected String[] getConfigLocations() { return new String[]{"classpath:/com/targettrust/spring/transaction/Springbeans.xml"}; } public void testSavePessoa() throws Exception{ Produto p = new Produto(); p.setNome("PRODUTO QUE NO DEVE APARECER NO BANCO DE DADOS"); p.setTipo("FANTASMA"); p.setValor(666d); produtoService.salvar(p); System.out.println(produtoService.findAll()); } }

Cdigo 5.20 TesteTransactionalWithRollBack.java classe de teste de fato.

Diego Pacheco http://diego-pacheco.blogspot.com

5-28

Spring Framework Framework para desenvolvimento de aplicaes java

Remoting com RMI


O Spring framework prove recursos de remoting. Imagine que voc tem um sistema construdo com Spring em sua corporao e um sistema novo necessita acessar dados do outro sistema, uma soluo expor os servios do Spring j existentes e assim no ter retrabalho e ter aproveitamento de cdigo, centralizao das regras de negcio e produtividade. Esses requisitos so possiveis e fceis de se atingirem com os recursos de remoting do Spring. O Spring pode expor um servio das mais diversas maneiras como: JMS, JMX, RMI, Http Invoker, Burlap, Hessian e at mesmo EJB. Nesse captulo vamos estudar a forma do Spring expor um servio via RMI. O RMI uma forma de RPC s que para objetos e permite efetuarmos chamadas remotas em aplicaes desenvolvidas em Java. A vantagem do RMI que podemos trafegar objetos complexos entre sistemas, sem termos muita preocupao com o protocolo.Para trafegarmos um objeto via o remoting RMI do Spring esse objeto deve obrigatoriamente ser Serializable. Para fazer a exposio de um servio do Spring via RMI basta utilizarmos o RmiServiceExporter. Para fazer a exposio obrigatrio o uso de interfaces, deve existir uma interface publica no servio. Essa interface ser utilizada pelo sistema que deseja acessar os dados. O nico ponto ruim que temos que abrir uma porta para tal operao, isso deve ser feito com cuidado por questes de segurana. Vamos aplicao prtica. Primeiro vamos definir uma interface de acesso, a HoraService.
package com.targettrust.spring.remoting; import java.util.Date; public interface HoraService { public Date getDate(); }

Cdigo 5.21 HoraService.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-29

Spring Framework Framework para desenvolvimento de aplicaes java

Agora vamos fazer uma implementao de servio padro para essa interface.
package com.targettrust.spring.remoting; import java.util.Calendar; import java.util.Date; public class HoraServiceImpl implements HoraService{ public Date getDate() { return Calendar.getInstance().getTime(); } }

Cdigo 5.22 HoraServiceImpl.java Configurao do Spring no servidor aplicao que expe o Servio para outras aplicaes acessarem.
<?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-2.0.xsd" > <bean id="horaService" class="com.targettrust.spring.remoting.HoraServiceImpl" /> <bean class="org.springframework.remoting.rmi.RmiServiceExporter" > <property name="serviceName" value="Target-HoraService"/> <property name="service" ref="horaService"/> <property name="serviceInterface" value="com.targettrust.spring.remoting.HoraService"/> <property name="registryPort" value="1199"/> </bean> </beans>

XML 5.10 server-beans.xml

Diego Pacheco http://diego-pacheco.blogspot.com

5-30

Spring Framework Framework para desenvolvimento de aplicaes java

Nesse arquivo de configurao do Spring, foi registrado o service de hora, o HoraServiceImpl. E exposto como RMI atravs do RmiServiceExporter esse projeto tem quatro propriedades que devem ser injetadas, so elas: serviceName: Nome do Servio que o cliente ir se conectar. service: Ref para o bean que o servio real. serviceInterface: Apontamento para a interface do servio. registryPort: Porta na qual ser disponibilizado o RMI. Agora vamos ao programa server quer ficar expondo o servio por tempo indeterminado, para fins didticos foi feito um while(true).
package com.targettrust.spring.remoting; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ContextServer { @SuppressWarnings("unused") public static void main(String[] args) throws Throwable { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/remoting/serverbeans.xml"); while(true){ Thread.sleep(10000L); } } }

Cdigo 5.23 ContextServer.java Agora vamos a configurao xml do cliente, que poderia ser um programa Java com RMI normal, nesse exemplo vamos utilizar os prprios recursos do Spring para isso.
<?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-2.0.xsd" > <bean id="horaService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean" > <property name="serviceUrl" value="rmi://localhost:1199/TargetHoraService"/> <property name="serviceInterface" value="com.targettrust.spring.remoting.HoraService"/> </bean>

Diego Pacheco http://diego-pacheco.blogspot.com

5-31

Spring Framework Framework para desenvolvimento de aplicaes java

</beans>

XML 5.11 cliente-beans.xml

Diego Pacheco http://diego-pacheco.blogspot.com

5-32

Spring Framework Framework para desenvolvimento de aplicaes java

Na configurao do Spring foi definido um bean, o bean horaService que est vindo de um proxy remoto. Dessa forma podemos trabalhar com o servio normalmente, at mesmo injet-lo em outros beans colaboradores. Para essas operaes de suma importncia a interface. Na definio desse bean passamos dois parmetros so eles: serviceURL: URL apontando para onde est o servio RMI. serviceInterface: Apontando para qual interface esse servio est exposto. Para finalizar o programa cliente que chama o server e testa o servio completo de RMI.
package com.targettrust.spring.remoting; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ContextCliente { @SuppressWarnings("unused") public static void main(String[] args) throws Throwable { ApplicationContext ac = new ClassPathXmlApplicationContext("/com/targettrust/spring/remoting/clientebeans.xml"); HoraService hs = (HoraService)ac.getBean("horaService"); System.out.println("Hora vinda do Service: " + hs.getDate()); } }

Cdigo 5.24 ContextCliente.java

Diego Pacheco http://diego-pacheco.blogspot.com

5-33

Spring Framework Framework para desenvolvimento de aplicaes java

Exerccios

1) Crie um Aspecto para logar todas as chamadas aos dados de um sistema. 2) Crie um agendamento com JDK Task que de cinco em cinco segundos manda um e-mail para uma pessoa informando se ouve alguma mudana no sistema. 3) Crie um servio de calculadora e exporte-o via RMI, faa um programa cliente com o suporte de Junit do Spring e suas classes de teste.

Diego Pacheco http://diego-pacheco.blogspot.com

5-34

Spring Framework Framework para desenvolvimento de aplicaes java

Espao para anotaes

Diego Pacheco http://diego-pacheco.blogspot.com

5-35

Você também pode gostar