Sunteți pe pagina 1din 75

Spring Framework Parte 1 -> Dependency

Injection
By Felipe Saab

Quem dessa rea e nunca ouviu falar de Spring Framework por favor levante a
mo.. timo, todo mundo pelo menos j ouviu falar desse tal de Spring.
Durante esta srie de tutoriais eu vou demonstrar o que , pra que server e como vc pode
utilizar o Spring para facilitar seus projetos.
Primeiramente, o que esse tal de Spring afinal de contas? Spring um framework que
propicia um container para sua aplicao, ou seja, sua aplicao roda em cima do
container do Spring. Tal container prov principalmente a Injeo de Dependncia e a
Programao Orientada a Aspectos.
Nesta primeira parte eu vou falar sobre o padro Injeo de Dependncia e os benefcios
que ele prov. Vamos l ento:
O padro de projeto Injeo de Dependncia diz que uma classe no deve criar as suas
dependncias, em outras palavras, uma classe no deve instanciar seus atributos. Ao
invs disso, eles devem ser injetados na classe atravs de um mecanismo externo, ou
atravs de quem criou o objeto desta classe.
Ainda no est claro n Vamos a um exemplo (baseado em um dos exemplos do livro
Spring in Action 2, 2008) para facilitar as coisas.
Vamos imaginar que fomos contratados para desenvolver o software do dolos Spring?,
uma competio de talentos musicais onde as pessoas cantam e/ou tocam. Primeiro de
tudo vamos desenvolver uma interface genrica o suficiente para todos os nossos
competidores:

public interface Competidor


public void apresentar();
}

Pronto, agora todo mundo que for competir no dolos Spring vai ter que implementar essa
interface para poder participar ( quase como se fosse a inscrio da competio
hahahahah pssima analogia.. ).
Vamos ento aos competidores, vamos comear com um cantor. Um cantor no toca
nenhum instrumento musical, ele apenas canta uma msica. Vamos ento interface que
descreve uma msica:

public interface Musica


public void cantar();
}

Baseado na interface, j podemos criar uma msica:

public class AtireiOPauNoGato implements Musica {

private static String[] letra = {


"Atirei o pu no gato t t",
"Mas o gato t t",
"No morreu reu reu",
"Dona Chica c",
"Admirou-se se",
"Do berro, do berro que o gato deu",
"Miau !!!!!!"};

public void cantar() {


for (int i = 0; i < letra.length; i++) {
System.out.println(letra[i]);
}
}
}

Legal, algum vai cantar a famosa cantiga Atirei o pau no gato. Vamos codificar o cantor
que ir fazer isso ento:

public class Cantor implements Competidor {

private Musica musica;

public Cantor() {
this.musica = new AtireiOPauNoGato();
}

public void apresentar() {


musica.cantar();
}

Prontinho. Agora toda vez que um cantor for se apresentar ele ir cantar Atirei o Pau no
Gato. Mas pera ai, tem alguma coisa que no faz muito sentido aqui no tem?
Ser que TODO cantor da nossa competio vai cantar a mesma msica? Acho que no
n E do jeito que esta classe est implementada, ns temos que mudar a classe para
ele cantar uma outra musica. Isso no l muito vivel
O que a Injeo de Dependncia prega que ao invs de o cantor se preocupar em ficar
preparando a msica que ele vai cantar, ele apenas vai receber a msica impressa um
pouco antes da competio e pronto.
Pensando nisso, o cantor ficaria assim:

public class Cantor implements Competidor {

private Musica musica;

public Cantor() {
}

public void setMusica(Musica musica) {


this.musica = musica;
}

public void apresentar() {


musica.cantar();
}
}
Pronto, o cantor j no est mais preparando a sua msica, pouco antes da apresentao
ele vai receber a msica (atravs do setter) e vai cant-la (porque quem bom faz ao vivo!
hehehe).
Ok ok, at aqui no teve absolutamente NADA do tal do Spring, e vc provavelmente ainda
no entendeu o porque desse monte de interfaces que parecem bobas no mesmo?
Vamos l, advinhem quem vai dar a musica para o cantor? EXATO!! O container do Spring
quem vai ser responsvel por entregar a msica para o nosso cantor, ou em termos mais
tcnicos, o container quem faz toda a linkagem dos beans (cada objeto manipulado pelo
container um bean, ex: uma musica, um cantor, um objeto que acessa o banco de dados,
etc).
Para ns vermos como isso tudo funciona (pq ngm gosta de bla bla bla), vou abrir o
NetBeans 6.8, criar uma nova Aplicao Java e criar as interfaces e classes descritas at
aqui.
O NetBeans j traz as bibliotecas do Spring Framework junto com a IDE, o que te
economiza um tempinho baixando-as. Clique com o boto direito na pasta Bibliotecas e
cliquem Adicionar bliblioteca e adicione a biblioteca Spring Framework 2.5

Uma vez que o Spring j est no classpath ns j podemos criar um arquivo de


configurao para descrever os beans da nossa aplicao. Toda a configurao do
container feita atravs de arquivos XML.
Sendo assim eu criei mais um pacote (conf) e criei o arquivo idolos.xml dentro dele, este
ser o arquivo que o Spring ir utilizar para o container da nossa aplicao.
A tag root dos arquivos de configurao do Spring a tag <beans> que define os
namespaces e os DTDs necessrios. De comeo deixe o arquivo 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">

</beans>

Essa a estrutura bsica de um arquivo de configurao (no se assuste com o tamanho


dessa tag, vc no precisa decorar essas coisas).
J que nossas classes esto prontas, vamos para o nosso primeiro competidor: Jos. O
Jos vai cantar Atirei o Pau no Gato. Para declar-lo e dar a msica pra ele vai 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="atireiopau" class="injecaodependencia.AtireiOPauNoGato" />

<bean id="jose" class="injecaodependencia.Cantor">


<property name="musica" ref="atireiopau" />
</bean>

</beans>

Aqui que o Spring comea a trabalhar, cada tag no arquivo de configurao representa
um objeto que o container ir gerenciar. No nosso exemplo, temos o bean atireiopau que
um objeto da classe AtireiOPauNoGato e o bean jose que eh um Cantor e vai cantar a
msica referenciada pelo bean atireiopau.
Em termos de cdigo, seria como se o container fizesse o seguinte:

injecaodependencia.AtireiOPauNoGato atireiopau = new


injecaodependencia.AtireiOPauNoGato();
injecaodependencia.Cantor jose = new injecaodependencia.Cantor();
jose.setMusica(atireiopau);
Essa a mgica da Injeo de Dependncia, o Jos teve a msica injetada nele, se a
gente quiser que ele cante outra msica no precisamos reescrever a classe Cantor,
apenas injetar uma msica diferente nele.
Isso torna a aplicao muito mais desacoplada, muito mais fcil de testar e de reusar os
mdulos!!!
Mas e para usar isso agora? Como que a gente pe isso pra funcionar? Eu quero ver o
Jos cantar!!!! hehehe
Vamos l ento, vamos ao cdigo da classe principal do nosso exemplo:

public class Main {

public static void main(String[] args) {


ApplicationContext ctx = new
ClassPathXmlApplicationContext("conf/idolos.xml");

Competidor competidor = (Competidor) ctx.getBean("jose");

competidor.apresentar();
}

A interface ApplicationContext justamente o container (um dos existentes) do Spring


Framework. Existe tambm a BeanFactory mas essa bem mais simples e eu no irei
coment-la.
O que acontece nesse cdigo ento o seguinte: criado o container passando o arquivo
de configurao que ele ir utilizar, depois recuperado o bean jose do container (nesse
momento o container instancia o bean e todas as suas dependncias) e por fim, ns
pedimos pro Jos se apresentar.
Voc dever ver ele cantando incrivelmente bem o clssico Atirei o Pau no Gato.
Porm o prximo competidor promete! Ele ir cantar E tocar Ciranda Cirandinha com uma
gaita!! Essa eu quero ver!!
Vamos s classes necessrias para o prximo competidor:

public class CirandaCirandinha implements Musica {

private static String[] letra = {


"Ciranda , cirandinha,",
"Vamos todos cirandar,",
"Vamos dar a meia volta,",
"Volta e meia vamos dar",
"",
"O anel que tu me destes,",
"Era vidro",
"E se quebrou.",
"O amor que tu me tinhas",
"Era pouco e se acabou.",
"",
"Ciranda , cirandinha,",
"Vamos todos cirandar,",
"Vamos dar a meia volta,",
"Volta e meia vamos dar"};

public void cantar() {


for (int i = 0; i < letra.length; i++) {
System.out.println(letra[i]);
}
}
}

public interface Instrumento {


public void tocar();
}

public class Gaita implements Instrumento {


public void tocar() {
System.out.println("FUU FUU FII FII");
}
}

public class CantorTocador extends Cantor {

private Instrumento instrumento;

public CantorTocador() {
super();
}

public void setInstrumento(Instrumento instrumento) {


this.instrumento = instrumento;
}

public void apresentar() {


instrumento.tocar();
super.apresentar();
instrumento.tocar();
}

Pronto, agora nosso prximo competidor est pronto para se apresentar. Sras e Srs dem
as boas vindas para Carlos:

<?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="atireiopau" class="injecaodependencia.AtireiOPauNoGato" />


<bean id="jose" class="injecaodependencia.Cantor">
<property name="musica" ref="atireiopau" />
</bean>

<bean id="ciranda" class="injecaodependencia.CirandaCirandinha" />


<bean id="gaita" class="injecaodependencia.Gaita" />
<bean id="carlos" class="injecaodependencia.CantorTocador">
<property name="musica" ref="ciranda" />
<property name="instrumento" ref="gaita" />
</bean>

</beans>

Agora basta chamar o Carlos para se apresentar ao invs do Jos:

public class Main {


public static void main(String[] args) {
ApplicationContext ctx = new
ClassPathXmlApplicationContext("conf/idolos.xml");
Competidor competidor = (Competidor) ctx.getBean("carlos");

competidor.apresentar();
}
}

E se a gente quisesse que o Carlos tocasse piano cantando Atirei o Pau no Gato?
Simples:

public class Piano implements Instrumento {


public void tocar() {
System.out.println("PLIN PLIN PLIN");
}
}

<?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="atireiopau" class="injecaodependencia.AtireiOPauNoGato" />


<bean id="jose" class="injecaodependencia.Cantor">
<property name="musica" ref="atireiopau" />
</bean>

<bean id="ciranda" class="injecaodependencia.CirandaCirandinha" />


<bean id="gaita" class="injecaodependencia.Gaita" />

<bean id="piano" class="injecaodependencia.Piano" />


<bean id="carlos" class="injecaodependencia.CantorTocador">
<property name="musica" ref="atireiopau" />
<property name="instrumento" ref="piano" />
</bean>

</beans>

Basta injetar os beans desejados nas dependncias e boa! Tudo segue seu fluxo natural.
Esta foi uma pequena (eu diria mnima) introduo Injeo de Dependncias no Spring
Framework. O container ApplicationContext possui muuuuuito mais funes para gerenciar
os seus beans, porm isso iria extender demais este assunto.
Acho que se voc leu o post at aqui, vc conseguiu pegar o que eu quis passar: programar
utilizando interfaces torna o seu cdigo muito mais limpo, fcil de entender, fcil de dar
manuteno, fcil de reutilizar, fcil de extender, ou seja, melhora tudo!!
Adicionando isso com a tcnica de Injeo de Dependncia torna a aplicao altamente
desacoplada em termos de componentes (voc pode utilizar a classe Cantor em qualquer
outra aplicao, s precisa passar uma classe que implemente a interface Musica pra ele e
tudo vai funcionar perfeitamente).

Spring Framework Parte 2 -> Aspect


Oriented Programming
By Felipe Saab
Consideraes iniciais: se vc veio ler este post e ainda no leu o post anterior (Spring
Framework Parte 1 -> Dependency Injection), por favor o faa! Caso contrrio voc pode
no entender os cdigos utilizados aqui.
Beleza, daqui pra frente vou assumir que voc j sabe como linkar os beans no Spring
utilizando o arquivo de configurao (pelo menos o bsico, como visto na Parte 1 desta
srie).
Vamos ao nosso post ento: AOP: Aspect Oriented Programming (POA: Programao
Orientada a Aspectos). E como sempre, pra fugir um pouco dos termos tcnicos, vamos
a uma histria:
Imagine que voc est desenvolvendo um e-commerce, atualmente est desenvolvendo o
checkout do teu sistema, ou seja, o cliente j escolheu tudo o que ele queria, e agora vai
fazer a transferncia eletrnica do pagamento (vamos imaginar que voc est
desenvolvendo tudo isso). Olhando com um nvel de abstrao muito alto o seu cdigo
poderia ser algo assim:

public class CheckoutService {


//...
public void efetuarPagamento(Carrinho carrinho){
LOGGER.log(new Date().toString() + " - Executando
efetuarPagamento(Carrinho carrinho)");
if (carrinho.getCliente().temPermissao()){
DAO.iniciarTransacao();
try {
carrinho.getCliente().debitar(carrinho.getValorTotal());
carrinho.finalizarCompra();
DAO.commit();
LOGGER.log(new Date().toString() + " - Pagamento efetuado!");
} catch (Exception e) {
DAO.rollback();
LOGGER.log(new Date().toString() + " - " + e.toString());
}
} else {
LOGGER.log(new Date().toString() + "Cliente no est
autenticado");
}
}
//...
}

D uma boa olhada no cdigo O que tem a ver mesmo com o checkout so apenas as
linhas:

carrinho.getCliente().debitar(carrinho.getValorTotal());
carrinho.finalizarCompra();

O resto cdigo responsvel por logging, controle de transao, permisso de acessos,


coisas que so necessrias porm que ocupam muito espao, sujam o cdigo. A idia da
orientao a objetos encapsular em um objeto todas as coisas referentes a ele, os
servios que ele vai prestar, e no ficar poluindo ele com outros cdigos que no tem nada
a ver com o seu propsito.
Mas esses cdigos so necessrios para a aplicao funcionar corretamente! O que fazer
ento? Orientao a Aspectos!!!
A Orientao a Aspectos surgiu exatamente para eliminar os cross-cutting
concerns (cdigo que necessrio, porm foge das preocupaes principais do objeto,
como no caso acima, o checkout tem que se preocupar com o logging, transao e
permisso).
OBS: Existem vrios termos tcnicos, sem graa, e difceis de entender envolvidos nesse
paradigma de programao. Ns vamos discutindo-os conforme o tutorial for andando.
Ento como eu fao para separar esse cdigo chato dos meus objetos? A Orientao a
Aspectos funciona assim:
-> Primeiro a gente separa o cdigo que no tem nada a ver com o nosso objeto (logging,
transao, permisso e tals) em um lugar separado. Esse lugar separado se
chama advice( o o que).
-> Ainda dentro do advice, definido onde o programa tem que dar uma paradinha para
que o cdigo que foi separado possa ser executado. Todo lugar que o programa pode dar
essa paradinha chamado de join point. Um join point pode ser por exemplo: uma
chamada de mtodo, a execuo de um mtodo, instanciao de objetos, execuo de
construtores, e mais alugns ( o quando).
-> Uma vez que ns j sabemos o que vai ser feito (advice) e quando vai ser feito (join
point), falta definir onde vai ser feito. Para isso servem os pointcuts. Geralmente so
definidos utilizando os nomes das classes e mtodos que queremos interceptar, mas
tambm podem ser definidos atravs de expresses regulares (logo mais veremos um
exemplo na prtica).
-> Por fim, o conjunto de tudo isso (o que vai ser feito, quando vai ser feito e onde vai ser
feito) chamado de aspect (aspecto).
Em muito poucas palavras isso a base da orientao a aspectos. Vamos ver como a
gente pode utilizar isso no Spring.
O Spring oferece diversos tipos de suporte a Orientao a Aspectos (eles foram evoluindo
atravs das verses), dentre eles o suporte para a orientao a aspectos declarativa (no
XML de configurao) e anotativa (utilizando annotations (se no sabe o que so
annotations clique aqui)).
Eu estudei as duas e devo dizer que me identifiquei muito mais com a orientao a
aspectos utilizando annotations, portanto ela que eu irei mostrar aqui (caso queira
aprender sobre o outro tipo eu aconselho fortemente o livro Spring in Action 2 (Manning,
2008), captulo 4).
OBS: Eu irei reaproveitar o cdigo da Parte 1, ento caso voc no tenha feito o tutorial
anterior eu aconselho a pelo menos pegar os cdigo de l. Tudo o que eu fiz foi renomear
o projeto para OrientacaoAspectos, o pacote principal para orientacaoaspectos e todas
as definies dos beans no arquivo de configurao para bater com o novo nome do
pacote.
Como o suporte de orientao a aspectos do Spring consegue usar a poderosa linguagem
do AspectJ (para definir pointcuts) ns vamos us-la aqui, para tanto necessrio o
download da biblioteca do AspectJ e a incluso dela no classpath. O arquivo pode ser
baixado no site do projeto.
S mais um detalhe: o arquivo que vc baixa do site eh um .jar chamado: aspectj-x.x.x.jar,
dentro dele que esto as bibliotecas que o Spring precisa, ento abra este arquivo com o
WinRAR (ou outro do gnero) navegue at a pasta /lib, extraia os .jar que esto l e os
adicione ao classpath.
Voltando ao escopo da nossa aplicao: o show de talentos dolos Spring, vamos adicionar
um requisito muito importante para qualquer programa de entrenimento: a platia!
Sem utilizar a orientao a aspectos ns teramos os seguintes cdigos:

public class Plateia {

public Plateia() { }

public void sentar(){


System.out.println("A platia est sentando");
}

public void desligarCelulares(){


System.out.println("A platia est desligando os celulares");
}

public void aplaudir(){


System.out.println("CLAP CLAP CLAP UHULL CLAP CLAP");
}

public void vaiar(){


System.out.println("UUUUUU!! E FORA! E FORA! UUUUU!! ");
}
}
public class Cantor implements Competidor {

private Musica musica;


private Plateia plateia;

public Cantor() {
}

public void setMusica(Musica musica) {


this.musica = musica;
}

public void setPlateia(Plateia plateia) {


this.plateia = plateia;
}

public void apresentar() {


plateia.sentar();
plateia.desligarCelulares();
try {
musica.cantar();
plateia.aplaudir();
} catch (Exception e) {
plateia.vaiar();
}
}
}

OBS: A platia estaria sendo injetada na classe Cantor pelo container assim como est
acontecendo com a musica.
Sem a orientao a aspectos, toda classe que implemente a interface Competidor tem que
ficar se preocupando com a platia. No certo o competidor ficar mostrando os assentos
para a platia, pedir para elas desligarem os celulares, se apresentar e por fim pedir para
eles aplaudirem ou vaiarem. Isso coisa que a platia tem que fazer sozinha!
Vamos utilizar todo o poder da orientao a aspectos para que a platia consiga fazer isso
sozinha. A classe Cantor volta a ser o que era antes, se preocupando somente em cantar a
sua musica:

public class Cantor implements Competidor {

private Musica musica;

public Cantor() {
}

public void setMusica(Musica musica) {


this.musica = musica;
}

public void apresentar() {


musica.cantar();
}
}

E a classe Plateia vai ser anotada para utilizar as funcionalidades da orientao a


aspectos:

@Aspect
public class Plateia {

public Plateia() { }

@Pointcut("execution(* *.apresentar(..))")
public void apresentacao() {}

@Before("apresentacao()")
public void sentar(){
System.out.println("A platia est sentando");
}

@Before("apresentacao()")
public void desligarCelulares(){
System.out.println("A platia est desligando os celulares");
}

@AfterReturning("apresentacao()")
public void aplaudir(){
System.out.println("CLAP CLAP CLAP UHULL CLAP CLAP");
}
@AfterThrowing("apresentacao()")
public void vaiar(){
System.out.println("UUUUUU!! E FORA! E FORA! UUUUU!! ");
}
}

Aconteceram algumas coisas aqui:


-> Primeiro de tudo, a classe foi anotada com a anotao @Aspect indicando o bvio: esta
classe ser um aspecto;
-> Depois foi criado um mtodo que no faz absolutamente nada
chamado apresentacao()cujo nico propsito deste mtodo ser anotado para se tornar
um pointcut (tornar entre aspas porque apresentar() continua sendo um mtodo que no
faz nada, apenas contm uma anotao que um pointcut).
O parmetro passado para a anotao @Pointcut uma frase na linguagem de descrio
de pointcuts do AspectJ. Segue uma pequena explicao dela (que eu acabei de fazer no
Paint!! hehehe):

-> Depois que o pointcut est definido, basta anotar os mtodos desejados especificando
quando e onde eles devem ser executados. Para especificar onde os mtodos sero
executados utilizado o nome do mtodo que est anotado com o pointcut (no nosso
exemplo a string apresentacao()) e para especificar quando existem algumas outras
anotaes. Creio que as mais utilizadas
so: @Before, @AfterReturning e @AfterThrowing(caso queira saber quais so as outras,
fique a vontade para fuar na documentao).
E voil, nosso aspecto est pronto! Para ele funcionar s falta mais uma coisinha, que no
to pequena assim (pelo menos na teoria, na prtica sim! ).
Para a orientao a aspectos funcionar devem ser criadas cpias dos objetos que
queremos interceptar. Tais cpias contm os advices (cdigos das cross-cut concerns) e
esse objeto que recebe as requisies, executa os advices e depois passa a requisio
para o mtodo do objeto original. Essas cpias de objetos que contm os advices so
chamados de Proxy (no plural: Proxies).
E at algumas verses atrs os proxies tinham que ser criados na mo!!! Imagine que
trabalho que dava Porm o Spring prov um mecanismo automtico para a criao dos
proxies (ufa!).
Segue o arquivo de configurao para podermos fazer nosso exemplo funcionar:

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

<!-- competidores -->


<bean id="atireiopau" class="orientacaoaspectos.AtireiOPauNoGato" />
<bean id="jose" class="orientacaoaspectos.Cantor">
<property name="musica" ref="atireiopau" />
</bean>

<bean id="ciranda" class="orientacaoaspectos.CirandaCirandinha" />


<bean id="gaita" class="orientacaoaspectos.Gaita" />

<bean id="piano" class="orientacaoaspectos.Piano" />


<bean id="carlos" class="orientacaoaspectos.CantorTocador">
<property name="musica" ref="atireiopau" />
<property name="instrumento" ref="piano" />
</bean>

<!-- platia -->


<bean class="orientacaoaspectos.Plateia" />
<aop:aspectj-autoproxy />
</beans>

Trs coisas novas apareceram no arquivo de configurao:


1 Na root tag () foi definido mais um namespace (xmlns:aop) e na localizao dos
esquemas esto os seus respectivos links. Isso necessrio para o arquivo de
configurao saber quais tags podem e quais no podem quando o assunto AOP;
2 Foi declarado o bean correspondente platia. Ele no tem o atributo id definido
porque provavelmente ns nunca precisaremos de uma referncia platia, eles fazem
tudo sozinhos! No tem porque darmos um id para a platia sendo que nunca iremos
utiliz-la;
3 A simples tag < aop:aspectj-autoproxy /> j diz para o Spring fazer todo o trabalho
duro de ficar criando os proxies para ns.
E isso caro leitor(a) (ser que mulher le isso? to brincando!! hehehe), agora s
compilar (in the java-way of course), pedir pra tia VM executar e ver a platia trabalhando
sozinha, que povo educado!
Saindo da historinha e voltando ao mundo real, extremamente fcil prover um
mecanismo de log simples e que pode sofrer modificaes facilmente utilizando a
programao orientada a aspectos. Suponha que sua aplicao utilize o mecanismo
padro de log do Java e queira mudar para o Log4J: simples! Basta ir no seu aspecto
responsvel pelo log, e alterar os cdigos. Voc s tem trabalho uma vez (e nem tanto
trabalho assim)!
Nos prximos posts veremos os mecanismos que o Spring prov para banco de dados,
transaes, segurana, e mais alguns. To fcil quanto um System.out.println(Hello
World).
Spring Framework Parte 3 -> Java
Database Connectivity (JDBC)
By Felipe Saab

Bem vindo leitor a mais um post da srie Spring Framework.


Caso voc ainda no leu os posts anteriores, por favor d um pulinho bem rpido neles:

Spring Framework Parte 1 -> Dependency Injection

Spring Framework Parte 2 -> Aspect Oriented Programming

Vamos ao nosso prximo assunto ento: JDBC e como o Spring facilita esse cara pra
gente!

Tirando essa imagem do livro Spring in Action 2 (Manning, 2008) ns j conseguimos


ver bem por cima como que o Spring pretende acessar de maneira padronizada a base de
dados (Hitting the database) atravs de um objeto de acesso aos dados (DAO), um
template (provido pelo prprio Spring) e caso ns quisssemos, o Spring tambm oferece
suporte padro para alguns frameworks de persistncia (ser um dos prximos artigos
desta srie).
Tudo muito legal, muito bonito! Vamos tentar seguir este modelinho porque ele bem
bonitinho e vai nos ajudar um pouco. Apenas avisando que o jeito que descreverei neste
tutorial no o nico jeito de acessar os dados atravs do seu driver JDBC, porm um
jeito que eu achei bem interessante e que vale a pena todos sabermos um pouquinho =]

Existem apenas 2 conceitos bsicos que o Spring nos sugere para o acesso rpido e fcil
aos dados atravs de drivers JDBC: DataSource (DAO fornecido pelo Spring) e
JdbcTemplate (template para acesso a dados atravs de um driver JDBC fornecido pelo
Spring):
DataSource uma classe provida pelo nosso querido Spring Framework e que se
preocupa com toda a conexo e conversao com o driver JDBC que iremos utilizar (neste
exemplo iremos utilizar o driver JDBC para o banco de dados MySQL). Em palavras um
pouco mais tcnicas, esta classe ir se resonsabilizar por nos entregar um
objetojava.sql.Connection, java.sql.Statement, entre esses objetos que utilizamos
quando o assunto conexo de dados JDBC.
JdbcTemplate uma outra classe muito til provida pelo nosso adorado Spring! Este
template prov mtodos padronizados para acessarmos os dados (selecion-los e
manipul-los), ou seja, fazer tudo o que podemos fazer com eles de um jeito bem fcil de
acessar (como voc ir descobrir logo a frente).
Muito bem, com esses dois conceitos j pintados na sua cabea, por favor responda
corretamente a prxima pergunta: J que estas classes so providas pelo nosso amigo
Spring, quem instancia elas?. Exato!! O prprio Spring cria os beans para estas classes,
tudo o que temos que fazer declarar estes beans no arquivo de configurao do Spring.
Vamos a ele ento:

<?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">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/spring_jdbc" />
<property name="username" value="root" />
<property name="password" value="123" />
</bean>

<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>

</beans>

To simples quanto encher um copo com gua! Eu sinto at orgulho de mostrar como
fcil conectar com uma fonte de dados JDBC atravs do Spring!
O nosso primeiro bean o dataSource. Como eu j disse ali em cima, esse o cara
responsvel por conversar com o driver JDBC. Ento nada mais justo que a gente ensinar
ele a se comunicar com o driver passando os parmetros corretos no Os parmetros
(injetados atravs da DI) passados para o dataSource foram: dataClassName (qual driver
JDBC ser usado), url (caminho do JDBC para se conectar at o banco de dados
desejado), username (login do banco de dados) e password (senha do banco de dados).
No caso desse nosso exemplo, o driver JDBC do MySQL, nunca esquea que o driver
deve estar no classpath em!!! Segue uma foto te ensinando como adicionar o driver JDBC
do MySQL no NetBeans:
E o segundo bean do arquivo de configurao o jdbcTemplate que o template provido
pelo Spring para facilitar a manipulao dos dados. A unica dependncia que este bean
tem o prprio dataSource, ou seja, ele precisa de uma referncia para um dataSource
para saber em qual banco ele vai executar os comandos que quisermos. Sendo assim, de
um jeito muito fcil (injeo de dependncia), ns passamos uma referncia do
nossodataSource j criado para ele. ^^
S fazendo uma pequena pausa no Spring agora, vamos falar um pouquinho do banco de
dados: criei uma tabela de Pessoas para fazermos nossos teste aqui. D uma olhada no
script de criao:

CREATE TABLE `Pessoas` (


`pes_cod` INT NOT NULL ,
`pes_nome` VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT
NULL ,
`pes_idade` INT NOT NULL ,
PRIMARY KEY ( `pes_cod` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Muuuito bem! A esta altura ns j temos os arquivos base para a conexo com o banco de
dados E o banco de dados! Vamos continuar a codificar mais algumas classes e veremos
o quo fcil o Spring tornou o acesso aos dados atravs do JDBC para ns.
J que temos a tabela pronta no banco de dados, precisamos desenvolver uma classe
Java que ir representar cada registro dessa tabela (para manipulao em memria n):
Pessoa.java

public class Pessoa {

private int cod;


private String nome;
private int idade;
public Pessoa() {
this.cod = -1;
this.nome = "No Encontrado";
this.idade = -1;
}

public int getCod() {


return cod;
}

public void setCod(int cod) {


this.cod = cod;
}

public int getIdade() {


return idade;
}

public void setIdade(int idade) {


this.idade = idade;
}

public String getNome() {


return nome;
}

public void setNome(String nome) {


this.nome = nome;
}

@Override
public String toString() {
return "Codigo: " + String.valueOf(this.cod)
+ " | Nome: " + this.nome
+ " | Idade: " + String.valueOf(this.idade);
}
}

Pronto, com a classe Pessoa agora fica bem mais fcil ns termos uma Pessoa em
memria! Vamos daqui pra frente tentar unir a classe Pessoa que acabamos de escrever
com o banco de dados, ou seja, inserir um objeto da classe Pessoa no banco de dados,
recuperar um objeto Pessoa do banco, e por ai vai
Caso voc acompanha este blog regularmente, j deve ter percebido que eu virei f de
utilizar as interfaces no desenvolvimento (os motivos so muitos! ento apenas acredite:
compensa!). J que eu sou um cara que gosta de seguir padres e tudo mais, vamos
codificar uma interface que ser muito til para o nosso acesso ao banco de dados:
IBanco.java

public interface IBanco {

public void InserirPessoa(Pessoa pessoa);

public void AtualizarPessoa(Pessoa pessoa);

public void ApagarPessoa(Pessoa pessoa);

public Pessoa SelecionarPessoa(Pessoa pessoa);


}
Esta interface obriga a classe que implement-la a dar suporte para as operaes CRUD
referntes aos objetos Pessoa juntamente com a tabela do banco de dados Pessoa (ficou
meio confusa essa frase? hehehe).
Como o cdigo sempre resolve tudo, vamos a ele que voc ir entender do que eu estou
falando:
BancoDados.java

public class BancoDados implements IBanco {

private JdbcTemplate jdbcTemplate;

public BancoDados() {
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {


this.jdbcTemplate = jdbcTemplate;
}

public void InserirPessoa(Pessoa pessoa) {


String sql = "INSERT INTO Pessoas(pes_cod,pes_nome,pes_idade)
VALUES(?,?,?)";
jdbcTemplate.update(sql, new Object[]{pessoa.getCod(),
pessoa.getNome(), pessoa.getIdade()});
}

public void AtualizarPessoa(Pessoa pessoa) {


String sql = "UPDATE Pessoas SET pes_nome = ?, pes_idade= ? WHERE
pes_cod = ?";
jdbcTemplate.update(sql, new Object[]{pessoa.getNome(),
pessoa.getIdade(), pessoa.getCod()});
}

public void ApagarPessoa(Pessoa pessoa) {


String sql = "DELETE FROM Pessoas WHERE pes_cod = ?";
jdbcTemplate.update(sql, new Object[]{pessoa.getCod()});
}

public Pessoa SelecionarPessoa(Pessoa pessoa) {


String sql = "SELECT * FROM Pessoas WHERE pes_cod = ?";

List resultados = jdbcTemplate.query(sql, new Object[]


{pessoa.getCod()},
new RowMapper() {

public Object mapRow(ResultSet rs, int i) throws


SQLException {
Pessoa p = new Pessoa();
p.setCod(rs.getInt("pes_cod"));
p.setNome(rs.getString("pes_nome"));
p.setIdade(rs.getInt("pes_idade"));
return p;
}
});

Pessoa pes = new Pessoa();


if (resultados.size() > 0) {
pes = (Pessoa) resultados.get(0);
} else {
pes.setCod(pessoa.getCod());
}

return pes;
}
}
Muito bem, vamos com calma
A primeira coisa que devemos notar que temos uma varivel de instncia
chamadajdbcTemplate. Como eu imagino que voc leitor um cara que associa tudo
muito rpido e j viu que um pouco mais pra baixo dessa varivel tem o setter dela, eu
imagino que voc j entendeu que essa varivel vai ser injetada atravs do container do
Spring n =]
Como ns j pedimos pro Spring criar um bean do tipo JdbcTemplate no arquivo de
configurao, daqui a pouco ns voltaremos nele e pediremos pra ele enviar uma
referncia do JdbcTemplate aqui pra essa nossa classe poder usar. Tudo muito prtico!
Depois disso o que ns podemos entender que a classe reescreveu os mtodos que a
interface obriga e os implementou de fato! Vamos entender eles rapidinho
Para as operaes de insero, alterao e excluso os mtodos so absolutamente
iguais: primeiro foi definido o SQL referente a operao e depois foi chamado o
mtodoupdate da nossa classe super amigvel: jdbcTemplate.
Existem dois detalhes para chamar a ateno na execuo destas operaes:
1 O SQL que foi montado no possui os valores finais. Ao invs deles esto presentes
pontos de interrogao ( ? ) representando parmetros.
2 Os parmetros informados no SQL so enviados como o segundo parmetro do
mtodo update do jdbcTemplate. Para a padronizao na chamada do mtodo
necessrio que todos os parmetros definidos no SQL sejam passados dentro de um vetor
de Object (mesmo que seja s um parmetro, ele tambm deve estar dentro do vetor).
Outra coisa que vale ser lembrada que o primeiro item do vetor ir ser includo no lugar
do primeiro parmetro do SQL (primeiro ponto de interrogao) ento tome cuidado para
passar os parmetros na ordem correta para o vetor de Object.
S mais um comentrio para a operao de seleo: tambm foi utilizado um SQL com
parmetro e um vetor de Object referenciando os parmetros porm o mtodo
dojdbcTemplate utilizado no foi o update, e sim o query!
O funcionamento deste mtodo bem interessante: ao invs de apenas 2 parmetros
(como no mtodo update), depois do vetor de Object passado um
objetoorg.springframework.jdbc.core.RowMapper que responsvel por mapear cada
registro retornado por um ResultSet interno ao jdbcTemplate em um objeto
correspondente ao registro e aps o mapeamento o objeto customizado adicionado a
umjava.util.List que o retorno final do mtodo query.
Exemplo do nosso caso: caso sejam retornadas 3 pessoas pelo SQL utilizado, o
mtodomapRow do objeto RowMapper ser invocado 3 vezes (uma para cada registro).
Cada vez que ele for invocado ser configurado um novo objeto Pessoa com os dados de
cada registro retornado do banco de dados e cada vez que o mtodo retornar um novo
objeto Pessoa ele ser guardado na lista que ser retornada pelo mtodo query.
Logo depois deste mtodo eu apenas retorno o primeiro objeto que est na lista ou ento
retorno um objeto com o mesmo cdigo da busca caso no foi encontrado nenhum
registro.
Sempre muito simples esses cdigos adoro isso ehheheh
Vamos adicionar um bean ao arquivo de configurao do Spring para o container tambm
instanciar a nossa classe responsvel pelo banco de dados e claro, vamos tambm j
injetar o JdbcTemplate no nosso novo bean:

<?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">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/spring_jdbc" />
<property name="username" value="root" />
<property name="password" value="123" />
</bean>

<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>

<bean id="banco_dados" class="spring_jdbc.BancoDados">


<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

</beans>

E isso tudo!!
Nossas classes base para o acesso e manipulao da entidade Pessoa no banco de
dados e no nosso prprio software j esto codificadas e bem funcionais. Tudo que
precisamos agora de um programinha exemplo para testarmos estas classes e ver como
iriam ser realmente usadas.
Segue a classe que contm o mtodo main desta aplicao:

public class Principal {

public static void main(String[] args) {


ApplicationContext ctx = new
ClassPathXmlApplicationContext("/conf/spring_jdbc.xml");

BancoDados banco = (BancoDados) ctx.getBean("banco_dados");

//cria os objetos Pessoa


Pessoa p1 = criar_pessoa(1, "Felipe", 18);
Pessoa p2 = criar_pessoa(1, "Felipe Saab", 21);
Pessoa felipe = null;

//insere no banco
try {
banco.InserirPessoa(p1);
System.out.println("1 - Pessoa Inserida");
} catch (Exception e) {
System.out.println("No foi possvel inserir o registro: " + e);
}

//recupera
try {
felipe = banco.SelecionarPessoa(p1);
System.out.println("2 - Pessoa recuperada: " + felipe);
} catch (Exception e) {
System.out.println("No foi possvel recuperar o registro: " + e);
}

//altera
try {
banco.AtualizarPessoa(p2);
System.out.println("3 - Pessoa Atualizada");
} catch (Exception e) {
System.out.println("No foi possvel atualizar o registro: " + e);
}

//recupera novamente
try {
felipe = banco.SelecionarPessoa(p2);
System.out.println("4 - Pessoa recuperada: " + felipe);
} catch (Exception e) {
System.out.println("No foi possvel recuperar o registro: " + e);
}

//apaga
try {
banco.ApagarPessoa(p2);
System.out.println("5 - Pessoa Apagada");
} catch (Exception e) {
System.out.println("No foi possvel apagar o registro: " + e);
}

//procura pela ultima vez


try {
felipe = banco.SelecionarPessoa(p2);
System.out.println("6 - Pessoa recuperada: " + felipe);
} catch (Exception e) {
System.out.println("No foi possvel recuperar o registro: " + e);
}
}

public static Pessoa criar_pessoa(int cod, String nome, int idade) {


Pessoa p = new Pessoa();
p.setCod(cod);
p.setNome(nome);
p.setIdade(idade);
return p;
}
}

Concordo que o exemplo meio grandinho mas bem fcil de entender no ?


Primeiro foram criados 3 objetos Pessoa (p1 Felipe, p2 Felipe Saab e felipe que ir
receber o resultado da busca no banco), depois foi inserido um dos objetos, procurado por
ele no banco, depois ele foi alterado com as informaes do outro objeto e foi recuperado
novamente, e por fim a Pessoa foi apagada do banco e s para garantir foi feita uma
ltima busca.
Este exemplo foi s para testar todas as operaes que ns implementamos. Caso voc
use algo parecido no seu software do dia a dia ir ver que tudo funciona perfeitamente
bem (cada operao no teu lugar certo).
isso ai leitor! Voc chegou ao fim deste post grando!!
Espero que tenha gostado da leitura e da funo que foi descrita aqui.
Caso queira fazer o download do projeto que eu desenvolvi como exemplo pode fazer o
download aqui (OBS: o projeto est com bibliotecas do NetBeans 6.8 (Spring 2.5 e MySQL
JDBC) ento ele s vai rodar 100% certo caso voc abra ele no NetBeans 6.8 ou superior,
caso contrario, apenas aproveite os cdigos fonte =] ).

Spring Framework Parte 4 -> Integrao


com o Hibernate
By Felipe Saab
Antes de comearmos mais um post da srie de tutoriais sobre o Spring Framework eu
sugiro a leitura dos posts anteirores (caso voc ainda no tenha conhecimento dos
assuntos abordados):

Spring Framework Parte 1 -> Dependency Injection

Spring Framework Parte 2 -> Aspect Oriented Programming

Spring Framework Parte 3 -> Java Database Connectivity (JDBC)

Assumindo ento que agora voc j sabe sobre o Spring, vamos ver como ele facilita o
uso do framework de mapeamento objeto-relacional Hibernate (verso 3.x).
OBS: Irei comentar detalhadamente apenas coisas relacionadas ao Spring, ou seja,
espero que voc j possua o conhecimento necessrio do Hibernate.
Apenas para lembrarmos como o Spring tenta padronizar o acesso a dados em uma base
de dados vamos dar uma olhada na imagem do post anterior (retirada do livro Spring in
Action 2, Manning 2008):

Interpretando a figura a gente consegue chegar em algo assim: o nosso objeto


responsvel pelas operaes de manipulao de dados ir utilizar um template (fornecido
pelo Spring) que saiba interagir com o Hibernate (que conste no classpath e cuja verso
seja 3.x) e que ir utilizar um DAO que saiba se comunicar com a base de dados (um data
source).

S com o pargrafo acima j deu pra ver que precisaremos criar e configurar alguns beans
no Spring: um data source que se comunique com a base de dados e um template que se
comunique com o Hibernate.
Vamos a eles ento:

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/hibernate_teste" />
<property name="username" value="root" />
<property name="password" value="123" />
</bean>

<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

Como voc pode notar o template precisa de uma referncia para um bean que seja uma
implementao de org.hibernate.SessionFactory e a depende de como voc est
acostumado a mapear os objetos para tabelas: utilizando XML ou Anotaes.
Utilizando XML:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>Livro.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

Utilizando classes anotadas:

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryB
ean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>spring_hibernate.modelo.Livro</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

Os beans so bem parecidos, precisam de pelo menos trs propriedades setadas via
injeo de dependncia:
dataSource -> referncia para o data source
hibernateProperties -> uma lista (do tipo props, onde tanto a chave (key) quanto o valor
so Strings) contendo as propriedades da session factory que queremos setar
E a terceira propriedade depende do bean que est sendo declarado:
se for LocalSessionFactoryBean utiliza-se a propriedade mappingResources que
recebe uma lista contendo todos os XMLs responsveis pelo mapeamento
se for AnnotationSessionFactoryBean utiliza-se a propriedade annotatedClassesque
recebe uma lista contendo todas as classes que representam o mapeamento
OK. Estes so os beans que o Spring fornece para facilitar a nossa vida ao utilizar o
Hibernate. Vamos ento a um pouco de cdigo para demonstrar como ns utilizamos tais
beans nas nossas prprias classes.
Primeiro de tudo, no banco de dados vamos criar uma tabela para os testes:

CREATE TABLE `Livros` (


`liv_cod` INT NOT NULL ,
`liv_titulo` VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT
NULL ,
PRIMARY KEY ( `liv_cod` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Nossa tabela ento ser sobre livros, contendo apenas o cdigo e o ttulo do livro, vamos a
classe que vai representar um livro:

public class Livro {

private int cod;


private String titulo;

public Livro() {
}

public int getCod() {


return cod;
}

public void setCod(int cod) {


this.cod = cod;
}

public String getTitulo() {


return titulo;
}

public void setTitulo(String titulo) {


this.titulo = titulo;
}
}

Um simples POJO para representar o livro


Neste tutorial eu irei fazer o mapeamento utilizando um XML, vamos a ele:

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


<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="spring_hibernate.modelo.Livro" table="Livros">
<id name="cod" column="liv_cod" type="int">
<generator class="increment"/>
</id>
<property name="titulo" column="liv_titulo" />
</class>
</hibernate-mapping>

Como a tabela contm apenas dois campos o mapeamento fica bem simples: a chave
primria que a varivel de instncia cod (coluna liv_cod) e a varivel de instncia titulo
ligada a coluna liv_titulo.
S chamando a ateno para o generator do cod, que increment, ou seja, no
precisamos setar o cdigo de um novo livro para adicion-lo ao banco, o novo cdigo ser
gerado sozinho pelo Hibernate.
Muito bem, agora que o mapeamento da classe Livro para a tabela Livros est feito
vamos comear a escrever o nosso DAO. Primeiro vamos a interface (gosto de reforar a
idia de que interfaces devem ser utilizadas):

public interface IBanco {

public Livro InserirLivro(Livro livro);

public void AtualizarLivro(Livro livro);

public void ApagarLivro(Livro livro);

public List<livro> SelecionarLivrosPorTitulo(String titulo);

public Livro SelecionarLivroPorCodigo(int cod);


}

Acho que o nico comentrio que essa interface merece no mtodo InserirLivro porque
ele recebe o Livro que ser inserido e retorna outro Livro. Isso se deve ao fato da varivel
de instncia cod do Livro ser nula quando o livro estiver sendo gravado no banco e aps a
sua gravao o Hibernate retorna qual valor foi atribudo como cdigo, ou seja, depois de
gravado no banco que ns descobrimos o valor do cdigo, ento apenas atualizamos o
objeto Livro com o seu novo cdigo e retornamos um objeto consistente.
Vamos implementao dessa interface para podermos ver como o template do Hibernate
facilita a nossa vida:

public class BancoDados implements IBanco {

HibernateTemplate hibernateTemplate;

public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {


this.hibernateTemplate = hibernateTemplate;
}

public Livro InserirLivro(Livro livro) {


int cod = (Integer) hibernateTemplate.save(livro);
livro.setCod(cod);
return livro;
}

public void AtualizarLivro(Livro livro) {


hibernateTemplate.update(livro);
}

public void ApagarLivro(Livro livro) {


hibernateTemplate.delete(livro);
}

public List<livro> SelecionarLivrosPorTitulo(String titulo) {


//utilizando criteria
DetachedCriteria crit = DetachedCriteria.forClass(Livro.class)
.add(Restrictions.like("titulo", titulo));
return hibernateTemplate.findByCriteria(crit);

//utilizando HQL
//String hql = "from Livro where titulo like '%"+titulo+"%'";
//return hibernateTemplate.find(hql);
}

public Livro SelecionarLivroPorCodigo(int cod) {


Livro livro = (Livro) hibernateTemplate.get(Livro.class, cod);
return livro;
}
}

Hibernate j facilita a vida do desenvolvedor, adicionando o Spring na brincadeira ento,


tudo fica mais fcil como voc acabou de ver.
Creio que os mtodos save, update e delete do template so completamente auto
explicativos.
Porm quando o assunto vai para o lado da busca e seleo de registros, temos alguns
mtodos que podem ajudar:
mtodo get que busca um objeto da classe passada por parmetro que contenha a
chave primria igual ao segundo parmetro
mtodo find que realiza uma busca de acordo com uma query HQL
mtodo findByCriteria para quem est mais acostumado a fazer busca com criterias
Os mtodos find e findByCriteria (e os outros find que o template tem disponvel)
retornam um List tipado com objetos relacionados consulta, no nosso caso ento
retornado um List .
Mais um pequeno detalhe: o HibernateTemplate que usamos nesta classe dever ser
injetado pelo container, ou seja, essa classe ser mais um bean para o Spring gerenciar. O
arquivo de configurao completo deste tutorial ser 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="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/hibernate_teste" />
<property name="username" value="root" />
<property name="password" value="123" />
</bean>

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>Livro.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="banco_dados" class="spring_hibernate.BancoDados">


<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>

</beans>

Como exemplo final eu s gostaria de deixar um cdigo de como utilizar essa classe
BancoDados:

public class Main {

public static void main(String[] args) {

ApplicationContext ctx = new


ClassPathXmlApplicationContext("conf/spring.xml");
System.out.println("Spring inicializado");

BancoDados banco = (BancoDados) ctx.getBean("banco_dados");

Livro livro1 = new Livro();


livro1.setTitulo("Spring + Hibernate");
Livro livro2 = new Livro();
livro2.setTitulo("Hibernate Avanado");
System.out.println("Objetos Livro inicializados");

livro1 = banco.InserirLivro(livro1);
livro2 = banco.InserirLivro(livro2);
System.out.println("Livros gravados no banco");

//zerando os objetos Livro


livro1 = null;
livro2 = null;

System.out.println("Selecionando livros por cdigo");


livro1 = banco.SelecionarLivroPorCodigo(1);
exibe(livro1);

livro2 = banco.SelecionarLivroPorCodigo(2);
exibe(livro2);

System.out.println("Selecionando livros que contenham 'Hibernate' no


ttulo");
List<livro> lista = banco.SelecionarLivrosPorTitulo("Hibernate");
for (Livro l : lista){
exibe(l);
}

System.out.println("Atualizando livro");
livro1.setTitulo(livro1.getTitulo()+" Segunda Edio");
banco.AtualizarLivro(livro1);

System.out.println("Apagando livro");
banco.ApagarLivro(livro2);
}

static void exibe(Livro livro) {


if (livro == null)
System.out.println("Livro no encontrado");
else
System.out.println("Livro -> cod: " + livro.getCod() + " | Ttulo:
" + livro.getTitulo());
}
}

Muito bem leitor, se voc chegou at aqui voc vai desenvolver com uma produtividade
bem alta porque agora que voc j sabe Hibernate E Spring voc pode se concentrar
muito mais na camada de negcios, ou seja, no precisa perder muito tempo codificando
acesso a banco de dados e operaes necessrias para manipulao dos dados.

Spring Framework Parte 5 -> Spring Web


MVC
By Felipe Saab

Antes de entrar no assunto deixe-me dar aquele aviso de praxe: caso voc no ainda no
conhea o bsico do Spring Framework d uma olhadinha nos posts anteriores dessa
srie:

Spring Framework Parte 1 -> Dependency Injection

Spring Framework Parte 2 -> Aspect Oriented Programming

Spring Framework Parte 3 -> Java Database Connectivity (JDBC)

Spring Framework Parte 4 -> Integrao com o Hibernate

Spring Security 3 -> Deixando sua aplicao Web segura!


Beleza, j que voc conhece o Spring vamos ao assunto de hoje: como o Spring
implementa o padro de projeto Model-View-Controller (MVC).
O MVC um padro de arquitetura de software que visa separar a lgica de negcio da
lgica de apresentao, permitindo o desenvolvimento, teste e manuteno isolado de
ambos (via Wikipedia).
A imagem acima descreve o fluxo das informaes no padro MVC:
1 O usurio dispara um evento atravs da camada de visualizao (clica em um boto
na pgina ou algo do gnero);
2 O controlador recebe o evento e coordena como as coisas vo acontecer do lado do
servidor, ou seja, passa o fluxo para os objetos necessrios para realizar a regra de
negcio;
3 O modelo utilizado para representar o domnio das informaes do negcio ento ele
chamado pelo controlador para a realizar a regra de negcio que deve ser realizada. O
modelo pode ainda ser usado para enviar os dados para a viso (camada onde o
usuriov as coisas acontecerem, uma pgina web por exemplo);
4 Depois que o controlador realiza a regra de negcio utilizando o modelo ele renderiza a
nova viso e a envia para o usurio. Criar uma aplicao utilizando o padro MVC nada
mais do que separar a lgica em pacotes (um que representa a interface com o usurio
viso, um que conter o domnio da aplicao modelo, e um que ter as classes
responsveis por controlar o fluxo da aplicao controlador) e fazer com que as
informaes sigam um caminho certo.

Aps essa pequena introduo terica vamos ver como o Spring implementa esse padro:

Figura 1 Fluxo
de informaes no Spring Web MVC
1 A requisio do usurio sempre chega em um nico servlet, o Dispatcher Servlet. Esse
um padro muito comum em frameworks MVC chamado front controller (controlador
frontal) onde um nico servlet responsvel por receber a requisio, delegar o
processamento para os outros componentes da aplicao e devolver uma resposta para o
usurio;
2 Uma vez que o Dispatcher Servlet tem a requisio ele precisa descobrir para
qualcontroller essa requisio ser enviada. Para isso ele pede ajuda para o Handler
Mapping. Baseado na URL da requisio ele indica qual o controlador a ser invocado;
3 A requisio ento enviada para o controlador que cuidar dos dados contidos nela.
Uma vez que o controlador recebe a requisio ele processa os dados que ela trouxe e
executa alguma regra do negcio da aplicao (faz uma venda, adiciona um novo produto
no estoque, aluga um dvd, abre uma os, );
4 Frequentemente a lgica processada pelo controlador resulta em alguma informao
que deve ser levada de volta para o usurio (o model). Somente enviar a informao de
volta no o suficiente, ela deve ser formatada de um jeito que o usurio a entenda, para
isso ela deve ser enviada para a view. Para isso o model e alguns dados da view so
encapsulados em um objeto ModelAndView e retornados ao Dispatcher;
5 Como o controlador no fica preso a apenas uma view ele envia uma dica no
objetoModelAndView para o Dispatcher saber para qual view deve enviar os dados. O
Dispatcher repassa essa dica para o ViewResolver que devolve qual view deve ser
chamada;
6 Por fim o Dispatcher envia as informaes (model) para a view (pgina JSP) que
acabou de descobrir. A pgina renderiza as informaes recebidas e devolvida ao
usurio.
Simples de entender, no!?
Vamos por a mo na massa ento! A IDE ser o NetBeans 6.9.1. Crie uma nova Aplicao
Web (Java Web > Aplicao Web) e no ltimo passo do assistente selecione o framework
Spring Web MVC (Figura 2) e finalize.

Figura 2 Incluir o framework Spring Web MVC no projeto


O NetBeans j cria alguns arquivos para ns (legal ele n). Vamos dar uma analisada nos
cdigos que ele gerou.

Figura 3 Arquivos gerados pelo NetBeans


O arquivo de configurao do Dispatcher Servlet o dispatcher-servlet.xml, nele so
declarados todos os beans que o servlet precisa para conhecer os controladores e os
outros componentes que o auxiliam no decorrer da aplicao.
Repare que o arquivo redirect.jsp o nico arquivo que fica fora do diretrio WEB-INF.
Isso feito porque uma boa prtica que todas as views fiquem dentro do diretrio WEB-
INF para que s possam ser acessadas a partir do Dispatcher. O redirect.jsp apenas envia
qualquer requisio feita na raiz da aplicao para a pgina index.jsp que est dentro do
WEB-INF.
Para poder fazer esse redirecionamento necessrio que o fluxo explicado logo antes (6
passos) seja seguido. Para tal o NetBeans criou os seguintes beans no arquivo de
configurao do Dispatcher:

<bean name="indexController"

class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />

O controlador que ser responsvel por uma requisio pgina index.jsp. Como esse
controlador no vai fazer nenhum processamento dos dados da requisio foi criado um
controlador da classe ParameterizableViewController que o Spring Web MVC j tem
implementado. O que ele faz apenas repassar um ModelAndView informando o nome da
view (informado no parmetro viewName) para o Dispatcher.

<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>

Quando utilizado o ParameterizableViewController necessrio mapear quais URLs


sero direcionadas para aquele controlador, por isso foi criado o bean urlMapping da
classeSimpleUrlHandlerMapping que apenas linka a url index.htm ao
controladorindexController.

<bean id="viewResolver"

class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />

O viewResolver quem vai ajudar o Dispatcher a saber para qual view encaminhar
oModelAndView que o controlador retornar (passo 5 do fluxo ali em cima). Como
noModelAndView s vai ter o nome lgico da view (no caso da index vai ter apenas a
Stringindex que foi definida no controlador indexController), o que o viewResolver faz
criar o caminho da view utilizando o prefixo e sufixo informados na declarao do bean.
Para descobrir o caminho da view index ele vai fazer:
WEB-INF/jsp/ + index + .jsp => resultando em WEB-INF/jsp/index.jsp
E por fim o NetBeans criou um bean sem id:

<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerM
apping"/>

Esse bean o cara que vai analisar todas as outras URLs e mape-las para os nossos
controladores. Isso vai ficar mais claro daqui a pouquinho quando fizermos o nosso
controlador.
Bom, vamos a nossa aplicao ento, vou utilizar a idia de uma aplicao que tem no
livroUse a Cabea: Servlets & JSP: uma aplicao que d conselhos sobre cerveja! O
usurio diz o tipo da cerveja que ele quer e nossa aplicao retorna alguns conselhos
sobre quais cervejas ele poderia tomar.
Vamos aproveitar a estrutura que o NetBeans j criou e apenas alterar a pgina index.jsp
para ser o nosso formulrio onde o usurio vai indicar qual tipo de cerveja ele quer tomar:

<%@page contentType="text/html" pageEncoding="UTF-8"%>


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

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cervejeiro Online</title>
</head>

<body>
<h3>Eu sou um cervejeiro profissional!</h3>
<form action="sugestor.htm" method="post">
<p>
Qual tipo de cerveja voc prefere?
<select name="tipo">
<option value="pilsen">Pilsen</option>
<option value="chop">Chop</option>
<option value="malzbier">Malzbier</option>
</select>
</p>
<p><input type="submit" value="Quer saber minha sugesto?" /></p>
</form>
</body>
</html>

Quando o usurio pedir o conselho da nossa aplicao sobre cervejas do tipo que ele
selecionou os dados sero enviados via POST para a URL sugestor.htm.
Lembra daquele bean que o NetBeans criou sem id
(ControllerClassNameHandlerMapping)? Ento, ele vai entrar em ao agora! Ele vai ser
chamado pelo Dispatcher para identificar qual controlador vai receber a requisio.
O processo que esse bean utiliza para identificar qual controlador vai ser chamado
apenas pegar a String existente na URL at .htm e concatenar com Controller. Nesse
caso o controlador que vai ser chamado o SugestorController. Caso nosso formulrio
enviasse os dados para cervejeiro.htm o controlador que o Dispatcher tentaria invocar
seria o CervejeiroController. Facinho no? ^^
Sendo assim vamos construir o nosso controlador:

public class SugestorController extends AbstractController {

private SugestorService sugestor;

public void setSugestor(SugestorService sugestor) {


this.sugestor = sugestor;
}

@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {

String tipo = request.getParameter("tipo");


List<cerveja> sugestoes = sugestor.sugerir(tipo);

ModelAndView modelAndView = new ModelAndView("sugestao", "cervejas",


sugestoes);

return modelAndView;
}
}

Uma coisa que no podemos esquecer: para o Spring entender que essa nossa classe
um controlador ela deve herdar de AbstractController ou qualquer outra classe que
represente um controlador para o Spring Web MVC (pode ver mais exemplos aqui
na referncia oficial).
Uma boa prtica no desenvolvimento de aplicativos MVC nunca deixar toda a lgica
dentro do controlador, usar ele apenas para delegar funes para outros componentes
para que esses sim executem a lgica.
Para isso servem os famosos Services! Nosso controlador recebe um SugestorService
(injetado pelo Spring) e delega para ele a funo de sugerir as cervejas para o usurio.
Depois que o SugestorService retorna uma lista de cervejas (j j veremos a
classe Cervejaque faz parte do model da nossa aplicao) para o controlador hora de
montar oModelAndView que deve ser retornado para o Dispatcher.
Nosso ModelAndView foi instanciado com 3 parmetros sendo o primeiro o nome da view
(aquela dica que o bean viewResolver vai usar para montar o nome do arquivo lembra?),
o segundo o nome que a lista de cervejas ter na pgina JSP e o terceiro a lista
propriamente dita, quer dizer, quando formos mostrar as cervejas na pgina WEB-
INF/jsp/sugestao.jsp (eu sei que voc lembra como o viewResolver acha o arquivo da
view, s escrevi ele ali pra voc no esquecer mesmo.. hehehe) a lista ter o
nomecervejas.

Figura 4 Fluxo de componentes que so executados para uma requisio (sem


contar com a view)
Com isso nosso controlador ficou muito bem projetado, recebe uma requisio, chama um
Service para realizar a lgica de negcio da aplicao e devolve um ModelAndView para o
Dispatcher. Exatamente o que se espera de um controlador: que ele controle os
componentes necessrios para a regra de negcio ser executada.
Vamos ver como o SugestorService funciona. Apenas um pequeno detalhe:
SugestorService uma interface que apenas diz que o Service que a implementar deve
sugerir uma lista de cervejas a partir do tipo ( bom utilizar as interfaces! se voc no tem
esse costume passe a ter! Lendo os primeiros posts dessa srie voc vai entender
porqu):

public interface SugestorService {


List<cerveja> sugerir(String tipo);
}
Agora vejamos como esse Service funciona mesmo atravs do SugestorServiceImpl:

public class SugestorServiceImpl implements SugestorService {

public List<cerveja> sugerir(String tipo) {


List<cerveja> cervejasSugeridas = new ArrayList<cerveja>();

if (tipo.equals("pilsen")){
cervejasSugeridas.add(criarCerveja("Skol", 600));
cervejasSugeridas.add(criarCerveja("Antartica", 600));
} else if (tipo.equals("chop")){
cervejasSugeridas.add(criarCerveja("Brahma", 600));
} else if (tipo.equals("malzbier")){
cervejasSugeridas.add(criarCerveja("Brahma Malzbier", 355));
cervejasSugeridas.add(criarCerveja("Caracu", 355));
}

return cervejasSugeridas;
}

private Cerveja criarCerveja(String nome, Integer quantidade) {


Cerveja cerveja = new Cerveja();
cerveja.setNome(nome);
cerveja.setQuantidade(quantidade);
return cerveja;
}
}

Apenas verificamos qual o tipo que o usurio selecionou e montamos uma lista de cervejas
a partir dele (desculpe se no gosta das que coloquei, juro que tentei ser bem simples e
ecltico).
A classe que representa nosso modelo um simples POJO com o nome e a quantidade
(em mls) da cerveja:

public class Cerveja {


private String nome;
private Integer quantidade;

public String getNome() {


return nome;
}

public void setNome(String nome) {


this.nome = nome;
}

public Integer getQuantidade() {


return quantidade;
}

public void setQuantidade(Integer quantidade) {


this.quantidade = quantidade;
}
}

Bom, com toda a regra de negcio implementada vamos para a pgina que vai mostrar as
cervejas sugeridas pela nossa aplicao (sugestao.jsp):

<%@ page contentType="text/html" pageEncoding="UTF-8"%>


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Minha Sugesto</title>
</head>
<body>
<h3>Eu acho que voc deveria experimentar:</h3>
<p>
<c:forEach items="${cervejas}" var="cerveja">
<li>
<c:out value="${cerveja.nome}"/> -
<c:out value="${cerveja.quantidade}"/>ml
</li>
</c:forEach>
</p>
<p>
<a href="index.htm">Voltar</a>
</p>
</body>
</html>

Apenas percorremos a lista de cervejas exibindo-as na tela (lembrando que o nome da


lista cervejas pois foi esse o nome que foi passado no ModelAndView l no Controller).
Para fazermos nossa aplicao rodar precisamos apenas declarar o SugestorController e
o SugestorServiceImpl no arquivo de configurao do Dispatcher Servlet:

<bean id="sugestorService"
class="br.javasimples.cervejeiro.service.impl.SugestorServiceImpl" />
<bean name="sugestorController"
class="br.javasimples.cervejeiro.controller.SugestorController">
<property name="sugestor" ref="sugestorService" />
</bean>

Prontinho!! Simples cdigos no? S com essas pequenas classes ns construmos um


Sugestor de Cervejas MVC!!!

Figura 5 Escolhendo um tipo e pedindo a opinio da aplicao


Figura 6 Cerveja sugerida pela aplicao
Espero que com esse pequeno tutorial e essa pequena aplicao voc tenha entendido
(pelo menos um pouco) o padro MVC e como ele torna nossa aplicao muito bem
estruturada. D uma olhada como os pacotes do meu projeto ficaram bem separados:

Figura 7 Hierarquia de pastas e pacotes da aplicao


Caso queira pegar o projeto fique a vontade para baix-lo por aqui.
Apenas um ltimo conselho antes de encerrarmos este post: o que foi apresentado aqui foi
a estrutura mais bsica possvel do Spring Web MVC, apenas com o que vimos voc
consegue fazer uma aplicao de pequeno porte porm eu aconselho fortemente voc
procurar aprender mais sobre o framework antes de utiliz-lo no desenvolvimento do seu
projeto de graduao (hehehe).
O Spring Web MVC contm muitos (muitos mesmo!) outros beans que facilitam muito a
vida do desenvolvedor! Vale mesmo a pena dar uma procurada por fontes mais
avanadas. Um livro bem didtico o Spring in Action 2 (Craig Walls, 2008) e
a referncia incrvel!

Spring Framework Parte 6 -> Injeo de


Dependncia via Anotaes
By Felipe Saab
Em todos os posts da srie at
agora ns utilizamos a injeo de dependncia declarativamente, ou seja, definimos em
um arquivo de configurao do Spring (um arquivo XML) qual bean ia ser injetado em qual
e ai ento o container fica responsvel por fazer isso em tempo de execuo.
Bem legal, j vimos que funciona e funciona muito bem desse jeito.
Porm, sempre tem um porm hehe conforme o sistema vai comeando a crescer os
arquivos de configurao comeam a se tornar verdadeiras teias de aranha. Crescem
muito!
E como a ideia do Spring simplificar ao invs de complicar existe um jeito alternativo aos
arquivos XML para configurar a injeo de dependncia nos nossos beans: anotaes.
Utilizando simples anotaes ns conseguimos deixar o(s) arquivo(s) de configurao do
Spring o mais simples possvel e ainda assim deixar o container cuidar da injeo de
dependncia.

NOSSA APLICAO
Vamos desenvolver um pequeno programa para simular o funcionamento de um
computador ento.
O projeto vai ter a seguinte estrutura:

OBS: a pasta lib contm todas as bibliotecas necessrias para rodar o projeto.
Vamos comear dando uma olhada no pacote br.blog.javasimples.spring.pecas para
vermos as interfaces que definem as pecas do computador:

/**
* Interface que define os mtodos necessrios para uma pea do computador.
*
* @author Felipe
*/
public interface Peca {

void ligar();

}
/**
* Interface que define os mtodos necessrios para um Monitor.
*
* @author Felipe
*/
public interface Monitor extends Peca {

/**
* Escreve uma mensagem na tela.
*/
void escreverNaTela(String mensagem);

}
/**
* Interface que define os mtodos necessrios para um Processador.
*
* @author Felipe
*/
public interface Processador extends Peca {

/**
* Soma dois inteiros.
*/
int soma(int x, int y);

Vamos dar uma olhada em como as implementaes dessas interfaces funcionam


(pacotebr.blog.javasimples.spring.pecas.impl):

/**
* Classe que representa um monitor CRT de 17 polegadas.
*
* @author Felipe
*/
public class Monitor17 implements Monitor {

private final int FREQUENCIA = 60;

/**
* {@inheritDoc}
*/
@Override
public void ligar() {
System.out.println("Iniciando o monitor [" + FREQUENCIA +
"Hz];");
}

/**
* {@inheritDoc}
*/
@Override
public void escreverNaTela(String mensagem) {
System.out.println("[" + mensagem + "]");
}
}
/**
* Classe que representa um processador DualCore.
*
* @author Felipe
*/
public class DualCore implements Processador {

private final double FRQUENCIA = 2.6;

private final int NUCLEOS = 2;

/**
* {@inheritDoc}
*/
@Override
public void ligar() {
System.out.println("Iniciando o processador [" + FRQUENCIA +
"GHz, " + NUCLEOS + " ncleos];");
}

/**
* {@inheritDoc}
*/
@Override
public int soma(int x, int y) {
return x + y;
}
}

Cada implementao especfica de um produto, ou seja, temos um monitor CRT de 17


que s suporta 60Hz e um processador DualCore (Intel) cuja frequncia 2.6GHz.
E o computador? Como fica?

/**
* Classe que representa o computador.
*
* @author Felipe
*/
public class Computador {

private Processador processador;

private Monitor monitor;

public Computador(Processador processador, Monitor monitor) {


super();
this.processador = processador;
this.monitor = monitor;
}

public void ligar() {


System.out.println("Ligando computador...");
processador.ligar();
monitor.ligar();
System.out.println("Computador ligado.");
}

public void somar(int x, int y) {


monitor.escreverNaTela(String.format("%d + %d = %d", x, y,
processador.soma(x, y)));
}
}

O computador foi escrito seguindo as melhores prticas de desenvolvimento conforme j


conversamos na Parte 1 da srie n:

Programao orientada a interfaces e no a implementaes: perceba que o


computador no sabe se na sua placa me tem um processador Intel ou AMD, ele s sabe
que tem um processador que sabe como ligar e somar;

Injeo de dependncia: perceba que todas as dependncias do computador so


injetadas nele atravs do seu construtor, com isso ganhamos muita flexibilidade para
futuras mudanas em relao a quais componentes devemos injetar no computador.

E o arquivo de configurao ficou da seguinte maneira:

<?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.xsd">

<bean id="computador" class="br.blog.javasimples.spring.Computador">


<constructor-arg name="monitor" ref="monitor" />
<constructor-arg name="processador" ref="processador" />
</bean>

<bean id="processador"
class="br.blog.javasimples.spring.pecas.impl.DualCore"/>

<bean id="monitor"
class="br.blog.javasimples.spring.pecas.impl.Monitor17"/>

</beans>

Para executar a nossa pequena aplicao temos a classe Main.java:

public class Main {

public static void main(String[] args) {


ApplicationContext context = new
ClassPathXmlApplicationContext("br/blog/javasimples/spring/config/applicationC
ontext.xml");
Computador pc = (Computador) context.getBean("computador");
pc.ligar();
pc.somar(2, 2);
}

O que acontece nela que criamos o container do Spring a partir do arquivo de


configurao, ligamos o computador e realizamos uma simples operao nele. Ao executar
essa classe ns recebemos a seguinte sada:

Ligando computador...
Iniciando o processador [2.6GHz, 2 ncleos];
Iniciando o monitor [60Hz];
Computador ligado.
[2 + 2 = 4]

Legal, tudo funciona como ns j estvamos acostumados.

Preparando o container
Por padro o container do Spring no vem com o suporte para injeo de dependncia via
anotaes habilitado. Para fazer isso ns precisamos fazer uma pequena alterao no
arquivo de configurao:

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


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:annotation-config />

<bean id="computador" class="br.blog.javasimples.spring.Computador"/>

<bean id="processador"
class="br.blog.javasimples.spring.pecas.impl.DualCore"/>

<bean id="monitor"
class="br.blog.javasimples.spring.pecas.impl.Monitor17"/>

</beans>

E como vamos utilizar a injeo de dependncia via anotaes ns j podemos remover


as injees declarativas do arquivo de configurao.
O Spring suporta algumas anotaes para a injeo de dependncia, so elas:

A anotao do prprio Spring Framework @Autowired;

A anotao @Inject da JSR-330 (Dependency Injection for Java);

A anotao @Resource da JSR-250 (Common Annotations for the Java Plataform).

Hoje vamos ver somente a @Autowired. As outras so bem parecidas e ficam por sua
conta o estudo ok?

A anotao @Autowired
A anotao @Autowired pode ser utilizada em setters, construtores ou at mesmo em uma
varivel de classe independe da sua visibilidade, ou seja, mesmo que private.
Na nossa aplicao podemos utiliz-la assim:

public class Computador {

private Processador processador;

private Monitor monitor;


@Autowired
public Computador(Processador processador, Monitor monitor) {
super();
this.processador = processador;
this.monitor = monitor;
}

// ...

Eu, particularmente, estou mais acostumado a utilizar assim:

public class Computador {

@Autowired
private Processador processador;

@Autowired
private Monitor monitor;

public Computador(Processador processador, Monitor monitor) {


super();
this.processador = processador;
this.monitor = monitor;
}

// ...

E a ltima maneira seria nos setters:

public class Computador {

private Processador processador;

private Monitor monitor;

public Processador getProcessador() {


return processador;
}

@Autowired
public void setProcessador(Processador processador) {
this.processador = processador;
}

public Monitor getMonitor() {


return monitor;
}

@Autowired
public void setMonitor(Monitor monitor) {
this.monitor = monitor;
}

// ...

OBS: os getters no so uma obrigatoriedade, coloquei apenas por conveno.


Simples assim, toda vez que precisarmos das dependncias elas estaro l! Para testar
podemos rodar o projeto novamente e veremos que nada mudou na sada, ou seja, tudo
ainda est funcionando!
O Spring deve obrigatoriamente achar um bean para injetar no atributo anotado
com@Autowired, caso contrrio ser lanada uma NoSuchBeanDefinitionException. Caso
o atributo possa ter ou no valor, ou seja, se pode acontecer de o Spring no achar um
bean para o atributo devemos setar a propriedade required da anotao para false:

public class Computador {

@Autowired
private Processador processador;

@Autowired(required=false)
private Monitor monitor;

// ...

Porm quando fizer isso tome o cuidado de sempre verificar se o atributo est nulo ou no
antes de utiliz-lo para evitar os famosos NullPointerException.
Outra coisa que devemos saber que o Spring realiza uma busca por tipo (byType) para
encontrar as dependncias para atributos anotados com @Autowired, ou seja, como
anotamos um atributo do tipo br.blog.javasimples.spring.pecas.Monitor o Spring vai
procurar por algum bean que implemente essa interface para poder injetar no nosso
computador.
Como disse anteriormente, caso ele no encontre nenhum bean ser lanada
uma NoSuchBeanDefinitionException.
Mas aqueles momentos em que voc tem uma ideia que voc acha que ningum teve
antes e se ele encontrar mais de um bean que implemente essa interface?
Esse ser o assunto do nosso prximo tpico, e s a nvel de curiosidade, caso isso
acontea e no seja tratado o Spring tambm ir lanar
uma NoSuchBeanDefinitionException.

Tratando dependncias ambguas


com@Qualifier
E agora entra mais uma anotao para o nosso arsenal! hehehe
Para tratar dependncias ambguas o Spring nos oferece a anotao @Qualifier e
algumas maneiras de utiliz-la. Antes de vermos todas essas maneiras vamos nos armar
uma prpria emboscada: criar mais um monitor para podermos simular tal erro.

/**
* Classe que representa um monitor LED de 22 polegadas.
*
* @author Felipe
*/
public class MonitorLED22 implements Monitor {

private final int FREQUENCIA = 75;

/**
* {@inheritDoc}
*/
@Override
public void ligar() {
System.out.println("Iniciando o monitor [" + FREQUENCIA +
"Hz];");
}

/**
* {@inheritDoc}
*/
@Override
public void escreverNaTela(String mensagem) {
System.out.println("[[[" + mensagem + "]]]");
}

Nosso novo monitor LED, muito melhor do que o antigo CRT, e tem 22, um tamanho
bem agradvel. Ele to melhor que at o seu mtodo de escrever coloca umas
frescurinhas a mais para tentar agradar o usurio (heheheh). Vamos adicion-lo ao arquivo
de configurao:

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


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:annotation-config />

<bean id="computador" class="br.blog.javasimples.spring.Computador"/>

<bean id="processador"
class="br.blog.javasimples.spring.pecas.impl.DualCore"/>

<bean id="monitor"
class="br.blog.javasimples.spring.pecas.impl.Monitor17"/>

<bean id="monitorLED22"
class="br.blog.javasimples.spring.pecas.impl.MonitorLED22"/>

</beans>

Se tentarmos rodar agora iremos ver a nossa to


comentada NoSuchBeanDefinitionException.
Vamos ver ento como podemos resolver isso de algumas maneiras diferentes.
Selecionando de acordo com o ID
Podemos especificar na anotao @Qualifier qual o ID do bean que queremos injetar:

public class Computador {

@Autowired
private Processador processador;

@Autowired
@Qualifier("monitorLED22")
private Monitor monitor;

// ...

Ao executar nossa aplicao assim ser exibida a seguinte sada indicando que nosso
computador est utilizando o monitor de 22:

Ligando computador...
Iniciando o processador [2.6GHz, 2 ncleos];
Iniciando o monitor [75Hz];
Computador ligado.
[[[2 + 2 = 4]]]

Selecionando de acordo com um qualificador


No exemplo anterior ns utilizamos o monitor novo, mas e se quisssemos utilizar o
antigo?

public class Computador {

@Autowired
private Processador processador;

@Autowired
@Qualifier("monitor")
private Monitor monitor;

// ...

Assim funciona porm no est muito intuitivo n Um Monitor anotado


com@Qualifier(monitor) no muito fcil de entender n, em uma futura manuteno o
pobre coitado vai ter que caar no XML qual o bean que tem id=monitor para poder
chegar na respectiva classe. Seria muito mais fcil se a anotao
fosse @Qualifier(monitorCRT17)no seria?
A primeira ideia que vem na cabea : beleza, vou mudar de id=monitor para
id=monitorCRT17! .
Como nossa aplicao apenas um exemplo bem pequeno no teria problema nenhum.
Mas imagine em uma aplicao grande que j est em produo.. O risco de gerar algum
erro mudando o id do bean um pouco maior.
Para evitar isso o Spring permite que informemos um qualificador para o bean. Podemos
fazer isso de duas maneiras diferentes:
No XML de configurao:

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


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config />

<bean id="computador" class="br.blog.javasimples.spring.Computador"/>

<bean id="processador"
class="br.blog.javasimples.spring.pecas.impl.DualCore"/>

<bean id="monitor"
class="br.blog.javasimples.spring.pecas.impl.Monitor17">
<qualifier value="monitorCRT17" />
</bean>

<bean id="monitorLED22"
class="br.blog.javasimples.spring.pecas.impl.MonitorLED22"/>

</beans>

Ou ento na prpria classe:

@Qualifier("monitorCRT17")
public class Monitor17 implements Monitor {

// ...

Criando qualificadores customizados


Se voc, assim como eu, acha que ficar se referindo diretamente aos IDs (ou at mesmo
qualificadores) no uma soluo muito elegante o Spring permite que criemos nossos
prprios qualificadores criando anotaes que sejam anotadas com @Qualifier.
Vamos criar um qualificador que vai qualificar as tecnologias dos monitores, ou seja,
@MonitorLED e @MonitorCRT (vou criar as anotaes em um novo
pacotebr.blog.javasimples.spring.pecas.anotacoes):

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})


@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MonitorCRT {
}
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MonitorLED {
}

E vamos tambm anotar cada monitor com seu respectivo tipo:

@MonitorCRT
public class Monitor17 implements Monitor {

// ...

}
@MonitorLED
public class MonitorLED22 implements Monitor {

// ...
}

Com isso podemos facilmente anotar a dependncia do computador com a nossa nova
anotao:

public class Computador {

@Autowired
private Processador processador;

@Autowired
@MonitorLED
private Monitor monitor;

// ...

Nesse momento h aquele flash na sua cabea (de novo) e voc pergunta: e se eu tiver 2
monitores de LED porm com tamanhos diferentes?.
Vamos adicionar um novo monitor de LED ao nosso projeto ento:

/**
* Classe que representa um monitor LED de 19 polegadas.
*
* @author Felipe
*/
@MonitorLED
public class MonitorLED19 implements Monitor {

private final int FREQUENCIA = 75;

/**
* {@inheritDoc}
*/
@Override
public void ligar() {
System.out.println("Iniciando o monitor [" + FREQUENCIA +
"Hz];");
}

/**
* {@inheritDoc}
*/
@Override
public void escreverNaTela(String mensagem) {
System.out.println("[[" + mensagem + "]]");
}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:annotation-config />

<bean id="computador" class="br.blog.javasimples.spring.Computador"/>


<bean id="processador"
class="br.blog.javasimples.spring.pecas.impl.DualCore"/>

<bean id="monitor"
class="br.blog.javasimples.spring.pecas.impl.Monitor17"/>

<bean id="monitorLED19"
class="br.blog.javasimples.spring.pecas.impl.MonitorLED19"/>

<bean id="monitorLED22"
class="br.blog.javasimples.spring.pecas.impl.MonitorLED22"/>

</beans>

Ao executar esse cdigo camos novamente na nossa


adorvel NoSuchBeanDefinitionException.
Para resolver isso podemos utilizar combinaes de qualificadores, ou seja, vamos criar
mais alguns qualificadores para as polegadas:

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})


@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Monitor19 {
}
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Monitor22 {
}

Vamos qualificar os monitores:

@MonitorLED
@Monitor19
public class MonitorLED19 implements Monitor {

// ...

}
@MonitorLED
@Monitor22
public class MonitorLED22 implements Monitor {

// ...

E por fim identificar corretamente qual monitor nosso computador ir possuir:

public class Computador {

@Autowired
private Processador processador;

@Autowired
@MonitorLED
@Monitor19
private Monitor monitor;

// ...

}
Ao executar esse cdigo recebemos a seguinte sada indicando que nosso monitor de 19
entrou em ao:

Ligando computador...
Iniciando o processador [2.6GHz, 2 ncleos];
Iniciando o monitor [75Hz];
Computador ligado.
[[2 + 2 = 4]]

Na minha humilde opinio essa a melhor e mais elegante soluo para resolver o
problema. Podemos fazer qualquer combinao com os qualificadores desde que ela
identifique somente um bean.

Descoberta automtica de beans


A utilizao da tag <context:annotation-config /> no arquivo de configurao do Spring
possibilita a utilizao de vrias anotaes para a injeo de dependncia porm no
elimina a necessidade de declarar todos os seus beans no arquivo de configurao.
Em um sistema grande ainda teremos que declarar muitos beans no XML, o que acaba
sendo um pouco chato
Para evitar isso o Spring tem uma facilidade que possibilita que ele mesmo procure pelos
beans em tempo de execuo, ou seja, no precisamos declar-los via XML.
Para isso precisaremos fazer uma mudana no arquivo de configurao:

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


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<context:component-scan base-package="br.blog.javasimples.spring" />

</beans>

Agora sim temos um belo arquivo de configurao em!


A tag <context:component-scan base-package=br.blog.javasimples.spring /> possibilita o
uso das anotaes que anteriormente a tag <context:annotation-config /> possibilitava e
ainda permite que o Spring procure sozinho por beans a partir do
pacotebr.blog.javasimples.spring (incluindo todos os subpacotes).
Porm o Spring s vai saber quais so os beans se eles estiverem identificados. Para
fazer isso basta anotarmos os beans com uma das seguintes anotaes:

@Component Uma anotao de propsitos gerais para identificar um bean;

@Controller Indica que o bean um controlador do Spring Web MVC;

@Repository Indica que a classe um repositrio de dados;

@Service Indica que a classe um servio.


OBS: Para @Controller, @Repository e @Service existem situaes em que essas
anotaes possuem um tratamento especial. Bateu a curiosidade? Go go Google!
hehehe
Como em nossa pequena aplicao ns no precisaremos de nenhum comportamento
especial podemos simplesmente anotar as nossas classes que representam beans para o
container com @Component:

@Component
public class Computador {

// ...

}
@Component
public class DualCore implements Processador {

// ...

}
@Component
@MonitorCRT
public class Monitor17 implements Monitor {

// ...

}
@Component
@Monitor19
@MonitorLED
public class MonitorLED19 implements Monitor {

// ...

}
@Component
@Monitor22
@MonitorLED
public class MonitorLED22 implements Monitor {

// ...

Ao executarmos nossa aplicao agora tudo ir funcionar perfeitamente bem (ou pelo
menos deveria hehehe).
nesse momento que voc tem sua ltima epifania do post e pergunta: u, l na classe
Main.java ns buscamos o computador pelo ID dele, como o Spring pegou a classe
certa?.
Muito bem observado! hehehe
Quando o Spring busca e cria automaticamente os beans ele seta o ID de cada bean com
o nome da classe no padro CamelCase para identificadores. Com
isso Computador ficacomputador.
Mas caso haja a necessidade de especificar qual ser o ID do bean basta informar na
prpria anotao @Component:

@Component("pc")
public class Computador {

// ...
}

E na hora de recuperar ele basta utilizar o novo ID:

public class Main {

public static void main(String[] args) {


ApplicationContext context = new
ClassPathXmlApplicationContext("br/blog/javasimples/spring/config/applicationC
ontext.xml");
Computador pc = (Computador) context.getBean("pc");
pc.ligar();
pc.somar(2, 2);
}

Concluso
E no fim do post temos um XML de configurao do Spring com apenas 1 linha!
No sei quanto a vocs mas eu acho isso fantstico, onde for possvel minimizar as
configuraes em XML melhor pois torna o cdigo bem mais legvel e fcil de entender.

Spring Framework Parte 7 ->


Agendamento de Tarefas
By Felipe Saab

Algo um tanto quanto comum em aplicaes de mdio / grande porte o agendamento de


tarefas.
Exemplos: toda madrugada atualizar alguns registros que dependam de data (ex:
contratos atrasados), todos os dias s 20:00h enviar e-mail para os clientes que faam
aniversrios no dia, todo domingo das 18:00h at 23:59h atualizar o data warehouse (DW)
da empresa com as vendas da semana.
Surgem muitas e muitas idias e possibilidades quando pensamos no agendamento de
tarefas. Legal, na viso do cliente e do seu gerente uma grande maravilha (de fato,
realmente ) mas ai chega um requisito na tua mesa te falando pramagicamente fazer
isso pra ontem.
E agora? Agora o Java Simples est aqui pra te ajudar!
Vamos criar um projeto utilizando o agendamento de tarefas provido pelo Spring pois
simples de usar e poderoso o suficiente para resolver a maioria das necessidades quando
o assunto agendamento.
Por que no utilizar o Quartz?
Pois uma ferramenta incrivelmente robusta que prov funcionalidades como suporte
para clusterizao e transaes JTA. Na boa, na maioria dos casos o Quartz um ferrari
pra comprar po na esquina como dizia uma professora que tive.
Vamos manter as coisas simples at que seja realmente necessrio complic-las!
* Mas eu confesso, a imagem do post do site do Quartz hehehe

Nossa aplicao
Vamos imaginar que voc trabalha em uma startup na rea de desenvolvimento de
software e o seu chefe te escolheu para criar uma pequena aplicao para ele poder ter
mais controle sobre a empresa.
Nessa empresa utilizado o Scrum como processo de desenvolvimento. Sempre antes de
ir embora os desenvolvedores acessam o sistema de controle da empresa para marcar
quais atividades esto concludas, quais esto em andamento e quais ainda esto
paradas.
Existem algumas mquinas que o chefe gosta de chamar de servidores (d um desconto
vai, est no comeo ainda) pois elas executam os papis de servidores de firewall, banco
de dados (onde roda o mysql) e de aplicaes (onde roda o tomcat).
O chefe quer chegar todo dia de manh e a primeira coisa que ele quer fazer verificar um
e-mail enviado pelo novo sistema com o andamento das tarefas do dia anterior, inclusive,
ele quer que no e-mail aparea em vermelho o nome das pessoas que no atualizaram o
status das tarefas no dia anterior pra ele poder ter uma conversinha com elas. hehehehe
Outra coisa que acontece bastante na empresa que os servidores costumar cair. Sempre
que isso acontece voc pensa: Eu j disse que aquelas mquina no so servidores! Viu
s! No aguentam a carga!.
Tudo bem, todos concordamos que essa situao no muito legal mas at a empresa
arranjar mais alguns clientes o chefe disse que no vai trocar nada. Por causa dessas
quedas frequentes ele tambm quer que toda vez que algum servidor pare de funcionar
ele receba um email avisando isso.
Uma ltima necessidade que a aplicao seja web e seja possvel o chefe saber qual
servidor parou, quando o e-mail foi enviado, enfim, um histrico de tudo que o seu
programa fez. Ele quer isso para que ele possa verificar tudo atravs do celular.
Recapitulando ento, a aplicao vai ser web, vai ter que enviar um e-mail bem cedo com
o andamento das tarefas do dia anterior e toda vez que algum servidor cair ele quer
receber um e-mail informando.
Legal, agora que j temos o nosso escopo vamos ao trabalho!
O projeto
No fim desse post teremos um projeto com essa estrutura:
Aps o projeto web ter sido criado e todas as dependncias corretamente referenciadas
vamos dar uma olhada no web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>

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

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

Apenas informamos o listener para carregar o Spring assim que a aplicao for iniciada e
definimos o arquivo para ser compatvel com servlets 3.0 .
O arquivo de configurao do Spring tambm no tem nenhum segredo:

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


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd">

<context:component-scan base-
package="br.blog.javasimples.spring.agendamento" />

<task:annotation-driven />

</beans>

Atravs da tag <context:component-scan> o Spring vai procurar sozinho pelos beans que
ele deve gerenciar (como explicado no post Injeo de dependncias via anotaes).
E atravs da tag <task:annotation-driven /> o Spring tambm vai procurar
automaticamente por tarefas agendadas e vai ficar responsvel pela execuo delas.
A interface Web
Nossa aplicao web vai usar uma estrutura bem simples (servlet + JSP) apenas para no
alongar muito o post.
A nica pgina que vamos desenvolver vai mostrar um histrico de tudo que a aplicao j
fez, vamos ver como ficaria a pgina index.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"


pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Tarefas Agendadas</title>
</head>
<body>
<p>
<a href="./historico">Recarregar...</a>
</p>
<p>Tarefas executadas:</p>

<c:if test="${historico != null && historico.size() > 0}">


<ul>
<c:forEach var="hist" items="${historico}">
<li>${hist}</li>
</c:forEach>
</ul>
</c:if>
</body>
</html>

Um simples JSP que vai mostrar todos os registros de um histrico que um servlet ir
retornar. Vamos dar uma conferida no servlet:

/**
* Servlet para a recuperao do histrico de todas as tarefas executadas.
*
* @author Felipe
*/
@WebServlet(value="/historico")
public class HistoricoServlet extends HttpServlet {

private static final long serialVersionUID = -3612078136798710447L;

@Autowired
private HistoricoExecucao historicoExecucao;

@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);

SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
config.getServletContext());
}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setAttribute("historico",
historicoExecucao.getHistorico());
RequestDispatcher dispatcher =
req.getRequestDispatcher("index.jsp");
dispatcher.forward(req, resp);
}

Toda vez que chegar uma requisio GET na URL /historico da nossa aplicao o servlet
vai carregar o histrico atravs do bean historicoExecucao e vai renderizar a
pginaindex.jsp para o usurio saber quais foram as ltimas tarefas executadas.
Por que a sobrescrita do mtodo init(ServletConfig)?
Bom nosso servlet possui um atributo que precisa ser injetado pelo Spring; o Spring s
consegue injetar dependncias em beans que esto sendo gerenciador por ele, ou seja, os
beans devem estar no contexto do Spring para terem suas dependncias injetadas; em
tempo de execuo quem vai instanciar o servlet o container web (ex: tomcat) e no o
Spring;
Sendo assim, quando o servlet instanciado ele no est no contexto do Spring e
consequentemente no ter suas dependncias injetadas. Para ter as suas dependncias
injetadas ns invocamos o mtodo esttico
processInjectionBasedOnServletContext(Object, ServletContext) da
classe SpringBeanAutowiringSupport para o Spring fazer esse favor para ns.
Vamos ver ento o que esse historicoExecucao faz:

/**
* Classe que contm o histrico de execuo de todas as tarefas.
*
* @author Felipe
*/
@Component
public class HistoricoExecucao {

private List historico;

private SimpleDateFormat simpleDateFormat;

public HistoricoExecucao() {
historico = new ArrayList();
simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy -
HH:mm:ss");
}

public void novoHistorico(String hist) {


historico.add(simpleDateFormat.format(new Date()) + ": " +
hist);
}

public List getHistorico() {


return historico;
}

uma classe que simplesmente mantm um histrico de mensagens em memria. Vamos


utilizar ela para manter um histrico de todas as tarefas que foram executadas pela nossa
aplicao.
Agendamento de tarefas
Uma vez que o servlet est pronto vamos comear a agendar as tarefas.
Vamos comear com a classe responsvel por verificar o status dos servidores.
Tudo o que vamos fazer realizar um ping nos servidores para verificar se eles esto
online. Como voc um desenvolvedor esperto voc pensou: Bom.. pode ser que em um
outro momento seja necessrio utilizar a funcionalidade de dar ping em alguma mquina
ou at mesmo recuperar os IPs dos servidores J sei! Vou colocar em uma classe
utilitria!
Boa! E com isso temos a classe InfraUtils:

/**
* Classe utilitria para tarefas relacionadas a infra estrutura.
*
* @author Felipe
*/
public class InfraUtils {

public static final String IP_SERVIDOR_FIREWALL = "192.168.0.20";


public static final String IP_SERVIDOR_BD = "192.168.0.21";
public static final String IP_SERVIDOR_APLICACAO = "192.168.0.22";

public static final String[] IPS_SERVIDORES = {IP_SERVIDOR_FIREWALL,


IP_SERVIDOR_BD, IP_SERVIDOR_APLICACAO};

public static boolean pingaServidor(String ip) {


// Simula o ping
try {
Thread.sleep(3500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

// Verifica o resultado do ping


if (((int) (Math.random() * 10))

Agora que j temos a estrutura para realizar um ping ou pelo menos simular um vamos
para as tarefas mesmo. Vamos comear criando uma interface para padronizar todas as
nossas tarefas:

/**
* Contrato que define os mtodos necessrios para uma tarefa.
*
* @author Felipe
*/
public interface Tarefa {
void executar(Object... args);
}

A nica coisa que uma Tarefa vai ter que fazer ser executada. Simples assim.
Agora que j sabemos como vai ser uma tarefa podemos criar a TarefaPingServidores:

/**
* Tarefa para pingar os servidores e verificar se esto ativos ou no.
*
* @author Felipe
*/
@Component
public class TarefaPingServidores implements Tarefa {

@Autowired
private HistoricoExecucao historicoExecucao;

@Override
public void executar(Object... args) {
if (args == null || args.length == 0) {
throw new IllegalArgumentException("A tarefa deve
receber o IP do servidor a ser pingado!");
}

String ipServidor = args[0].toString();


String nomeServidor = "Servidor de " +
InfraUtils.traduzirIp(ipServidor);
String historico = "";

if (InfraUtils.pingaServidor(ipServidor)) {
historico = nomeServidor + " pingado com sucesso.";
} else {
historico = nomeServidor + " caiu!";
EmailUtils.enviaEmail(EmailUtils.EMAIL_CHEFE,
historico);
}

historicoExecucao.novoHistorico(historico);
}

Nossa tarefa segue uma lgica um tanto quanto simples no? Garante que foi enviado o IP
do servidor a ser pingado, pega o nome do servidor a partir do seu IP, se no pingou com
sucesso, ou seja, se o servidor caiu envia um e-mail para o chefe e por fim registra o que
aconteceu no histrico.
Como envia o e-mail? Sinto muito mas no vai ser hoje que vamos ver hehehehe

/**
* Classe utilitria para o envio de emails.
*
* @author Felipe
*/
public class EmailUtils {

public static final String EMAIL_CHEFE = "chefe@empresa.com.br";

public static void enviaEmail(String para, String mensagem) {


System.out.println(String.format("Email enviado para %s com a
mensagem \"%s\"",
para,
mensagem));
}

A anotao @Scheduled

Ok, temos a nossa primeira tarefa pronta. Mas como vamos fazer ela ser executada a
cada 5 segundos?
Vamos dar uma olhada na classe TarefasAgendadas que onde vo ficar todas os nossos
agendamentos para a execuo de tarefas:

/**
* Classe que contm todas as tarefas agendadas do sistema.
*
* @author Felipe
*/
@Component
public class TarefasAgendadas {

@Autowired
@Qualifier("tarefaPingServidores")
private Tarefa pingarServidores;

@Scheduled(fixedDelay=5000)
private void pingarServidores() {
String[] servidores = InfraUtils.IPS_SERVIDORES;
for (int i = 0; i &lt; servidores.length; i++) {
pingarServidores.executar(servidores[i]);
}
}
}

A primeira coisa que precisamos prestar ateno a classe est anotada


com@Component, ou seja, ela ser um bean que o Spring vai descobrir automaticamente.
Uma vez que o Spring est gerenciando esse bean e encontra a anotao
@Scheduled ele j prepara toda a infra estrutura necessria para realizar essa tarefa de
acordo com o agendamento informado na anotao.
A anotao @Scheduled possui 3 parmetros para podermos definir o agendamento das
tarefas: fixedDelay, fixedRate e cron.

fixedDelay um valor em milissegundos que ser esperado entre o fim de uma


execuo e o comeo de outra;
fixedRate um valor em milissegundos que ser esperado entre as invocaes,
ou seja, sem considerar o fim do mtodo;

cron uma String contendo uma CronExpression. Veremos detalhes mais a


seguir.

Para o mtodo pingarServidores() ns definimos que a cada 5 segundos desde sua ltima
execuo ele dever ser invocado novamente. Com isso basta executarmos a aplicao,
esperar alguns segundos, clicar no link Recarregar e teremos uma sada parecida com
essa:

A anotao @Async

Depois que voc diz para o teu chefe que terminou a funcionalidade de pingar os
servidores ele pergunta: Mas o ping nos servidores est sendo feito de forma assncrona
certo?. Errado! Do jeito que est as chamadas esto sendo feitas de maneira sncrona
dentro do for, ou seja, para pingar o segundo servidor tem que esperar o ping do primeiro
terminar e assim por diante.
Mas por sorte a galera do Spring j pensou nisso e j disponibilizou uma anotao para
resolver o nosso problema: a anotao @Async.
Para tornarmos os pings assncronos basta fazermos o seguinte:

/**
* Classe responsvel pelas tarefas agendadas relacionadas a infra estrutura.
*
* @author Felipe
*/
@Component
public class TarefaPingServidores implements Tarefa {

@Autowired
private HistoricoExecucao historicoExecucao;

@Async
@Override
public void executar(Object... args) {
if (args == null || args.length == 0) {
throw new IllegalArgumentException("A tarefa deve
receber o IP do servidor a ser pingado!");
}

String ipServidor = args[0].toString();


String nomeServidor = "Servidor de " +
InfraUtils.traduzirIp(ipServidor);
String historico = "";

if (InfraUtils.pingaServidor(ipServidor)) {
historico = nomeServidor + " pingado com sucesso.";
} else {
historico = nomeServidor + " caiu!";
EmailUtils.enviaEmail(EmailUtils.EMAIL_CHEFE,
historico);
}

historicoExecucao.novoHistorico(historico);
}

S isso? Sim, s isso!


Para termos certeza de que isso vai funcionar mesmo vamos fazer o seguinte:

/**
* Classe que contm todas as tarefas agendadas do sistema.
*
* @author Felipe
*/
@Component
public class TarefasAgendadas {

@Autowired
@Qualifier("tarefaPingServidores")
private Tarefa pingarServidores;

@Scheduled(fixedDelay=5000)
private void pingarServidores() {
String[] servidores = InfraUtils.IPS_SERVIDORES;
for (int i = 0; i &lt; servidores.length; i++) {
pingarServidores.executar(servidores[i], i);
}
}
}
/**
* Classe responsvel pelas tarefas agendadas relacionadas a infra estrutura.
*
* @author Felipe
*/
@Component
public class TarefaPingServidores implements Tarefa {

@Autowired
private HistoricoExecucao historicoExecucao;

@Async
@Override
public void executar(Object... args) {
if (args == null || args.length == 0) {
throw new IllegalArgumentException("A tarefa deve
receber o IP do servidor a ser pingado!");
}

System.out.println(String.format("%s comeando
(%d)",Thread.currentThread().getName(), args[1]));

String ipServidor = args[0].toString();


String nomeServidor = "Servidor de " +
InfraUtils.traduzirIp(ipServidor);
String historico = "";
if (InfraUtils.pingaServidor(ipServidor)) {
historico = nomeServidor + " pingado com sucesso.";
} else {
historico = nomeServidor + " caiu!";
EmailUtils.enviaEmail(EmailUtils.EMAIL_CHEFE,
historico);
}

historicoExecucao.novoHistorico(historico);

System.out.println(String.format("%s terminando
(%d)",Thread.currentThread().getName(), args[1]));
}

Vamos enviar para a tarefa em qual loop ela foi executada


(pingarServidores.executar(servidores[i], i)) e depois vamos logar o incio e fim da
execuo de cada tarefa para podermos acompanhar se est acontecendo tudo em
sequncia mesmo ou se esto asncronas.
Ao executar a aplicao e observar o console por algum tempo iremos ver o seguinte:

S pelo nome da thread j podemos ver que funcionou n Em adio ao nome, se


repararmos na sada podemos ver que algumas invocaes posteriores podem comear a
ser executadas antes. Ex: 1, 0, 2 e 0, 2, 1.
Devido a anotao @Async, assim que o mtodo for chamado ele j vai retornar e o
Spring ir execut-lo em uma thread nica, por isso vale lembrar que isso ir funcionar
para mtodos que no possuam retorno (void). Caso seja necessrio retornar um valor do
mtodo assncrono devemos utilizar como retorno um objeto que implemente a
interfacejava.util.concurrent.Future. Para mais informaes consulte a documentao e/ou
o google. hehehe
Com isso terminamos o agendamento da tarefa para pingar os servidores da empresa!
Vamos para a nossa ltima tarefa: criar uma tarefa que envie um e-mail para o chefe todo
dia com o andamento das sprints. Vamo primeiro criar a tarefa que far isso:

/**
* Classe responsvel pelo envio agendado de emails.
*
* @author Felipe
*/
@Component
public class TarefaAndamentoDiarioSprints implements Tarefa {
@Autowired
private HistoricoExecucao historicoExecucao;

@Override
public void executar(Object... args) {
// Levanta os dados necessrios e monta a mensagem
String andamentoTarefas = "Segue o andamento das tarefas...";
EmailUtils.enviaEmail(EmailUtils.EMAIL_CHEFE,
andamentoTarefas);

historicoExecucao.novoHistorico("Andamento das tarefas


enviado por email.");
}
}

Uma vez que temos a tarefa vamos agend-la para que seja enviada no ltimo segundo de
cada dia, ou seja, 23:59:59h. Para isso usaremos o atributo cron da anotao
@Scheduled:

/**
* Classe que contm todas as tarefas agendadas do sistema.
*
* @author Felipe
*/
@Component
public class TarefasAgendadas {

@Autowired
@Qualifier("tarefaPingServidores")
private Tarefa pingarServidores;

@Autowired
@Qualifier("tarefaAndamentoDiarioSprints")
private Tarefa andamentoDiarioSprints;

@Scheduled(fixedDelay=5000)
private void pingarServidores() {
String[] servidores = InfraUtils.IPS_SERVIDORES;
for (int i = 0; i &lt; servidores.length; i++) {
pingarServidores.executar(servidores[i], i);
}
}

@Scheduled(cron = "59 59 23 ? * *")


private void andamentoDiarioSprint() {
andamentoDiarioSprints.executar();
}
}

Expresses cron

O que so expresses cron afinal de contas (que string esquisita)?


cron uma ferramenta UNIX muito poderosa para agendamento. Ela utilizada h muito
tempo, ou seja, sabemos que funciona! Expresses cron so as expresses que essa
ferramenta utiliza para realizar os agendamentos. Tais expresses so formadas por 6 ou
7 campos separados por espaos em branco, representando perodos de tempo. Vamos
dar uma olhada nesses campos:
Campo Obrigatrio? Valores permitidos Caracteres especiais permitidos
Segundos Sim 0-59 */,-

Minutos Sim 0-59 */,-

Horas Sim 0-23 */,-

Dia do ms Sim 1-31 */,-?LW

Ms Sim 1-12 ou JAN-DEC */,-

Dia da semana Sim 0-6 ou SUN-SAT */,-?L#

Ano No 19702099 */,-

Olhando para essa tabela agora j quase conseguimos ler a expresso que usamos na
anotao @Scheduled(cron =59 59 23 ? * *) J sabemos que vai ser no horrio
23:59:59, mas o que significam esses caracteres especiais? Vamos l:

Astersco (*) utilizado para selecionar todos os valores. Ex: * no campo


segundos significa todos os segundos;

Interrogao (?) utilizador quando o valor do campo no importa. Ex: quero que
seja disparada uma tarefa todo dia 10 mas no me importo qual dia da semana vai ser o
dia 10;

Hfen (-) utilizado para informar perodos. Ex: 1-4 no campo ms quer dizer que
a tarefa ser disparada em janeiro, fevereiro, maro e abril;

Vrgula (,) utilizado para valores adicionais. Ex: MON,WED,FRI no campo dia
da semana indica a execuo na segunda, quarta e sexta feiras;

Barra (/) utilizado para especificar incrementos. Utiliza a seguinte sintaxe:


<incio>/<incremento> (se o incio for omitido ele ser interpretado como 0). Ex: /30 no
campo segundos significa a cada 30 segundos e 1/5 no campo dia do ms indica a
execuo nos dias 1, 6, 11, 16, ;

L (last) - possui alguns significados dependendo do campo em que utilizado. Se


for utilizado no campo dia do ms significa o ltimo dia do ms, se for utilizado sozinho no
campo dia da semana significa 7 ou SAT (sbado), se utilizado com algum valor no campo
dia da semana seria o ltimo do ms (ex: 6L seria a ltima sexta feira do ms),
tambm possvel especificar um perodo antes do fim do ms no campo dia do ms (ex:
L-2 seria o antepenltimo dia do ms);

W (weekday) usado para especificar o dia til (segunda sexta) mais prximo
do dia informado. Ex: 15W no campo dia do ms vai executar na segunda feira (dia 14)
caso o dia 15 caia em um sbado ou ento vai executar em uma segunda (16) caso o dia
15 seja um domingo. Se utilizarmos 1W e o primeiro dia do ms seja um sbado, s vai
executar na segunda feira (dia 3). S possvel utilizar esse caractere quando o dia do
ms for um nico dia, sua utilizao com perodos no permitida;

Sustenido (#) utilizado para especificar o n-simo dia do ms. Ex: 6#3 no
campo dia da semana significa a terceira sexta feira do ms (6 = sexta, #3 = terceira);
4#5 significa a quinta quarta feira do ms, porm se no houver uma quinta quarta feira
no ms a tarefa no ser executada.

Obs: Os caracteres L e W podem ser utilizados em conjunto no campo dia do ms. Ex:
LW significa o ltimo dia til do ms.
Bom, expresses cron podem ser fceis como 0 0 15 ? * * ou podem ser complexas
como 0/5 14,18,3-39,52 * ? JAN,MAR,SEP MON-FRI 2002-2010.
Mas ento como saber se a sua expresso est certa ou no?
Para isso existe uma classe bem bacana na biblioteca do Quartz: CronExpression.java.
Nela existe o mtodo getNextValidTimeAfter(Date) que nos retorna a prxima data (a partir
do parmetro) na qual a tarefa ser executada. Com isso ns podemos montar uma classe
utilitria que nos permite testar se nossa expresso est certa ou no:

/**
* Classe responsvel por realizar testes com as Cron Expressions.
*
* @author Felipe
*/
public class TestaExpressao {

private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy


HH:mm:ss");

public static void main(String[] args) {


mostrarProximasDatas("59 59 23 ? * *", 10);
}

public static void mostrarProximasDatas(String cron, int quantDatas) {


try {
CronExpression e = new CronExpression(cron);
Date ultimaData = new Date();
for (int i = 0; i &lt; quantDatas; i++) {
ultimaData =
e.getNextValidTimeAfter(ultimaData);
System.out.println(String.format("%02d: %s",
i+1, sdf.format(ultimaData)));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Obs: para essa classe funcionar ser necessrio colocar a biblioteca do Quartz no
classpath.
O mtodo mostrarProximasDatas(String, int) recebe uma expresso e a quantidade de
datas futuras em que essa expresso ir disparar sero exibidas como parmetros. Ao
executar o exemplo acima vamos ter uma sada parecida com essa:
Vemos que vai disparar todo dia exatamente s 23:59:59, ou seja, conferimos que nossa
expresso vai fazer exatamente o que queremos!

Concluso
Bom pessoal, depois desse pequeno post voc vai conseguir entregar a aplicao para o
seu chefe antes do prazo e ele vai ficar muito satisfeito com o resultado! hehehe
Mas sem brincadeiras, o Spring prov uma forma maneira muito fcil e ao mesmo tempo
muito poderosa para agendarmos tarefas. Sem falar que incrivelmente legvel n (devido
ao uso de anotaes e poucas configuraes em XML).
Caso a sua aplicao seja muito grande mesmo e precise de tarefas agendadas como
realizar transaes bancrias (ou coisas de mesma importncia) eu aconselharia dar uma
olhada no Quartz mesmo. Ele prov algumas funcionalidades a nvel de aplicaes de
grande porte como persistncia dos jobs a serem executados (em caso de alguma falha),
clusterizao e suporte a transaes JTA.

Spring 3.1 + Hibernate 4.0


By Joo Corra da Costa Junior

A idia de criar este post foi do Felipe Saab quando sugeri a ele manter o post Spring
Framework Parte 4 -> Integrao com o Hibernate atualizado para uma verso mais nova
das bibliotecas.
Porm essa atualizao iria modificar uma parte da codificao do post ento decidimos
criar um novo focando somente em Spring 3.1 e Hibernate 4.0.
Aos que esto iniciando neste assunto, sugiro a leitura dos assuntos abordados em posts
anteriores:

Spring Framework Parte 1 -> Dependency Injection

Spring Framework Parte 2 -> Aspect Oriented Programming

Spring Framework Parte 3 -> Java Database Connectivity (JDBC)

Neste tpico vamos abordar a configurao de um projeto utilizando Hibernate 4 com


anotaes (annotations), Spring 3.1 e uma base de dados MySQL.

Usar Annotations ou XML?


Existe muita discusso sobre este assunto. O Hibernate permite as duas formas, ambas
tem suas vantagens e desvantagens.
Na minha opnio o Annotations tem grande vantagem pois elimina arquivos para cada
mapeamento, aumenta a produtividade pela configurao ficar diretamente no POJO, ou
seja, na classe java que representa a tabela que est sendo mapeada.
Uma das maneiras mais diretas de interagir com banco de dados usando o Java via
JDBC, porm exige muita codificao para manter os dados persistentes no sistema.
Atualmente temos ferramentas como o Hibernate que nos auxiliam neste trabalho e que
est evoluindo constantemente para ficar ainda melhor.
Bom, chega de papo, vamos codificar!
Vamos criar no Eclipse um novo Java Project chamado Spring_HibernateAnnotations.

Bibliotecas e Dependncias
Criarei no projeto uma pasta lib e colocarei dentro as bibliotecas necessrias para rodar o
Spring 3.1 e o Hibernate 4.0. As bibliotecas podem ser encontradas em:

Spring: http://www.springsource.org/download (todos os arquivos da pasta dist)

Hibernate: http://sourceforge.net/projects/hibernate/files/hibernate4/ (todos os


arquivos da pasta lib/required e lib/jpa)

O Spring e o Hibernate fazem uso de bibliotecas auxiliares que precisaro ser adicionadas:

Commons Logging: http://commons.apache.org/logging/ (extraia e adicione


somente o commons-logging-1.1.1.jar)

SLF4J: http://www.slf4j.org/download.html (adicione somente slf4j-api-


1.6.x.jar eslf4j-simple-1.6.x.jar)

JTA: http://repo2.maven.org/maven2/javax/transaction/jta/1.1/ (adicione


somente jta-1.1.jar)
AspectJ http://www.eclipse.org/aspectj/downloads.php (Extraia o aspectj-1.x.x
.jarcom o Winrar e adicione em seu projeto os arquivos da pasta lib)

AOPAlliance http://aopalliance.sourceforge.net/ (Adicione o aopalliance.jar)

Para conectar com a base de dados MySQL precisamos tambm do conector:

Connector J: http://dev.mysql.com/downloads/connector/j/ (Adicione o mysql-


connector-java-x.x.x-bin.jar)

Aps adicionar os jars ao projeto devemos ter uma tela parecida com essa:

Mos obra
Vamos definir uma estrutura inicial de pacotes para o nosso projeto:

conf: Guardar o arquivo de configuraes


spring_hibernateannotations: Local onde ficaro as classes que faro execuo

spring_hibernateannotations.interfaces: Guardar as interfaces

spring_hibernateannotations.modelo: Guardar os POJOs

Arquivo de configurao
Vamos criar o arquivo de configurao do Spring com o nome conf.xml no pacote conf:

<?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">
<property name="driverClassName"
value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost/hibernate_teste" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>

<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>

<value>spring_hibernateannotations.modelo.Livro</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<bean id="banco_dados" class="spring_hibernateannotations.BancoDados">


<property name="sessionFactory" ref="sessionFactory" />
</bean>

</beans>

dataSource: Bean base para o acesso base de dados. Injetamos nele as


informaes necessrias para realizar a conexo.

sessionFactory: a SessionFactory a parte do Hibernate responsvel por


carregar todo o mapeamento das nossas classes em memria e garantir que ele esteja
correto. Informamos atravs da lista annotatedClasses que a
classe spring_hibernateannotations.modelo.Livro uma classe anotada, ou seja, ela
possui mapeamento realizado atravs de anotaes. Com isso a sessionFactory vai
validar (em tempo de execuo) se as anotaes que informamos na classe livro esto
condizentes com o banco de dados e garantir que os dados das nossas classes sejam
persistidos na base.

banco_dados: Bean da nossa aplicao que ir encapsular toda a lgica de


acesso aos dados. Injetamos a sessionFactory para nossa classe poder delegar tais
acesso para ela.

Banco de Dados
Vamos neste post seguir a estrutura de banco do post anterior, ou seja, vamos utilizar a
classe Livro e a tabela Livros.
Segue o script para criar a tabela no MySQL (conforme publicao anterior do Felipe
Saab):

CREATE TABLE 'Livros' (


'liv_cod' INT NOT NULL ,
'liv_titulo' VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT
NULL ,
PRIMARY KEY ( 'liv_cod' )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Segue a imagem da minha base de dados recentemente criada:

Na package spring_hibernateannotations.modelo criarei a classe Livro.java com a


seguinte estrutura:

@Entity
@Table(name = "livros")
@GenericGenerator(name = "mygenLivros", strategy = "increment")
public class Livro implements Serializable {

private static final long serialVersionUID = 6216997659936884192L;

@Id
@GeneratedValue(generator = "mygenLivros")
@Column(name = "liv_cod")
private int cod;

@Column(name = "liv_titulo")
private String titulo;

// Getters e Setters

}
Se vocs repararem bem, uma simples classe com getters e setters, porm com
algumas coisas a mais:
implements Serializable: Uma boa prtica fazer com que todas as entidades mapeadas
(@Entity) implementem a interface java.io.Serializable pois em quase todas as aplicaes
web as entidades so serializadas do servidor para o cliente. Essa implementao garante
que nenhum dado se perca durante a serializao.
Campo esttico serialVersionUID: A serializao necessita de um identificador da classe
(mais detalhes em http://blog.caelum.com.br/entendendo-o-serialversionuid/). Uma
possibilidade ger-lo utilizando o prprio eclipse:

Hibernate Annotations
Caso voc no saiba o que so anotaes aconselho a leitura do post Annotations: O que
, pra que serve?.
So as informaes (metadados) que o Hibernate utilizar para associar esta classe
tabela do banco de dados. Acredito que neste ponto alguns desenvolvedores j podem
imaginar a econmia de cdigo que isso pode trazer. Explicarei abaixo cada uma desta
anotaes, porm entendam que existem mais anotaes, o que torna o Hibernate flexvel
para trabalhar com a maioria dos modelos de dados relacionais existentes.

@Entity: Especifica que a classe ser uma entidade mapeada;

@Table: Especifica que a classe representa uma tabela no banco;

o name: Opcionalmente podemos informar o nome da tabela na anotao,


caso ela no for informada o Hibernate vai assumir que o nome da tabela o mesmo
nome da classe.

@Id: Indica que o atributo anotado a chave primria da tabela;

@GenericGenerator: Define um gerador customizado de IDs. No nosso caso o


auto-numerador do MySQL;

o name: Nome que identifica o gerador (para ser utilizado como referncia
em outras anotaes);

o strategy: A estratgia que esse gerador vai utilizar para gerar os


identificadores. No nosso exemplo colocamos increment que diz que o seu valor ser o
incremento a partir da ltima gerao.
@GeneratedValue: Ao usar esta anotao, indicamos que o valor do atributo
anotado ser gerado por um gerador;

o generator: Nome do gerador customizado (o mesmo nome que est no


atributo name da anotao @GenericGenerator).

@Column: Indica que o atributo representa uma coluna da tabela.

o name: Tem o mesmo funcionamento do atributo name da


anotao @Table, ou seja, define o nome da coluna da tabela que o atributo est
mapeando. Caso no for informado o Hibernate assume que o nome da coluna igual o
nome do atributo.

Implementando a aplicao
Vamos criar agora a classe que implementa os mtodos CRUD do Livro. Na
packagespring_hibernateannotations.interfaces ser criada a interface IBanco.java. Em
nosso exemplo esta interface no parece muito til, mas em um projeto maior podemos
querer obrigar que toda classe que implementa a interface com banco de dados
implemente as mesmas assinaturas de mtodos.

public interface IBanco {

public Livro InserirLivro(Livro livro);

public void AtualizarLivro(Livro livro);

public void ApagarLivro(Livro livro);

public List<Livro> SelecionarLivrosPorTitulo(String titulo);

public Livro SelecionarLivroPorCodigo(int cod);

Vamos agora implementao dessa interface. Na


packagespring_hibernateannotations ser criada a classe BancoDados.java, que como
mostrado na seo do arquivo de configurao, recebe a SessionFactory do Hibernate
pela Injeo de Dependncia do Spring.
Colocarei nesta classe o controle de sesses (abrir e fechar Sessions do Hiberante) e
transaes, porm o mais vivel deixar Orientado a Aspecto, a partir de uma classe
Transacao.java (Advice) e com os Pointcuts em InserirLivro, AtualizarLivro e ApagarLivro.
Sempre executando um beginTransaction no @Before, um commit no @AfterReturning e
um rollback no @AfterThrowing. Ou at mesmo aproveitando o controle automtico de
transaes e sesses que o Spring proporciona, porm isso iria fugir do escopo deste post
ento fica para um prximo post ou para uma googleada da sua parte.. heheheh

public class BancoDados implements IBanco {

private SessionFactory sessionFactory;

private Session sessao;

private Transaction transacao;


public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
this.sessao = sessionFactory.openSession();
}

public Livro InserirLivro(Livro livro) {


try {
if(!sessao.isOpen()) {
sessao = sessionFactory.openSession();
}
transacao = sessao.beginTransaction();
int cod = (Integer) sessao.save(livro);
transacao.commit();
livro.setCod(cod);
}
catch(HibernateException e) {
System.out.println("Erro: " + e.getMessage());
transacao.rollback();
}
finally {
try {
if(sessao.isOpen()) {
sessao.close();
}
}
catch(Throwable e)
{
System.out.println("Erro ao finalizar
insero: " + e.getMessage());
}
}

return livro;

public void AtualizarLivro(Livro livro) {

try {
if(!sessao.isOpen()) {
sessao = sessionFactory.openSession();
}
transacao = sessao.beginTransaction();
sessao.update(livro);
transacao.commit();
}
catch(HibernateException e)
{
System.out.println("Erro: " + e.getMessage());
transacao.rollback();
}
finally {
try {
if(sessao.isOpen()) {
sessao.close();
}
}
catch(Throwable e){
System.out.println("Erro ao finalizar
atualizao: " + e.getMessage());
}
}

}
public void ApagarLivro(Livro livro) {
try {
if(!sessao.isOpen()) {
sessao = sessionFactory.openSession();
}
transacao = sessao.beginTransaction();
sessao.delete(livro);
transacao.commit();
}
catch(HibernateException e) {
System.out.println("Erro: " + e.getMessage());
transacao.rollback();
}
finally {
try {
if(sessao.isOpen()) {
sessao.close();
}
}
catch(Throwable e) {
System.out.println("Erro ao finalizar : " +
e.getMessage());
}
}
}

public List<Livro> SelecionarLivrosPorTitulo(String titulo) {


if(!sessao.isOpen()) {
sessao = sessionFactory.openSession();
}
Criteria criteria = sessao.createCriteria(Livro.class);
criteria.add(Restrictions.like("titulo", titulo));
return criteria.list();
}

public Livro SelecionarLivroPorCodigo(int cod) {


if(!sessao.isOpen()) {
sessao = sessionFactory.openSession();
}
Criteria criteria = sessao.createCriteria(Livro.class);
criteria.add(Restrictions.eq("cod", cod));
Livro livro = (Livro) criteria.uniqueResult();
return livro;
}

No post anterior era utilizado o HibernateTemplate, um facilitador do Spring para utilizar o


Hibernate, porm desde a verso 3.x do Hibernate aconselhvel utilizar diretamente
aSessionFactory ao invs do HibernateTemplate para deixar o Hibernate com mais
controle das aes realizadas atravs das suas Sessions.
Bom, feitos todos os acessos, vamos criar a classe principal da aplicao. Ela
exatamente igual a do post anterior.
Vamos criar ento a classe Main.java na package spring_hibernateannotations:

public class Main {

public static void main(String[] args) {

ApplicationContext ctx = new


ClassPathXmlApplicationContext("conf/conf.xml");
System.out.println("Spring inicializado");
BancoDados banco = (BancoDados) ctx.getBean("banco_dados");

Livro livro1 = new Livro();


livro1.setTitulo("Spring + Hibernate");
Livro livro2 = new Livro();
livro2.setTitulo("Hibernate Avanado");
System.out.println("Objetos Livro inicializados");

livro1 = banco.InserirLivro(livro1);
livro2 = banco.InserirLivro(livro2);
System.out.println("Livros gravados no banco");

//zerando os objetos Livro


livro1 = null;
livro2 = null;

System.out.println("Selecionando livros por cdigo");


livro1 = banco.SelecionarLivroPorCodigo(1);
exibe(livro1);
livro2 = banco.SelecionarLivroPorCodigo(2);
exibe(livro2);

System.out.println("Selecionando livros que contenham


'Hibernate' no ttulo");
List<Livro> lista =
banco.SelecionarLivrosPorTitulo("Hibernate");
for (Livro l : lista){
exibe(l);
}

System.out.println("Atualizando livro");
livro1.setTitulo(livro1.getTitulo()+" Segunda Edio");
banco.AtualizarLivro(livro1);

System.out.println("Apagando livro");
banco.ApagarLivro(livro2);
}

public static void exibe(Livro livro) {


if (livro == null)
System.out.println("Livro no encontrado");
else
System.out.println("Livro -> cod: " + livro.getCod()
+ " | Ttulo: " + livro.getTitulo());
}

O projeto est pronto para rodar:


isso a pessoal, para projetos que so grandes ou que tem tendncia de crescer e
essencial o uso de frameworks que tornam a codificao produtiva, a modificao nas
camadas transparente, e que permitem ajustes a diferentes ambientes.
O Hibernate muito mais do que foi explicado aqui, implementando o C3PO (connection
pool framework) podemos deixa-lo preparado para quantidades grandes de acessos
simultneos, controle de cache para manter a performance de grandes massas de dados.
Das annotations podemos fazer configuraes de relacionamentos 1:1, 1:N, N:1, N:N,
mapear chaves estrangeiras.

S-ar putea să vă placă și