Prezados,
No projeto em que trabalho, tive a necessidade de configurar 2 DataSources diferentes, pois preciso acessar duas bancos de dados diferentes. Achei uma solução com o Atomikos e agora consigo obter os dois sem problemas. O problema agora está no controle de transação do Spring com o @Transactional.
Tenho meu Controller do VRaptor com um método salvar que preciso que seja transacionado, pois ele executa uma série de operações de inserção no banco de dados e se ocorrer algum erro, deve ser realizado Rollback. O problema é que o Rollback não acontece.
Meu applicationContext.xml:
[code]<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” 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/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd”>
<tx:annotation-driven />
<bean id="dataSourceUm" class="com.atomikos.jdbc.AtomikosDataSourceBean">
<property name="uniqueResourceName"><value>dataSourceUm</value></property>
<property name="xaDataSourceClassName"><value>org.postgresql.xa.PGXADataSource</value></property>
<property name="xaProperties">
<props>
<prop key="user">${db1.usuario}</prop>
<prop key="password">${db1.senha}</prop>
<prop key="databaseName">${db1.nomebanco}</prop>
<prop key="serverName">${db1.url}</prop>
<prop key="portNumber">${db1.porta}</prop>
</props>
</property>
<property name="maxPoolSize" value="10" />
<property name="minPoolSize" value="5" />
<property name="maxIdleTime" value="1200" />
<property name="testQuery" value="select 1" />
<property name="reapTimeout" value="0" />
</bean>
<bean id="dataSourceDois" class="com.atomikos.jdbc.AtomikosDataSourceBean">
<property name="uniqueResourceName"><value>dataSourceDois</value></property>
<property name="xaDataSourceClassName"><value>org.postgresql.xa.PGXADataSource</value></property>
<property name="xaProperties">
<props>
<prop key="user">${db2.usuario}</prop>
<prop key="password">${db2.senha}</prop>
<prop key="databaseName">${db2.nomebanco}</prop>
<prop key="serverName">${db2.url}</prop>
<prop key="portNumber">${db2.porta}</prop>
</props>
</property>
<property name="maxPoolSize" value="10" />
<property name="minPoolSize" value="5" />
<property name="maxIdleTime" value="1200" />
<property name="testQuery" value="select 1" />
<property name="reapTimeout" value="0" />
</bean>
<bean id="sessionFactoryUm" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSourceUm" />
</property>
<property name="annotatedClasses">
<list>
//Classes anotadas...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<!-- atomikos -->
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">
com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
</props>
</property>
</bean>
<bean id="sessionFactoryDois" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSourceDois" />
</property>
<property name="annotatedClasses">
<list>
//Classes anotadas...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<!-- atomikos -->
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">
com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
</props>
</property>
</bean>
<bean id="um" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactoryUm"/>
</bean>
<bean id="dois" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactoryDois"/>
</bean>
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="true" />
<!-- this prop is in seconds -->
<property name="transactionTimeout" value="300"/>
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<!-- this prop is in seconds -->
<property name="transactionTimeout" value="300" />
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
<property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" />
</bean>
</beans>[/code]
Meu DAO:
[code]@Component
public class MeuDaoImpl implements MeuDao {
@Resource(name = "um")
private HibernateTemplate hibernateTemplate;
public void salvar(Entidade entity) {
hibernateTemplate.save(entity);
}
//...
}[/code]
Com essa estratégia, consigo obter um ou outro ( "um" ou "dois" ) HibernateTemplate definido no applicationContext.xml, neste caso estou obtendo o "um".
Meu Controller está anotado com @Resource do VRaptor. Meu Controller herda de outra classe (quer herda de outra) mas possui um construtor vazio. O método salvar:
[code]
@Autowired
private MeuDao meuDao;
@Post
@Transactional
public void salvar(Entity entity) throws Exception {
//Processamento fictício, apenas para testar o Rollback!
for (int i = 0; i < 2; i++) {
meuDao.salvar(entity);
}
throw new Exception("Forçando erro para testar o Rollback…");
}[/code]
Porém, o rollback não acontece, os dados são persistidos no banco.
Alguém sabe o que posso estar fazendo errado?
Grato pela atenção!
PS.: Tecnologias usadas: VRaptor + Spring + Hibernate + Atomikos + Postgres