Showing posts with label Spring Multiple Database Java JTA Hibernate Transactions. Show all posts
Showing posts with label Spring Multiple Database Java JTA Hibernate Transactions. Show all posts

Wednesday, August 12, 2009

Using Spring with multiple databases Part 4

In your web config file (web.xml) you reference your applicationcontext.xml file and any other configuration file that you need to use.
To configure Atomikos we created a xml file called jndi.xml and reference it in our web.xml file like so:

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



Here is how we configured Atomikos Transaction Manager in our jndi.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->

<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:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

<bean id="userTransactionService"
class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<!-- IMPORTANT: specify all Atomikos properties here -->
<props>
<prop key="com.atomikos.icatch.service">
com.atomikos.icatch.standalone.UserTransactionServiceFactory
</prop>
<prop key="com.atomikos.icatch.enable_logging">
false
</prop>
</props>
</constructor-arg>
</bean>



<!--JTA Manager-->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">

<!--
when close is called, should we force
transactions to terminate or not?
-->
<property name="forceShutdown" value="false" />
</bean>

<!--Also use Atomikos UserTransactionImp,
needed to configure Spring-->
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>

<bean id="jndi"
class="org.apache.xbean.spring.jndi.SpringInitialContextFactory"
factory-method="makeInitialContext">
<property name="entries">
<map>
<entry key="java:comp/TransactionManager" value-ref="AtomikosTransactionManager" />
<entry key="java:comp/UserTransaction" value-ref="AtomikosUserTransaction" />
<entry key="java:comp/UserTransactionService" value-ref="AtomikosUserTransaction" />
</map>
</property>
</bean>

</beans>


In the current trunk of Spring 3.0.0, when using the Spring MVC framework , I ended up having to place @Transactional (which tells the JVM to create a transaction) in my controller classes. I would have preferred to have them on my Data Access objects, but my Unit Tests revealed that Transactions only got created in the Spring MVC world when placed on my Controller classes.
Here is a code snippet example:

@Controller
@TransactionConfiguration(transactionManager="jtaTransactionManager", defaultRollback=false)
@Transactional
public class WizardController {

private static final Logger log = Logger
.getLogger(WizardController.class);

@Autowired
UserService userService;


In part 5, I will go over how to setup unit tests using JUnit 4 and Spring's Unit Test Annotations.

Using Spring with multiple databases Part 3

In this part, we setup our SessionFactories in our applicationcontext.xml file.
In our SessionFactories we specify our datasource, our entity classes, and also our hibernate properties.
Since we are using multiple databases, in this case 2 databases, we need to create two SessionFactory configurations.
Here is our first SessionFactory config that we place in applicationcontext.xml:

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.endurotracker.gwt.model.Users</value>

</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.isolation">3</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">com.endurotracker.gwt.transaction.AtomikosJTATransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</props>
</property>
</bean>




Here is our second SessionFactory config that we place in applicationcontext.xml:

<!--Hibernate SessionFactory2-->
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource2" />
<property name="annotatedClasses">
<list>
<value>com.endurotracker.gwt.model.Activitytype</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.isolation">3</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">com.endurotracker.gwt.transaction.AtomikosJTATransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</props>
</property>
</bean>


You will notice that we have 2 hibernate properties related to transactions:
hibernate.transaction.factory_class and hibernate.transaction.manager_lookup_class.
Due to a Hibernate bug ( bug HHH-3110), we had to create the following class which we reference as com.endurotracker.gwt.transaction.AtomikosJTATransactionFactory, so you can take this code and create your own class as well and update this property to your class name:

public class AtomikosJTATransactionFactory extends JTATransactionFactory{
UserTransaction userTransaction;

@Override
protected UserTransaction getUserTransaction() {
if (this.userTransaction == null)
{
this.userTransaction = new UserTransactionImp();
}

return this.userTransaction;

}

}


In Part 4, we will configure our Atomikos Transaction Manager via Atomikos' Transaction beans, and talk about how to use @Transactional Annotations in our Data Access layer and Controller layer. In Part 5, we will setup some unit tests using JUnit 4 and Spring's unit testing Annotations.