Série Spring: JEE:CRUD Hibernate com Spring 3 + JSF 2.0

 

Olá Pessoal,

Continuando a nossa série de post sobre o Spring vamos, ver hoje como fazer um simples CRUD com Spring + Hibernate + JSF.O objetivo maior, é para quem está chegando possa ver como juntar as tecnologias de maneira simples. E o melhor de tudo veremos como Spring  é uma mão na roda de verdade.

Lets go…

Starting…

A nossa aplicação será super simples, vamos fazer o cadastramento de carros, e exercitar o CRUD. Para exibição e cadastro dos veículos, vamos fazer uma página JSF de maneira mais simples possível e que seja funcional.  A seguir os requisitos:

Requisitos:

  • – MysqlSQL 5.x
  • – Hibernate 3.x
  • – Spring 3.x
  • – Tomcat 7.x
  • – JSF 2.x
  • – Jboss tools

Vou considerar que você vem acompanhando a série de posts  Spring no blog e alguns pontos que já foi tratado aqui, não estarei explicando novamente, dúvidas? Farei um link para o post referente. E sobre JSF 2.x também irei considerar que vc já brincou com o framework, mesmo que seja na versão anterior. Estou ressaltando isso, para que não entre no detalhes de cada ponto, e que o post fique mais direto e mão na massa.

 Configuração

Primeiro ponto é , criar um projeto JSF Project (é preciso ter o jboss tools instalado).

projetocrudspringcar

Escolha a opção JSF 2 na tela do assistente.  Em seguida crie os packages conforme a seguir, por enquanto eles estarão vazios, mas iremos daqui a pouco colocar carne no esqueleto : ).

Adicione os .jars na pasta lib do projeto:

webinflib

Criando o source unit/test

Observe que eu criei um source para os unit tests:

unitestscarcrud

Agora vamos criar o arquivo de configuração do Spring. Na verdade teremos dois, um para os unit tests e outro para aplicação. Apenas dupliquei, mas poderíamos otimizar o de unit tests importando apenas o que precisamos a partir do arquivo principal, mas não quis fazer isso por agora, vamos focar no CRUD.

Crie um arquivo springconfiguration.xml  dentro de WEB-INF, o nome poderia ser qualquer um, normalmente utiliza-se applicaiton-context.xml, mas quis fazer diferente para que você veja que o nome não importa.

Não irei adicionar o cabeçalho apenas o código, que não tem nada de diferente do que já vimos nos posts quando vimos hibernate com Spring.

<context:component-scan base-package=“*”/>

<tx:annotation-driven/> 

<tx:advice id=“txAdvice”>

<tx:attributes>

<tx:method name=“add*” propagation=“REQUIRED”/>

<tx:method name=“delete*” propagation=“REQUIRED”/>

<tx:method name=“read*” propagation=“REQUIRED”/>

<tx:method name=“*” propagation=“SUPPORTS” read-only=“true”/>

</tx:attributes>

</tx:advice> 

<aop:config>

<aop:advisor pointcut = “execution(* *..CarDAO.*(..)))” advice-ref=“txAdvice”/>

</aop:config> 

<bean class=“org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor”/> 

<bean id=“dataSource” class=“org.springframework.jdbc.datasource.DriverManagerDataSource”>

<property name=“driverClassName” value=“com.mysql.jdbc.Driver”/>

<property name=“url” value=“jdbc:mysql://localhost/test”/>

<property name=“username” value=“root”/>

<property name=“password” value=“camilo2593”/>

</bean> 

<bean id=“sessionFactory” class=“org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>

<property name=“dataSource” ref=“dataSource”/>

<property name=“packagesToScan” value=“br.com.camilolopes.car.domain.bean”/>

<property name=“hibernateProperties”>

<props>

<prop key=“hibernate.dialect”>org.hibernate.dialect.MySQL5InnoDBDialect</prop>

<prop key=“hibernate.hbm2ddl.auto”>update</prop>

</props>

</property>

</bean>

<bean id=“transactionManager” class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>

<property name=“sessionFactory” ref=“sessionFactory”/>

</bean>

 

Agora precisamos fazer umas configurações no arquivo web.xml

<!– dizendo onde está meu arquivo de configuração –>

 <context-param>

  <param-name>contextConfigLocation</param-name>

  <param-value>/WEB-INF/springconfiguration.xml,</param-value>

 </context-param>

 <!– configurando o context loader do Spring, esse cara permite carregar N arquivos de configuração –>

 <listener>

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

 </listener>

 <!– esse cara permite dizer ao JSF que os beans serão gerenciados pelo Spring é requerido ter essa

 configuração –>

 <listener>

  <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>

 </listener>

 Testando.

Se você subir aplicação agora, não há nade especial, apenas vai subir o exemplo que temos no JSF Project que é criado pelo Jboss tols. Mas, é bom testar para garantir que as mudanças que fizemos no web.xml , não afetou nada da aplicação.

Arquivo de configuração do spring para unit tests

Agora vamos criar um arquivo de configuração para executar os unit tests. Mas, pq? Simplesmente pq a partir de uma classe de teste você não consegue ler um arquivo que está em web-inf, então você precisa ter o arquivo em source.

Noticia boa: o código é o mesmo que  do arquivo anterior, então duplique o XML apenas, o meu chamei de springconfiguration-test.xml e coloquei no JavaSource:

sourcespringconfiuration-test

Agora vamos começar a brincadeira, ou seja, desenvolver.

Development

Começaremos pelos testes claro. Para isso criaremos uma classe que testará o serviço que implicitamente testa as classes DAO.

Antes criaremos os testes precisamos entender que é importante entender que:

– após testes terem sido executados este deve dar rollback, para que os dados não fiquem no banco;

– os testes não podem ser dependentes de outro test, ou seja, um @Test não pode depender da execução de outro @Test

Por enquanto, ao criar os unit test é esperado que nem compile, já que não temos nenhuma classe pronto, mas é isso que queremos, que os testes nos ensinem a  desenvolver as regras de negocio que precisamos.

O primeiro teste vai nos permitir  testar o salvarOrUpdate  da nossa aplicação, poderia ter separado em dois testes um para save e outro para update, mas não quis entrar muito detalhes sobre testes aqui, senão o post ia fica 2x maior e sinceramente não curto muito posts grandes.

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations={“classpath:springconfiguration-test.xml”})

@TransactionConfiguration(transactionManager=”transactionManager”,defaultRollback=true)

@Transactional

public class CarServiceImplTest {

      @Autowired

      private CarServices carServices;

      private Car car;

      @Before

      public void setUp() throws Exception {

      car = new Car();

      car.setDescription(“ferrari”);

      car.setPriceSale(BigDecimal.ZERO);

      car.setYear(“2010”);

      }

      @Test

      public void testSaveOrUpdate() {

            try{

                  carServices.saveOrUpdate(car);

            }catch (Exception e) {

                  fail(“not expected result”);

            }

      }

 

Observe que configuramos o rollback igual a true para tudo, então sempre será feito rollback e nada é inserido no banco. Mas,se você quer inserir no banco para um método especifico, basta anotarmos  no método assim: @Rollback(false) //isso faz inserir no banco 

Note: nesse exemplo não estou usando um banco em memória, então  é preciso que o Mysql esteja rodando para que os testes possam ser executados, o ideal é era fazer os testes rodarem em um banco em memória assim, não teríamos essa dependência, pois o banco seria iniciado sempre que os testes fossem executados.

Agora vamos criar as classes que o Eclipse está reclamando, vamos começar pela entidade Car:

@Entity(name=”SALE_CARS”)

public class Car implements Serializable{

      private static final long serialVersionUID = 2792374994901518817L;

      @Id

      @GeneratedValue

      private Long id;

      private String description;

      private BigDecimal priceSale;

      private String year;

//getters/setters omitidos

 

Services

Vamos criar os serviços, mas antes precisamos ter uma interface para os nossos serviços CRUD então:

public interface CarServices {

      void saveOrUpdate(Car car);

      void delete(Car car);

      List<Car> listAll();

}

 Agora vamos criar a classe em si:

@Service

public class CarServiceImpl implements CarServices {

      @Autowired

      private CarDAO carDAO;     

      public void saveOrUpdate(Car car) {

            carDAO.addCar(car);

      }

//setters CarDAO omitido. Não é preciso criar get.

DAO Interface

Também criaremos uma interface para o DAO e em seguida a implementação do método save

public interface CarDAO {

      void addCar(Car car);

      List<Car> readAll();

      void deleteCar(Long id);     

}

@Repository

public class CarDAOImpl implements CarDAO {

      @Autowired

      private SessionFactory sessionFactory;

           private Session getCurrentSession(){

            return sessionFactory.getCurrentSession();

      }

      public void addCar(Car car) {

            getCurrentSession().saveOrUpdate(car);

      }

//setters sessionFactory ommitido, não é preciso cria get.

Claro que os demais métodos da interface estarão sem código por enquanto, pois o objetivo agora é testar o create do CRUD.

Testando via Unit Tests

Agora vamos rodar o nosso teste e ver o resultado, se você não adicionou o JUNIT4 ao seu projeto, o Eclipse vai fazer a sugestão.

Note: Ao rodar o unit tests e você ter a exceção:

org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available

faça o download http://cglib.sourceforge.net/ e adicione a lib ao seu projeto na pasta web-inf/lib

O resultado

saveorupdategreen

Agora precisamos desenvolver o RUD.  A seguir os testes que foram criados e depois, o código com a resolução:

 @Test

public void testDelete() {

            try{carServices.saveOrUpdate(car);

                  carServices.delete(car);

            }catch (Exception e) {

String notExpectedResult = “Not expected result “+ e.getMessage();

                  fail(notExpectedResult);

            }

      }

      @Test

      public void testListAll() {

            carServices.saveOrUpdate(car);

            assertFalse(carServices.listAll().isEmpty());

      }

 Classe DAO

public List<Car> readAll() {

            return getCurrentSession().createCriteria(Car.class).list();

      } 

      public void deleteCar(Long id) {

            Criteria criteria = getCurrentSession().createCriteria(Car.class);

            criteria.add(Restrictions.eq(“id”, id));

            Car car = (Car) criteria.uniqueResult();

            getCurrentSession().delete(car);

      }

 Classe de Serviço:

      public void delete(Car car) {

            carDAO.deleteCar(car.getId());

      } 

      public List<Car> listAll() {     

            return carDAO.readAll();

      } 

      public void setCarDAO(CarDAO carDAO) {

            this.carDAO = carDAO;

      }

Rodando todos os testes:

reusultadoAlltestescrud

Há um detalhe que fiz de propósito, observe que não tem um teste para validar o update, deixarei esse como motivação para você brincar mais com unit test  : ).

 

resultdbcrudspringunittests

Observe que nosso banco está vazio, ou seja, nada foi adicionado.

JSF

Agora que já sabemos que o nosso CRUD está funcionando, vamos trazer isso para o nosso front-end com JSF.:

Crie uma classe controller

@Controller

public class CarController {

      @Autowired

      private CarServices carServices;

      private Car car;     

      private List<Car> listCars;     

      public CarController() {

            car = new Car();

      }     

      public void save(){

            carServices.saveOrUpdate(car);

            car = new Car();

      } 

      public void delete(){

            carServices.delete(car);

            car = new Car();

      }     

      public List<Car> getListCars() {

            listCars = carServices.listAll();

            return listCars;

      }

                //setters/getters omitidos

Observe que nosso controller conecta com o nosso service. Só isso que precisamos. Se você já brinca com JSF nada de especial por aqui.

Criando  .xhtml

Na verdade vamos alterar o index.xhtml que foi criado por default pelo jboss tools:

<html><head><meta http-equiv=“Refresh” content=“0; URL=pages/sales-car.jsf”/></head></html>

 

Apenas fizemos um redirecionamento para uma página que vamos criar.

sales-car.xhtml

Crie um xhtml, com suporte facelets e adicione o código a seguir:

<body>

<h:form>

<h:commandLink action=“form-car” value=“::Cadastro”/>

</h:form>

</body>

 

Essa página vai levar para a tela de cadastro:

form-car.xhtml

Vamos por parte:

Primeiro temos o código do form:

<h:form>

<h:panelGrid columns=“2”>

<h:outputLabel value=“Car Description: “/>

<h:inputText value=“#{carController.car.description}”/>

<h:outputLabel value=“Sale Price: “/>

<h:inputText value=“#{carController.car.priceSale}” converter=“javax.faces.BigDecimal”/>

<h:outputLabel value=“year:”/>

<h:inputText value=“#{carController.car.year}”/>

<h:commandButton value=“Save” actionListener=“#{carController.save}”/>

</h:panelGrid>

Agora vamos ter o código de uma tabela que exibi o usuário adicionado e permite editar/deletar :

<h:dataTable id=“cartable” value=“#{carController.listCars}” var=“car” cellpadding=“10”>

<h:column>

<f:facet name=“header”>

<h:outputText value=“Id”/>

</f:facet>

#{car.id}

</h:column>

<h:column>

<f:facet name=“header”>

<h:outputText value=“Description”/>

</f:facet>

#{car.description}

</h:column>

<h:column>

<f:facet name=“header”>

<h:outputText value=“Sale Price”/>

</f:facet>

<h:outputText value=“#{car.priceSale}”>

<f:convertNumber type=“currency” maxFractionDigits=“3”/>

</h:outputText>

</h:column> 

<h:column>

<f:facet name=“header”>

<h:outputText value=“Year”/>

</f:facet>

#{car.year}

</h:column> 

<h:column>

<f:facet name=“header”>

<h:outputText value=“Action”/>

</f:facet>

<h:commandLink value=“Delete” action=“#{carController.delete}”>

<f:setPropertyActionListener target=“#{carController.car}” value=“#{car}”/>

</h:commandLink>

<h:commandLink value=” | Edit “>

<f:setPropertyActionListener target=“#{carController.car}”  value=“#{car}”/>

</h:commandLink>

</h:column> 

</h:dataTable>

</h:form>

 

Pronto. Esse é o nosso front-end para testarmos o CRUD, vamos subir aplicação, clique com o botão direito  no projeto e escolha  Run as >> Run on Server

Note: Caso não tenha um servidor selecionado com o projeto o Eclipse vai solicitar que escolha um, no meu caso escolhi o tomcat e informei o local de instalação. Se der tudo certo você terá a tela a seguir:

screenaddjsfcars

Vamos para tela de cadastro clicando no botão “Cadastro”

 

cadcarscreenspring

addingcar

 

carsresultscreen

Verificando no bd:

 

checkingbdcars

Editando:

 

carrdseditjsf

Resultado Edição:

editresultjsfspring

E no banco:

 

editbdcars

 

Ufa! Post longo heim, e olha que reduzir. Mas, vou ficando por aqui. E espero que tenham gostado.

Abraços, see ya!!!

Série Spring: Spring Aspect Object Programming – AOP

olá Pessoal,

O post de hoje veremos com brincar com AOP. Opsss… O que é isso? Veremos um pouco mais a seguir a utilidade de usar AOP e faremos um exemplo simples para vê-lo em ação.

lets go…

AOP – Aspect Object Programming

Em poucas palavras a orientação a aspectos surgiu para eliminar os chamados de cross cutting concerns, ou seja, aquele código que é necessário, mas que não faz parte das principais obrigações do objeto, por exemplo: logging, transação etc. E para isso precisamos entender trêsp ontos apenas:

 

1. Advice: separa o código nada ver em um lugar especifico

2. join point: define dentro do advice o momento que o código separado executa

3.point cuts: é onde será feito.

Então o advice é o que será feito. O joint cuts é quando será feito. E o point cuts é o onde será feito.

 

Antes de começarmos colocar mão na masa precisamos fazer download do .jar do AspectJ http://www.eclipse.org/aspectj/downloads.php após baixar, descompacte o .jar com o winrar por exemplo vá na pasta lib copie os .jars existentes e adicione ao seu projeto.

 

Precisamos também do AOP Alliance http://ebr.springsource.com/repository/app/bundle/version/detail?name=com.springsource.org.aopalliance&version=1.0.0  faça o download e adicione ao seu projeto.

 

Adicione também o commons-logging-1.x http://commons.apache.org/logging/

 


AOPBankProject

Na diferente do que vimos no primeiro post. O objetivo de nossa aplicação é apenas logar informações quando um saque ou desposito for realizado. No exemplo logamos isso no console, em uma aplicação logariamos isso em arquivo de log por exemplo.

 

 

Desenvolvimento

 

1. crie o bean a seguir:

 

package br.com.camilolopes.bean;

import java.math.BigDecimal; 

public class Client  { 

                public void sacar(BigDecimal value) {

                               System.out.println(“Saque realizado com sucesso ” + value);

                }

                public void depositar(BigDecimal value) {

                               System.out.println(“Deposito realizado ” + value);

                }}

 

2. Agora vamos passar a resposabilidade para o Spring cuidar do nosso 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”

                xmlns:aop=”http://www.springframework.org/schema/aop”

                xsi:schemaLocation=”http://www.springframework.org/schema/beans

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

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.2.xsd”>

<bean id=”client”  />

<bean class=”br.com.camilolopes.manager.ManagerTransationAccount”/>

<aop:aspectj-autoproxy />

</beans>

 

Há uma pequena mudança no nosso arquivo xml, observe que adicionamos ao cabeçalho xmlns e http referente aop. E em seguida criamos  um bean para cada classe. A ManagerTransationAccount ainda não criamos, mas não há problemas em colocarmos ela no xml. Vamos criar um pouco mais adiante. A tag de proxy que adicionamos acima estamos falando para o Spring fazer o trabalho duro de criar proxy para nós.

Agora vamos criar a nossa classe que vai controlar as mensagens, ou seja, tudo que acontece na conta será logado:

 

@Aspect

public class ManagerTransationAccount {

                @Pointcut(“execution(* *.sacar(..)”)

                public void transacao(){}               

                @Before(“transacao()”)

                public void saque(){

//                           poderia logar a info no arquivo de log

                               System.out.println(“Transação de saque inicializada”);

                }

                @AfterReturning(“transacao()”)

                public void retirada(){

                               System.out.println(“Transação de saque concluida com sucesso”);

                }

               

                @Pointcut(“execution(* *.depositar(..))”)

                public void deposito(){}

               

                @Before(“deposito()”)

                public void depositar(){

                               System.out.println(“Transação de deposito iniciada”);

                }

               

                @AfterReturning(“deposito()”)

                public void depositado(){

                               System.out.println(“deposito realizado com sucesso”);

                }

}

 

Explicando:

Bem, anotação na classe é bem intuitiva certo? é preciso dizer que essa classe é orientada a aspect. Dai por isso anotação no inicio dela. Em seguida criamos um método da classe onde tudo começa o segredo está na anotação. Observe que é um pointcut, ou seja, onde será feito o trabalho e ali estamos dizendo que será feito quando o método sacar for chamado de qualquer classe passando qualquer parametro.

 

Atenção: Nenhum método criado nessa classe tem relação com os métodos que criamos na interface Machine. Poderiamos aqui chamar nosso método de qualquer coisa. O segundo que criamos e chamamos de saque que leva anotação @Before diz o seguinte: antes de chamar transacao(), ou seja, o métod que tem o pointcut, execute este aqui, ou seja, vai imprimir no console uma mensagem. Mas, poderiamos gravar uma informação no arquivo de log.

As demais anotações falam por si só.

 

Agora vamos testar, crie uma classe com método main:

public class MainBankMachine {

                public static void main(String[] args) {

                               ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“conf/springconfiguration.xml”);

                               Client bean = (Client) applicationContext.getBean(“client”);

                               bean.sacar(BigDecimal.TEN);

                              

                }

}

 

O resultado

 

 aopresult

Agora fazendo deposito e saque:

 

aopresult2

      public static void main(String[] args) {

            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“conf/springconfiguration.xml”);

            Client bean = (Client) applicationContext.getBean(“client”);

            bean.sacar(BigDecimal.TEN);

            bean.depositar(BigDecimal.ONE);

      }

bom, é isso. Bem mais simples e fácil de dar manutenção não?

Vou ficando por aqui espero que tenham gostado do post.

abracos, see ya!!!

Série Spring: CRUD Spring 3 + Hibernate + Unit Tests

Olá Pessoal,

No post de hoje veremos como fazer um simples CRUD usando o Spring, integrando com Hibernate e testando via unit tests com JUNIT4. No último posts vimos apenas uma integração com o Hibernate e também um CRUD usando HibernateTemplate, esse aqui  veremos que na versão 3 do Spring não precisamos mais do HiberanteTemplate e vamos testar nosso código com unit test.

Lets go…

Starting…

Primeiro passo é que  estarei assumindo que você já tem .jars necessário  para o ambiente. Já que esse não é o primeiro post da série, caso contrário terá que baixar os .jars para: driver Mysql 5, Hibernate 3.6, AOP, AspectJ, Spring 3.x.

Antes de começarmos a desenvolver, vamos primeiro estruturar nosso projeto e packages conforme a imagem a seguir:

springrentcarproject

Nosso CRUD será o cadastro  de veículos  que serão alugados. Claro que há muito mais regras de negócios do que a que veremos no exemplo a seguir, porém o nosso objetivo é explorar o framework Spring e não tratar todas as regras de negócio em um post.

  1. Crie a estrutura conforme a imagem acima
  2. Crie o arquivo de configuração de Spring, o qual chamei de springconfiguration.xml, e coloque dentro do package config.
  3.    Agora vamos colocar a carne no nosso XML

Cabeçalho fica assim:

<beans xmlns=“http://www.springframework.org/schema/beans”

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

xmlns:context=“http://www.springframework.org/schema/context”

xmlns:tx=“http://www.springframework.org/schema/tx”

xmlns:aop=“http://www.springframework.org/schema/aop”

xsi:schemaLocation=“http://www.springframework.org/schema/beans

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

http://www.springframework.org/schema/context

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

http://www.springframework.org/schema/tx

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

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.2.xsd”>

 

Estarei comentando mais na frente ou in line apenas o que  ainda não foi abordado nos posts anteriores.

O cara que busca os beans: 

<context:component-scan base-package=“*”/>

 Colocando translation

<!– esse cara faz as traduções das exception checked para as unchecked do Spring –>

<bean class=“org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor”/>

Data source

<!– pelo nome diz, data source para conexão com o DB –>

<bean id=“dataSource” class=“org.springframework.jdbc.datasource.DriverManagerDataSource”>

<property name=“driverClassName” value=“com.mysql.jdbc.Driver”/>

<property name=“url” value=“jdbc:mysql://localhost/test”/>

<property name=“username” value=“root”/>

<property name=“password” value=“camilo2593”/>

</bean>

 

Configurando a SessionFactory

<!– Aqui estamos definido como será a parte de persistêcia, e dizemos que faremos via annotation –>

<bean id=“sessionFactory” class=“org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>

<!– informando a quem estaremos conectado –>

<property name=“dataSource” ref=“dataSource”/>

<!– dizendo onde estão as classes dominio, ele saberá devido anotação @Entity  –>

<property name=“packagesToScan” value=“br.com.camilolopes.rentcar.domain.bean”/>

<!– configurando coisas especificas do Hibernate –>

<property name=“hibernateProperties”>

<props>

<prop key=“hibernate.dialect”>org.hibernate.dialect.MySQL5InnoDBDialect</prop>

<prop key=“hibernate.hbm2ddl.auto”>update</prop>

</props>

</property>

</bean>

 

Definindo Transaction

 <!– definindo quem vai gerenciar as transaction, ou seja, será o Hibernate –>

<bean id=“transactionManager” class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>

<property name=“sessionFactory” ref=“sessionFactory”/>

</bean>

</beans>

Há duas formas de declararmos as transaction no Spring por XML ou Annotation.  Veremos as duas formas, no nosso caso de usarmos o XML faremos com AOP e você entenderá o  motivo:

Via XML

<!– todo medoto que começa com add é required uma transaction –>

<tx:advice id=“txAdvice”>

<tx:attributes>

<tx:method name=“add*” propagation=“REQUIRED”/>

<tx:method name=“update*” propagation=“REQUIRED”/>

<tx:method name=“*” propagation=“SUPPORTS” read-only=“true”/>

</tx:attributes>

</tx:advice>

<!– toda classe que extends a interface terá uma referência para o advisor –>

<aop:config>

<aop:advisor pointcut = “execution(* *..RentCar.*(..)))” advice-ref=“txAdvice”/>

</aop:config>

 

Em alguns contexto dessa forma é bem mais prático que usar Annotations.

 

Via annotation

Remove todo o código XML acima e apenas adiciona a seguinte linha:

<tx:annotation-driven/>

 

Claro que teremos que anotar nas classes/métodos como @Transaction e informar como esse deve se comportar , seguindo o exemplo do XML acima seria algo  assim:

@Transactional(readOnly=true,propagation=Propagation.SUPPORTS)

public class myClass{  }

 

Normalmente você colocaria isso na camada de serviço.Mas, se você está brincando  e não tem uma camada de serviço, pode colocar direto no DAO.

E o método que faria uma das operações de banco ficaria assim:

@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED)

      public void save(Car car) {

            getCurrentSession().save(car);}

 

No nosso exemplo vamos não vamos usar Annotations e exploraremos o benefício de usar a versão do XML conforme acima, se vc deixar a tag para annotation no arquivo de configuração o Spring não vai se importar com isso.

Desenvolvimento

Após toda essa configuração, vamos agora desenvolver nossas classes .java. Começando pela classe de domínio:

@Entity

@Table(name=”CARS”)

public class Car implements Serializable{

private static final long serialVersionUID = -2896368465389020843L;

      @Id

      @GeneratedValue

      private Long id;

      private String manufacter;

      private String description;

      private BigDecimal marketValue;

                //getters/setters omitidos

Basicamente isso .

Interface DAO

public interface RentCarDAO {

      void save(Car car);

      List<Car> findAll();

      List<Car> findAllByDescription(String description);

      void update(Car car);

      void delete();

}

Implementação da Interface:

@Repository

public class RentCarDAOImpl implements RentCarDAO {

      @Autowired

      private SessionFactory sessionFactory;

      public Session getCurrentSession(){

            return sessionFactory.getCurrentSession();

      }

      @Override

      public void save(Car car) {

            getCurrentSession().save(car);

      }

      public void setSessionFactory(SessionFactory sessionFactory) {

            this.sessionFactory = sessionFactory;

      }

      @Override

      public List<Car> findAll() {

            return getCurrentSession().createCriteria(Car.class).list();

      }

      @Override

public List<Car> findAllByDescription(String description) {

Criteria createCriteria = getCurrentSession().createCriteria(Car.class);

createCriteria.add(Restrictions.ilike(“description”, description));

            return (List<Car>) createCriteria.list();

      }

      @Override

      public void update(Car car) {

            getCurrentSession().update(car);

      }

      @Override

      public void delete() {

Query query = getCurrentSession().createQuery(“delete from Car where id >0”);

            query.executeUpdate();

      }

Interface de Serviço

@Service

public interface RentCar {

      void addNewCar(Car car);

      List<Car> findAll();

      List<Car> findCarByDescription(String description);

      void updateCar(Car car);

      void delete();

}

Classe que implementa o Serviço

@Service

public class RentCarServiceImpl implements RentCar {

      @Autowired

      private RentCarDAO rentCarDAO;

      @Override

      public void addNewCar(Car car) {

            rentCarDAO.save(car);

      }

      public void setRentCarDAO(RentCarDAO rentCarDAO) {

            this.rentCarDAO = rentCarDAO;

      }

      @Override

      public List<Car> findAll() {           

            return rentCarDAO.findAll();

      }

      @Override

      public List<Car>findCarByDescription(String description) {

           return (List<Car>) rentCarDAO.findAllByDescription(description);

      }

      @Override

      public void updateCar(Car car) {

            rentCarDAO.update(car);

      }

      @Override

      public void delete() {

      rentCarDAO.delete();     

      }

}

 

Unit Test

Se não reparou quando criou o projeto, temos um source  apenas  para os unit tests, conforme a imagem a seguir:

springrentcarunittestssource

Agora crie a classe de teste. A seguir mostrarei apenas dois simples testes, você deve criar os demais para validar os cenários, não coloquei todos para não ficar mais longo ainda o post.

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations={“classpath:config/springconfiguration.xml”})

public class RentCarServicesTest {

      @Autowired

      private RentCar rentCarServicesImpl;

      private Car car;

      @Before

      public void setUp() throws Exception {

            car = new Car();

      }

      @Test

      public void testAddingNewCarWithSuccess(){

            try{

                  car.setDescription(“Civic”);

                  car.setManufacter(“Honda”);

                  car.setMarketValue(new BigDecimal(740000));

                  rentCarServicesImpl.addNewCar(car );

            }catch (Exception e) {

                  Assert.fail(“not expected result”);

            }

      }

      @Test

      public void testListAllCarIsNotEmpty(){

            assertFalse(rentCarServicesImpl.findAll().isEmpty());

      }

 Resultado

Lembre-se que seu BD precisa está rodando

springhibernateunittestresult

 

Ufa! Esse post foi longo heim, mas não tinha outra forma de mostrar tudo se não fosse assim, e olha que busquei resumir ao máximo possível. Enfim, vou ficando por aqui.

GitHub

Acesse o repositório no github com todos os projetos da série Spring:  https://github.com/camilolopes/workspacespring

Espero que tenham gostado do post.

Abraços, see ya!! 

Série Spring:Spring 3 com Hibernate 3.x

Olá Pessoal,

No post de hoje, veremos como integrar Spring com Hibernate. Ou seja, como podemos deixar tudo ao comando do Spring?  Deixar ele abrir ,fechar, commit , dar roll back nas transações? Diretamente o Spring não faz isso, mas ele delega para um cara que pode fazer isso. A moral da história que ao invés de nós programadores ter que dar beginTransaction, isso serrá feito nos bastidores. No exemplo a seguir fazeremos apenas um insert no banco de dados.

Lets go…

 

Requisitos

Antes de mais nada certifique que vc tem os .jars baixados:

  • – Mysql 5 .x
  • – Hibernate 3.6
  • – Spring 3.x
  • – AOP 1.x
  • – AspectJ
  • – commons-logging 1.x

Depois de garantir que você tem todos os .jars mãos na massa agora.

Starting…

Primeiro passo é que nosso exemplo será um Java Application, o objetivo é fazer a integração de maneira mais simples e funcional possível. Então crie seu Java Project e deixe conforme a imagem a seguir:

springwithhibernateproject

No final teremos os seguintes packages e classes:

 springhibernatepackages

Por onde começar?

Eu gosto sempre de iniciar pela parte de configuração, assim quando vou começar o desenvolvimento não preciso voltar para configurar, exceto quando é algo bem pontual. Então, iniciaremos pelo arquivo de configuração do Spring, no package config, crie um springconfiguration.xml.

Vou colocar o arquivo por partes e explicando, além disso coloquei uns comentários no .xml para facilitar o entendimento:

<beans xmlns=“http://www.springframework.org/schema/beans”

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

xmlns:context=“http://www.springframework.org/schema/context”

xmlns:tx=“http://www.springframework.org/schema/tx”

xsi:schemaLocation=“http://www.springframework.org/schema/beans

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

http://www.springframework.org/schema/context

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

http://www.springframework.org/schema/tx

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

 

Se vc vem acompanhando os outros posts e já conhece o básico do Spring deve conhecer o beans. A única coisa de novo que adicionamos aqui foi o xmlns tx para as transaction, que veremos mais na frente a sua importância. Portanto deixe seu beans conforme o código acima.

<!– buscando os beans –>

<context:component-scan base-package=“*” />

<!– transaction via annotations –>

<tx:annotation-driven />

<!– Translate exception –>

<bean class=“org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor”/>

 Aqui  temos um cara novo que é o PersistenceExceptionTransalationPostProcessor que é responsável por  “traduzir” as exceções checked em unchecked do Spring, assim não precisamos ficar tratando na nossa application.  Habilitamos que as transaction serão via annotation, ou seja, o Spring vai procurar pela annotation @Transaction. E também informamos que todo bean do Spring será via annotation e base de package colocamos todos.

DataSource

Agora precisamos criar um DataSource assim vamos dizer a que banco estaremos conectado em qual url e com o usuário xxxx, com a senha yyyyy.

<bean id=“dataSource” class=“org.springframework.jdbc.datasource.DriverManagerDataSource”>

<property name=“driverClassName” value=“com.mysql.jdbc.Driver”/>

<property name=“url” value=“jdbc:mysql://localhost/test”/>

<property name=“username” value=“root”/>

<property name=“password” value=“bahia”/>

</bean>

 SessionFactory

Agora precisamos configurar nossa  sessionFactory, nesse caso estamos dizendo que vamos usar annotation  para persistência. Lembra que fazíamos isso diretamente no Hibernate na hora de criar a sessionFactory (new annotationXXX)?  Aqui há alguns pontos importantes:

<bean id=“sessionFactory” class=“org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>

<!– informando o datasource, de onde vem a conexão? –>

<property name=“dataSource” ref=“dataSource”/>

<!– onde estão as classes com annotation? informando aqui –>

<property name=“packagesToScan” value=“br.com.camilolopes.model.bean”/>

<!– as configs do ormhibernate –>

<property name=“hibernateProperties”>

      <props>

<prop key=“hibernate.dialect”>org.hibernate.dialect.MySQL5InnoDBDialect”</prop>

      <prop key=“hibernate.hbm2ddl.auto”>update</prop>

      </props>

</property>

</bean>

 

Agora precisamos criar o cara que vai gerenciar as transaction no nosso caso como estamos usando o Hibernate será o HibernateTransactionManager:

<!–  esse é o cara que gerencia as transactions –>

<bean id=“transactionManager” class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>

<property name=“sessionFactory” ref=“sessionFactory”/>

</bean>

 Pronto terminamos a parte de configuração. Vamos agora para parte Java

Development

No package dao. Criaremos uma interface. Nossa aplicação vai salvar um produto apenas.

public interface ProductDAO {

      void save(ProductTech product);

}

 Agora vem a classe que implementa a interface:

@Repository

public class ProductDAOImpl implements ProductDAO {

      private SessionFactory sessionFactory;

      @Autowired

      public ProductDAOImpl(SessionFactory sessionFactory) {

            this.sessionFactory = sessionFactory;

      }

      private Session currentSession(){

            return sessionFactory.getCurrentSession();

      }

       @Override  //para execução deste método é requerido uma transação, é isso que estamos dizendo aqui

      @Transactional(propagation=Propagation.REQUIRED,readOnly=false)

      public void save(ProductTech product) {

            currentSession().save(product);

            System.out.println(“product saved with sucess”);

      }

}

 

E a nossa entidade:

@Entity

public class ProductTech implements Serializable{

      @Id

      @GeneratedValue

      private Long id;

      private String nameProduct;

                //getters/setters ommitidos

 

Testando

Vamos criar uma classe com método main para testar:

public class MainTestDAO {

      public static void main(String[] args) {

            ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“config/springconfiguration.xml”);

            ProductDAO bean = (ProductDAO) applicationContext.getBean(“productDAOImpl”);

            ProductTech product= new ProductTech();

            product.setNameProduct(“tablet samsung galaxy”);

            bean.save(product);

      }

}

Antes de rodar garanta que o Banco está rodando.  Ao executar:

springhibernateresultado

Fácil não? Nos preocupamos mais com a parte de negócio, toda aquela parte chata de transação por exemplo está sendo cuidada nos bastidores.

Bom, vou ficando por aqui. E espero que tenham gostado do post.

Abraços see ya!! 

Série Spring: CRUD com Hibernate e Spring framework

olá Pessoal,

O post de hoje vamos fazer um CRUD usando Spring com Hibernate. Nós últimos posts vimos as coisas de forma separada para entendermos o funcionamento bem especifico. Vou considerar que leu nossos posts anteriores e aquilo que já foi explicado não estarei repetindo,para evitar que o post fique longo, apenas estarei ressaltando o que for importante e relevante para que você entenda.

Lets go..

O nosso Cenário

Será bem simples e funcional e o mais direto possível. O cenário é bem trivial uma livraria tem vários e um livro está para uma categoria, e em uma categoria pode ter vários livros.Dai vamos exercitar o relancionamento @OneToMany do hibernate e a integração do Hibernate com Spring. E para completar faremos a injeção de dependência usando Annotations.

 

Desenvolvimento

A seguir como ficará o nosso projeto

 springcrudbookproject

1. Crie um java project e os respectivos packages 

2. Adicione as bibliotecas do Spring Framework 3.x, Hibernate 3.x e MySql 5.x 

3. Crie a interface que terá o CRUD:

public interface BookStore {

                void saveOrUpdate(Book book);

                void delete(Book book);

                Book findById(Long id);

} 

4. Agora criaremos a classe que vai implementar a Interface:

@Repository

public class BookStoreDAO implements BookStore {               

                @Autowired

                private HibernateTemplate hibernateTemplate; 

                @Override

                public Book findById(Long id) {

                               return hibernateTemplate.get(Book.class, id);

                } 

                public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {

                               this.hibernateTemplate = hibernateTemplate;

                } 

                public HibernateTemplate getHibernateTemplate() {

                               return hibernateTemplate;

                } 

                @Override

                public void saveOrUpdate(Book book) {

                               hibernateTemplate.saveOrUpdate(book);

                } 

                @Override

                public void delete(Book book) {

                               hibernateTemplate.delete(book);

                }}

 

 Até aqui nada de especial, exceto anotação @Autowired que colocamos para informar ao Spring que aquele atributo é dependecy injection que é controlado por ele. Quando criarmos o nosso arquivo de configuração do Spring vamos dizer para ele como olhar para as annotations. E anotação @Repository é para dizer ao Spring que essa classe é um DAO.

Agora vamos criar a classe CategoryDAO que vai persistir as categorias

@Repository

public class CategoryDAO {

                @Autowired

                private HibernateTemplate hibernateTemplate;               

                public void saveOrUpdate(Category category){

                               hibernateTemplate.saveOrUpdate(category);

                }}

Por enquanto essa classe não vai compilar, pq ainda não criamos a classe Category que criamos daqui a pouco, aguarde mais uns minutinhos. Bom,  até agora temos nossos DAOs prontos. Vamos criar nossos beans.

 

Book .java 

@Entity

public class Book implements Serializable{

                private static final long serialVersionUID = 888299914160143622L;               

                @Id

                @GeneratedValue

                private Long id;

                private Long isbn;

                private String title;

                private String author;

                @ManyToOne

                @JoinColumn(name=”category_id”)

                @Autowired

                private Category category;

//getters/setters omitidos

 

Category.java 

@Entity

public class Category implements Serializable { 

                private static final long serialVersionUID = 6469382724082923338L;

                @Id

                @GeneratedValue

                private Long id;

                private String categoryName;

                @OneToMany(mappedBy=”category”,targetEntity=Book.class,

fetch=FetchType.LAZY,cascade=CascadeType.ALL)

                @Autowired

                private List<Book> books = new ArrayList<Book>();

//getters/setters omitidos

 

Nada de especial aqui, apenas um relacionamento @OneToMany/@ManyToOne e o famoso @AutoWired que fará injeção de dependência.

 

Configurando o Spring 

1. Crie um arquivo xml e coloque no package conf,o meu chamei de springconfiguration.xml

 

O cabeçalho fica assim para dar suporte aos annotations: 

<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-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd”>

 

Agora vamos criar os beans:

<!– beans  –>

 <bean  id=”category” class=”br.com.camilolopes.domain.classes.Category”/>

 <bean  id=”book”/>

 <bean  id=”bookstoredao” class=”br.com.camilolopes.dao.BookStoreDAO”/>

 <bean  id=”categorydao” class=”br.com.camilolopes.dao.CategoryDAO”/>

 

O dataSource, vou usar o MySql 

<!– DataSource –>

<bean id=”dataSource”>

                <property name=”driverClassName” value=”com.mysql.jdbc.Driver”/>

                <property name=”url” value=”jdbc:mysql://localhost/test”/>

                <property name=”username” value=”root”/>

                <property name=”password” value=”camilo2593″/>

</bean>

 <!– Using Annotations for mapping –>

 <bean id=”sessionFactory” class=”org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>

 <!– property for DataBase –>

                <property name=”dataSource” ref=”dataSource”/>

                <!– informing the annotated classes –>

                 <property name=”annotatedClasses”>

                <list>

                               <value>br.com.camilolopes.domain.classes.Book</value>

                               <value>br.com.camilolopes.domain.classes.Category</value>

                </list>

                </property>

                <!– Property of Hibernate –>

                <property name=”hibernateProperties”>

                               <props>

                               <prop key=”hibernate.dialect”>org.hibernate.dialect.MySQLDialect</prop>

                <prop key=”hibernate.show_sql”>true</prop>

                <prop key=”hibernate.hbm2ddl.auto”>update</prop>

                               </props>

                </property>

 </bean> 

 <!– using HibernateTemplate from Spring –>

 <bean  id=”hibernateTemplate” class=”org.springframework.orm.hibernate3.HibernateTemplate”>

                <property name=”sessionFactory” ref=”sessionFactory”/>

 </bean>

 

E definindo o uso de annotations para o Spring:

<context:annotation-config/>

E não esqueça de fechar o arquivo com:

</beans>

 

Agora criaremos uma classe com método main para realizar o CRUD: 

 

bdcrudspring

Esse é o nosso banco, com um cara já persistido: 

Crie a classe Main 

public class Main {

                public static void main(String[] args) {

//                           essa classe é o container

                               ApplicationContext applicationContext = new ClassPathXmlApplicationContext(

                                                               “conf/springconfiguration.xml”);

                               BookStoreDAO bookStoreDAO = (BookStoreDAO) applicationContext.getBean(“bookstoredao”);

                               CategoryDAO categoryDAO = (CategoryDAO) applicationContext.getBean(“categorydao”);                              

//                           Book

                               Book book = new Book();

                               book.setAuthor(“Camilo Lopes”);

                               book.setIsbn(1235L);

                               book.setTitle(“Guia JEE c/ Frameworks”);                              

                               //Category

                               Category category = new Category();

                               category.getBooks().add(book);

                               category.setBooks(category.getBooks());

                               category.setCategoryName(“Development”);

                               book.setCategory(category );

//                           DAO

                                categoryDAO.saveOrUpdate(category);

                               bookStoreDAO.saveOrUpdate(book);                              

                               findBookById(bookStoreDAO, 1L);

                               deleteBook(bookStoreDAO,1L);

                }               

                private static void deleteBook(BookStoreDAO bookStoreDAO, long id) {

                               Book bookFound = bookStoreDAO.findById(id);

                               bookStoreDAO.delete(bookFound);

                               System.out.println(“Book deleted with sucess ” + bookFound.getTitle());                              

                }

                private static void findBookById(BookStoreDAO bookStoreDAO, Long id){

                               Book book = bookStoreDAO.findById(id);

                               System.out.println(“Title: “+ book.getTitle());

                               System.out.println(“Author: ” + book.getAuthor());

                }}

 

O código é bem simples somente para testarmos. Observe que salvamos um novo livro, em seguida buscamos o mesmo pelo Id e imprimos usando  o console do Java e depois deletamos o livro pelo Id.

Ao rodar teremos o resultado a seguir: 

resultcrudspring

Se formos no banco esperamos ter apenas o livro mais recente adicionado com o id igual 2 e o livro com o id = 1 deve ter sido deletado, com a imagem acima já vimos isso, pq temos o sql do hibernate habilitado, mas vamos ver na tabela do banco:

resultspringbd

 

resultcategoryspringbd

 

GitHub

Acesse o repositório no github com todos os projetos da série Spring:  https://github.com/camilolopes/workspacespring

Bom vou ficando por aqui, espero que tenham gostado do post.

abracos, see ya!!!