Spring and JPA with two data sources (with annotations)

A few days I recevied a comment from my friend @sock_osg (you can follow on twitter) he recomends me to rewrite my previous post with annotations.

And well here is it. But the are more few things to comment about it, for example in the previous post there are not a Transactional capabilities between DB’s because I’m not using JTA transaction type.

Now for this example I write the code to support transactions between multple data bases with different data sources, like I read on stack overflow:

if you find yourself with multiple entity managers, with corresponding tx managers, then you should consider using a single JtaTransactionManager instead. The entity managers should be able to participate in JTA transactions, and this will give you full transactionality across both entity managers, without having to worry about which entity manager you’re in at any one time.

You can download all code here, it’s hosted on my Github account, pull the code from the branch named “annotations”.

Let’s review the most important files, frst the DAO classes: Seguir leyendo

Anuncios

Spring and JPA with two data sources

JPA it’s the most used standar in java to manage the persistence and I ever want to write about this topic.

In this entry I want to share how configure a java project to use JPA with spring with two data sources, you can view all source of this project on my github repository.

Most of the configuration is in spring, in the application context you need declare:

  • 2 Data Sources
  • 2 Entity Manager Factories
  • 2 Transaction Manager

This is explained by self:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       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.xsd
        http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/jdbc
        http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">

    <context:property-placeholder location="classpath:app-props.properties" />

    <context:component-scan base-package="org.oz" />
    <context:annotation-config/>

    <bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="persistenceXmlLocations">
            <list>
                <value>classpath:META-INF/persistence.xml</value>
            </list>
        </property>
        <property name="dataSources">
            <map>
                <entry key="localDataSource" value-ref="dataSource1"/>
                <entry key="remoteDataSource" value-ref="dataSource2"/>
            </map>
        </property>

        <!-- if no datasource is specified, use this one -->
        <property name="defaultDataSource" ref="dataSource1"/>
        <property name="defaultPersistenceUnitName" value="unit1"/>

    </bean>

    <bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true" primary="true"
          p:driverClassName="${jdbc1.driver}"
          p:url="${jdbc1.url}"
          p:username="${jdbc1.user}"
          p:password="${jdbc1.pass}"
    />

    <bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:persistenceXmlLocation="classpath:META-INF/persistence.xml"
          p:persistenceUnitName="unit1"
          p:dataSource-ref="dataSource1"
          p:packagesToScan="org.oz.persistence.dao.db1"
          lazy-init="true"/>

    <bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory1"
          lazy-init="true"/>

    <bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true"
          p:driverClassName="${jdbc2.driver}"
          p:url="${jdbc2.url}"
          p:username="${jdbc2.user}"
          p:password="${jdbc2.pass}"
    />

    <bean id="entityManagerFactory2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
          p:persistenceXmlLocation="classpath:META-INF/persistence.xml"
          p:persistenceUnitName="unit2"
          p:dataSource-ref="dataSource2"
          p:packagesToScan="org.oz.persistence.dao.db2"
          lazy-init="true"/>

    <bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager"
          p:entityManagerFactory-ref="entityManagerFactory2"
          lazy-init="true"/>

    <tx:annotation-driven transaction-manager="transactionManager1"  />
    <tx:annotation-driven transaction-manager="transactionManager2" />

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

    <bean id="customerDao" class="org.oz.persistence.dao.db1.CustomerDao"/>
    <bean id="productDao" class="org.oz.persistence.dao.db2.ProductDao"/>

</beans>

 

Now in peresistence.xml we going to declare two persistence units:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
             http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="unit1" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <mapping-file>META-INF/native-querys.xml</mapping-file>
        <class>org.oz.persistence.dao.db1.model.Customer</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.archive.autodetection" value="class,hbm"/>
            <property name="useUnicode" value="true"/>
            <property name="characterSetResults" value="UTF8"/>
            <property name="characterEncoding" value="UTF8"/>
            <property name="hibernate.format_sql" value="false"/>
            <property name="hibernate.use_sql_comments" value="false"/>
            <property name="hibernate.hbm2ddl.keywords" value="auto-quote"/>
            <property name="hibernate.bytecode.use_reflection_optimizer" value="true"/>
            <property name="hibernate.connection.useUnicode" value="true"/>
            <property name="hibernate.connection.characterEncoding" value="UTF8"/>
            <property name="hibernate.connection.charSet" value="UTF8"/>
            <property name="hibernate.connection.characterSetResults" value="UTF8"/>

            <property name="hibernate.default_schema" value="BASEA"/>
        </properties>

    </persistence-unit>

    <persistence-unit name="unit2" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <mapping-file>META-INF/native-querys.xml</mapping-file>
        <class>org.oz.persistence.dao.db2.model.Product</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
            <property name="hibernate.archive.autodetection" value="class,hbm"/>
            <property name="useUnicode" value="true"/>
            <property name="characterSetResults" value="UTF8"/>
            <property name="characterEncoding" value="UTF8"/>
            <property name="hibernate.format_sql" value="false"/>
            <property name="hibernate.use_sql_comments" value="false"/>
            <property name="hibernate.hbm2ddl.keywords" value="auto-quote"/>
            <property name="hibernate.bytecode.use_reflection_optimizer" value="true"/>
            <property name="hibernate.connection.useUnicode" value="true"/>
            <property name="hibernate.connection.characterEncoding" value="UTF8"/>
            <property name="hibernate.connection.charSet" value="UTF8"/>
            <property name="hibernate.connection.characterSetResults" value="UTF8"/>

            <property name="hibernate.default_schema" value="BASEB"/>
        </properties>

    </persistence-unit>
</persistence>

Then only we’re need to do is set the reference of the persistence unit in every DAO to inject the EntityManager:

package org.oz.persistence.dao.db1;

import javax.persistence.*;
import java.util.Collection;

/**
 * Created by <a href="https://twitter.com/jaehoox">jaehoo</a> on 16/03/2018
 */
public class CustomerDao {

    public static final String SEL_TABLES="select.tablesh2";

    @PersistenceContext(unitName = "unit1" , type = PersistenceContextType.TRANSACTION)
    private EntityManager em;

    public Collection loadCustomers() {
        Query query = em.createQuery("FROM Customer");
        return query.getResultList();

    }

    public Collection getTables(){
        return em.createNamedQuery(SEL_TABLES).getResultList();
    }

}

package org.oz.persistence.dao.db2;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import java.util.Collection;

/**
 * Created by <a href="https://twitter.com/jaehoox">jaehoo</a> on 16/03/2018
 */
public class ProductDao {

    public static final String SEL_TABLES="select.tablesh2";

    @PersistenceContext(unitName = "unit2", type = PersistenceContextType.TRANSACTION, name = "unit2")
    private EntityManager em;

    public Collection loadProducts() {
        Query query = em.createQuery("FROM Product");
        return query.getResultList();

    }

    public Collection getTables(){
        return em.createNamedQuery(SEL_TABLES).getResultList();
    }

}

The interesting point of this is in the use of the transaction manager, lets take a look on test class:

package org.oz.persistence.dao.db1;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.oz.persistence.dao.db1.model.Customer;
import org.oz.persistence.dao.db2.ProductDao;
import org.oz.persistence.dao.db2.model.Product;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:app-ctx-test.xml"})
@TransactionConfiguration
@Slf4j
public class CustomerDaoTest {

    @Resource(name = "customerDao")
    private CustomerDao customerDao;

    @Resource(name = "productDao")
    private ProductDao productDao;

    @Test
    @Transactional("transactionManager1")
    public void loadCustomers() throws Exception {

        List customers = (List) customerDao.loadCustomers();

        log.info("customers:{}",customers.size());

        for(Customer c : customers){
            log.info("{}",c);
        }

        List tables = (List) customerDao.getTables();

        log.info("tables:{}",tables.size());
        for(Object c : tables){
            log.info("{}",c);
        }

    }

    @Test
    @Transactional("transactionManager2")
    public void loadProducts() throws Exception {

        List products = (List) productDao.loadProducts();

        log.info("products:{}",products.size());
        log.info("{}",products.get(0));

        List tables = (List) productDao.getTables();

        log.info("tables:{}",tables.size());
        for(Object c : tables){
            log.info("{}",c);
        }

    }

    @Test
    public void queryngTwoSoruces() throws Exception {

        log.info("getting data from two DS in one method");
        List tables = new ArrayList();

        tables.addAll(productDao.getTables());
        tables.addAll(customerDao.getTables());

        log.info("tables:{}",tables.size());
        for(Object c : tables){
            log.info("{}",c);
        }

    }

}

The first lines load the application context and inject DAO classes with the Entity Manager.

The first and the second method get all records of the customer and Product table and get all data base table names, each of one is using their corresponding transaction manager (as you can see on @Transactional annotation), until here everything is clear you can querying data from each data base.

But what happens in the third method??

Interesting rigth? and the anwser is… there is not a Transaction implicit, yeah so simple! it works but I don’t have transactional capabilities, that means that I need to manage each transaction in separated ways.

But I read this in stackoverflow:

The javadoc for JpaTransactionManager has some advice on this:

“This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. Note that you need to configure your JPA provider accordingly in order to make it participate in JTA transactions.”

In other words, if you find yourself with multiple entity managers, with corresponding tx managers, then you should consider using a single JtaTransactionManager instead. The entity managers should be able to participate in JTA transactions, and this will give you full transactionality across both entity managers, without having to worry about which entity manager you’re in at any one time.

Of course, JtaTransactionManager does require a full JTA-supporting application server, rather than a vanilla servlet engine like Tomcat.

Maybe one day I’ll write about how to do this with the server container but now this is enough.

Cheers

EJB 3 Overview


Recientenmente he tenido que analizar un proyecto web que se encuentra divido en dos partes (backend y frontend), el entregable es un ear con un jar y un war.

Todo el backend esta constriudo con EJB’s y aunque siempre he escuchado pestes de esta tecnología nunca le he dado un vistazo. Así que comencé por leer algunos artículos y en realidad me parece que los EJB’s son una buena iniciativa en Java para simplificar el desarrollo y adoptar mejores prácticas. Particularmente me ha encantado este:

http://refcardz.dzone.com/refcardz/dependency-injection-in-ejb3 Seguir leyendo

OZ Ejemplo Cajero ATM

¿Que vamos a desarrollar?

Una aplicación que simule el funcionamiento de un cajero automático, mostrando el uso de múltiples frameworks Java para crear un sistema modular y extendible.

Requisitos

  • Apache Maven >= 3.X
  • Java JDK >=  1.6
  • Netbeans >= 6.5
  • Base de Datos MySQL

Análisis

Supongamos que tenemos el siguiente requerimiento por parte del cliente o del analista:

Crear un cajero que permita realizar dos operaciones, Retirar efectivo y hacer Transferencias a otro Banco.

Veamos como se vería en un diagrama de casos de uso:

El usuario unicamente va a realizar dos operaciones retiro y transferencia.

Bien ahora la base de datos, vamos a utilizar este script para generarla.  Ejecutas el archivo en tu gestor favorito y te  creará el esquema llamado OZ_TEST, con las siguiente tablas:

Seguir leyendo

Spring Security, problemas con proxy Apache

He participado en un desarrollo web donde me ha tocado configurar un proxy con el servidor apache (mis últimos artículos han sido sobre este tema), la idea es exponer una aplicación web en Java por medio de un proxy con Apache.

Tengo una aplicación Java que utiliza Spring Security y todo funciona de maravilla cuando entras a la página web, sin embargo al colocar el proxy frente a este servidor Spring Security puede provocar algunos problemas:

Problema 1: Login, Authentication method not supported: GET

A la fecha no entiendo como puede ser esto posible, dentro del form está estrictamente definido que los datos se envían por POST y no por GET:

Este es el formulario: Seguir leyendo

Hibernate Composite Keys With Annotations

Hibernate, Llaves Compuestas Con Anotaciones

Dentro de las buenas y muy malas experiencias que me han tocado con Hibernate he aprendido que existen varios caminos y formas de utilizarlo, y en esta publicación quiero colocar la forma para crear una tabla con llaves compuestas utilizando anotaciones.

A pesar de que esto puede sonar una tarea común y corriente implica conocer algunos detalles que a veces son imperceptibles para los desarrolladores hasta que estamos frente al IDE (o editor de texto) y decimos “Y ahora como rayos hago esto??”, en fin en mi experiencia esto es lo que  he encontrado:

Nota: Los ejemplos los hice en MySQL pero llevan la anotación SequenceGenerator por que funcionan también en Oracle sin modificar nada de códig

Seguir leyendo

Introducción a Spring Framework

¿Que es Spring?

Es un contenedor ligero para la construcción de aplicaciones empresariales que proporciona un soporte comprensivo para el desarrollo de sistemas. Spring framework es modular, por lo cual te permite utilizar solo lo que necesitas, además no es intrusivo, es decir se integra facilmente en los proyectos y promueve el desarrollo con una alta cohesion (Especialización de clases) y bajo acoplamiento (Codigo menos dependiente).

Te permite generar código que no es dependiente incluso del mismo Spring (solo para el Core), por lo que facilmente puedes remover el framework si así lo deseas y por si fuera poco, se integra perfectamente con otros frameworks (¬¬ honestamente yo no lo cambiaría por nada!!!)

En resumen, yo me quedo con esta maravillosa frase que viene su documentación oficial:

“Spring handles the infrastructure so you can focus on your application.”

Spanish:

“Spring maneja la infraestructura así que TU puedes enfocarte en tu aplicación”

Seguir leyendo