Announcement Announcement Module
Collapse
No announcement yet.
Can't get embedded JBoss JTA to work (no rollback) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can't get embedded JBoss JTA to work (no rollback)

    As the title says I'm trying (for evaluation purposes) to use embedded JBoss JTA as the JtaTransactionManager.

    I wrote a Junit test that verifies the atomicity of a transaction (one SQL insert via a JdbcTemplate, then i throw a RuntimeException that should rollback the transaction).
    The transactional resource is a JDBC datasource that hits a H2 database.

    The same test with a DatasourceTransactionManager works fine.

    I have read the doc and the chapter about transaction management, but it doesn't have a JtaTransactionManager example explicitly about the case of a non-J2EE (embedded) JTA transaction manager.
    I have seen other posts of people who had the same issue, but it didn't help either.

    The test (it is create2Foos_rollbacked that fails with JtaTransactionManager):
    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration ( locations={"/resources/application-context.xml"} )
    public class TestTransactionsDeclarativesSpring_Jdbc
    {
    	@Resource ( name="fooServiceDB" )
    	private FooService fooServiceDB;
    	
    	@Before
    	public void viderFoos ()
    	{
    		fooService().deleteAllFoos();
    		assertEquals ( 0 , fooService().findNumberOfFoos() );
    	}
    	
    	@Test
    	public void fooCreated () throws Exception
    	{
    		fooService().createFoo();
    		assertEquals ( 1 , fooService().findNumberOfFoos() );
    	}
    	
    	@Test
    	public void create2Foos_committed () throws Exception
    	{
    		fooService().create2Foos ( false );
    		assertEquals ( 2 , fooService().findNumberOfFoos() );
    	}
    	
    	@Test
    	public void create2Foos_rollbacked () throws Exception
    	{
    		try
    		{
    			fooService().create2Foos ( true );//true=runtime exception thrown, transaction should be rollbacked
    			fail ();
    		}
    		catch ( DummyException d ) 
    		{}
    		
    		assertEquals ( 0 , fooService().findNumberOfFoos() );//Fails: expected 0, got 1 (the transaction wasn't rolled back)
    	}
    }
    The spring conf (test OK with <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>, KO with <tx:annotation-driven transaction-manager="jtaTransactionManager"/>)
    Code:
    <?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:tx="http://www.springframework.org/schema/tx"
           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">
        
        <context:component-scan base-package="hellotrackworld"/>
    
    									<!--vvvvv TRANSACTION MANAGERS vvvvv-->
    	<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource0" />
    	</bean>
    
    	<bean id="jbossTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple" />
    	<bean id="jbossUserTransaction" class="com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple"/>
      	<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        	<property name="transactionManager" ref="jbossTransactionManager" />
        	<property name="userTransaction" ref="jbossUserTransaction" />
      	</bean>
      									<!--^^^^^ TRANSACTION MANAGERS ^^^^^-->
    	
    									<!--vvvvv DATASOURCES vvvvv-->
    	<bean id="dataSource0" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
    		<property name="driverClassName" value="org.h2.Driver" />
    		<!--<property name="driverClassName" value="com.arjuna.ats.jdbc.TransactionalDriver" />-->
    		<property name="url" value="jdbc:h2:tcp://localhost/~/test" />
    		<property name="username" value="sa" />
    		<property name="password" value="" />
    	</bean>
    	
    	<!--<bean id="dataSource1" class="org.enhydra.jdbc.standard.StandardXADataSource">
    		<property name="driverName" value="org.h2.Driver" />
    		<property name="driverName" value="com.arjuna.ats.jdbc.TransactionalDriver" />
    		<property name="url" value="jdbc:h2:tcp://localhost/~/test" />
    	</bean>
    	<bean id="dataSource0" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">
       		<property name="dataSource" ref="dataSource1"/>
       		<property name="user" value="sa" />
    		<property name="password" value="" />
        </bean>-->
    									<!--^^^^^ DATASOURCES ^^^^^-->
    	
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
    		<constructor-arg ref="dataSource0" />
    	</bean>
    	
    	<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
    	<!--<tx:annotation-driven transaction-manager="jtaTransactionManager"/>-->
    
    </beans>
    The service implementation:
    Code:
    package hellotrackworld.spring.foo;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.annotation.Resource;
    
    import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Isolation;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    @Service("fooServiceDB")
    @Transactional (
    		propagation=Propagation.REQUIRED,
    		isolation=Isolation.DEFAULT,
    		readOnly=false,
    		timeout=5000)
    public class FooServiceDBImpl implements FooService 
    {
    	@Resource (name="jdbcTemplate")
    	private SimpleJdbcTemplate template;
    	
    	private static final String INSERT = "insert into TOTO (NOM) values (:NOM)"; 
    	private static final String DELETE_ALL = "delete from TOTO";
    	private static final String SELECT_ALL = "select count(*) from TOTO";
    	
    	@Override
    	public void create2Foos ( boolean failSecond ) 
    	{
    		System.out.println ( "create2Foos" );
    		Map<String,String> map = new HashMap<String,String> ();
    		
    		map.put ( "NOM" , "aaa" );
    		template.update ( INSERT , map  );
    		
    		if ( failSecond )
    		{
    			throw new DummyException ( "__DUMMY__" );
    		}
    		else
    		{
    			map.put ( "NOM" , "bbb" );
    			template.update ( INSERT , map  );			
    		}
    	}
    
    	@Override
    	public void createFoo() 
    	{
    		System.out.println ( "createFoo" );
    		Map<String,String> map = new HashMap<String,String> ();
    		map.put ( "NOM" , "aaa" );
    		template.update ( INSERT , map  );
    	}
    
    	@Override
    	public void deleteAllFoos() 
    	{
    		System.out.println ( "deleteAllFoos" );
    		template.update ( DELETE_ALL );
    	}
    
    	@Override
    	@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=true)
    	public int findNumberOfFoos() 
    	{
    		return template.queryForInt ( SELECT_ALL );
    	}
    }

  • #2
    It works with Atomikos essentials; here is the conf:
    Code:
    <?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:tx="http://www.springframework.org/schema/tx"
           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">
        
        <context:component-scan base-package="hellotrackworld"/>
    
        <bean id="atomikosNonXADataSource" class="com.atomikos.jdbc.nonxa.NonXADataSourceBean">
    		<property name="user" value="sa"/>
    		<property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
    		<property name="driverClassName" value="org.h2.Driver"/>
    	</bean>
    	
      	<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
    		<property name="forceShutdown" value="true"/>
    	</bean>
    	<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
        	<property name="transactionTimeout" value="300"/>
    	</bean>
      	
      	<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        	<property name="transactionManager" ref="atomikosTransactionManager" />
        	<property name="userTransaction" ref="atomikosUserTransaction" />
      	</bean>
    	
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
    		<!--<constructor-arg ref="dbcpDataSource" />-->
    		<constructor-arg ref="atomikosNonXADataSource" />
    	</bean>
    	
    	<tx:annotation-driven transaction-manager="jtaTransactionManager"/>
    
    </beans>
    The difference seems to be using a specific datasource (here atomikosNonXADataSource). Maybe there is a JbossTS equivalent .

    Comment

    Working...
    X