Atomikos Forum

Rollback in atomikos transaction causes partial commit of data

I am using JPA and this is my configuration:

@Entity
@Table(name = "EntityA")
public class EntityA implements Serializable
{
    @Id
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "EntityB_ID", nullable = false)
    private EntityB entityB;

    ...
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "entityB_type", discriminatorType = DiscriminatorType.STRING)
@Table(name = "EntityB")
public abstract class EntityB implements Serializable
{
    @Id
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "entityB_type")
    private String entityB_type;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "EntityC_ID", nullable = false)
    private EntityC entityC;

    ...
}

@Entity
@DiscriminatorValue("somevalue")
public class EntityB_Special extends EntityB implements Serializable
{
   
    @Column(name = "some_special_value")
    private String someSpecialValue;
}

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "entityC_type", discriminatorType = DiscriminatorType.STRING)
@Table(name = "EntityC")
public abstract class EntityC implements Serializable
{
    @Id
    private Long id;

    @Column(name = "entityC_type")
    private String entityC_type;

    ....
}

@Entity
@DiscriminatorValue("anothervalue")
public class EntityC_Special extends EntityC implements Serializable
{
   
    @Column(name = "another_special_value")
    private String anotherSpecialValue;
}

There are MySql foreign key constraints linking EntityA -> EntityB -> EntityC with database cascades set as "NO ACTION" since cascades are handled via hibernate.


This is my JTA.properties file:
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.console_file_name = EntityTxn.out
com.atomikos.icatch.log_base_name = EntityTxnlog
com.atomikos.icatch.console_log_level = WARN
com.atomikos.icatch.log_base_dir = ${catalina.base}/logs
com.atomikos.icatch.output_dir = ${com.atomikos.icatch.log_base_dir}
com.atomikos.icatch.tm_unique_name = Entity
com.atomikos.icatch.max_actives = 100

This is my spring transaction configuration:
<?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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<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="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionManager" ref="atomikosTransactionManager"/>
            <property name="userTransaction" ref="atomikosUserTransaction"/>
      </bean>

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

</beans>


This is my database configuration:

<bean id="entityDataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"><value>${master.jdbc.driver}</value></property>
        <property name="url"><value>${jdbc.url}</value></property>
        <property name="username"><value>${jdbc.user}</value></property>
        <property name="password"><value>${jdbc.password}</value></property>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="entityDataSource"/>
        
        <property name="annotatedClasses">
            <list>
<value>com.somepackage.EntityA</value>
<value>com.somepackage.EntityB</value>
<value>com.somepackage.EntityC</value>
<value>com.somepackage.EntityB_Special</value>
<value>com.somepackage.EntityC_Special</value>
</list>
</property>

<property name="entityCacheStrategies">
            <props>
                <prop key="com.somepackage.EntityA">read-only</prop>
                <prop key="com.somepackage.EntityB">read-only</prop>
                <prop key="com.somepackage.EntityC">read-only</prop>
            </props>
</property>

<property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.use_outer_join">false</prop>
                <prop key="hibernate.query.substitutions">true=1 false=0</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>
                <prop key="hibernate.connection.isolation">2</prop>
                <prop key="hibernate.current_session_context_class">jta</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
                <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory</prop>
                <prop key="net.sf.ehcache.configurationResourceName">${ehcache.config.file}</prop>
                <prop key="hibernate.cache.use_second_level_cache">false</prop>
            </props>
        </property>
    </bean>


I have a simple repository class as:
@Repository
public class EntityARepositoryImpl implements EntityARepository {
   
    /** Session factory */
    @Autowired
    private SessionFactory sessionFactory;

    /**
    * {@inheritDoc}
    */
    @Override
    public Long save(EntityA entityA) {
        return (Long) sessionFactory.getCurrentSession().save(entityA);
    }
}


I have a very simple code to try and save EntityA which is:

@Autowired
EntityARepositoryImpl entityARepositoryImpl;

EntityA entityA = new EntityA();
EntityB_Special entityBSpecial = new EntityB_Special();
EntityC_Special entityCSpecial = new EntityC_Special();

entityCSpecial.setxxx
...
entityBSpecial.setEntityC(entityCSpecial);

entityBSpecial.setName("A very long value");
...
entityA.setEntityB(entityBSpecial);

entityARepositoryImpl.save(entityA);

Lets say the user enters a very long value for the "name" field in entityB and there is an exception.

The exception thrown is as follows:

org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Transaction set to rollback only

...

10-12-28 14:48:00,600 [http-8080-2] Unexpected error in beforeCompletion:
org.hibernate.exception.DataException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:102)

....

Caused by: java.sql.BatchUpdateException: Data truncation: Data too long for column 'name' at row 1
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)

....

The issue is when I check the tables, Entity A and Entity B tables have no data but Entity C's data has been committed resulting in a partial commit eventhough the transaction has rolled back. This is similar to an issue raised by another post:

default82df.html?community.6.542.11

However this issue still persists. I am using version 3.6.6 of the atomikos release. I have attached the transaction log.

Please help.

Thanks

Dilshan
dilshan thambawita Send private email
Thursday, December 30, 2010
 
 
Transaction log:

10-12-28 14:31:07,407 [main] Starting read of logfile D:\Software\apache-tomcat-6.0.29\logs\entityTmlog86.log
10-12-28 14:31:07,407 [main] Done read of logfile
10-12-28 14:31:07,408 [main] Logfile closed: D:\Software\apache-tomcat-6.0.29\logs\entityTmlog86.log
10-12-28 14:34:57,716 [http-8080-6] Unexpected error in beforeCompletion:
org.hibernate.exception.DataException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:102)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
    at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114)
    at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
    at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2395)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2858)
    at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:267)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:259)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:178)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
    at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:88)
    at com.atomikos.icatch.jta.Sync2Sync.beforeCompletion(Sync2Sync.java:73)
    at com.atomikos.icatch.imp.TransactionStateHandler.commit(TransactionStateHandler.java:253)
    at com.atomikos.icatch.imp.CompositeTransactionImp.doCommit(CompositeTransactionImp.java:511)
    at com.atomikos.icatch.imp.CompositeTerminatorImp.commit(CompositeTerminatorImp.java:138)
    at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:317)
    at com.atomikos.icatch.jta.TransactionManagerImp.commit(TransactionManagerImp.java:613)
    at com.atomikos.icatch.jta.UserTransactionImp.commit(UserTransactionImp.java:168)
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1009)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy77.addNewStoreBasedOfferCampaign(Unknown Source)
    at entityARepositoryImpl.save(entityARepositoryImpl.java:5)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:244)
    at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1074)
    at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:955)
    at org.springframework.jmx.export.SpringModelMBean.invoke(SpringModelMBean.java:90)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:836)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761)
    at org.rydzewski.jmxconsole.action.CallOperationAction.doEexecute(CallOperationAction.java:48)
    at org.rydzewski.struts.action.BaseAction.execute(BaseAction.java:57)
    at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:53)
    at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:64)
    at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:48)
    at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
    at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:304)
    at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
    at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:280)
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1858)
    at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:459)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.rydzewski.common.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)
Caused by: java.sql.BatchUpdateException: Data truncation: Data too long for column 'name' at row 1
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)
    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1451)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 73 more
dilshan thambawita Send private email
Thursday, December 30, 2010
 
 
ehcache configuration:

 <defaultCache
                        maxElementsInMemory="10000"
                        memoryStoreEvictionPolicy="LRU"
                        eternal="false"
                        timeToIdleSeconds="120"
                        timeToLiveSeconds="120"
                        overflowToDisk="true"
                        diskSpoolBufferSizeMB="30"
                        maxElementsOnDisk="10000000"
                        diskPersistent="false"
                        diskExpiryThreadIntervalSeconds="120" >

        </defaultCache>

<cache name="somepackage.EntityA"
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="500"
        timeToLiveSeconds="5000"
        overflowToDisk="false"
        copyOnRead="false"
        copyOnWrite="false">

    </cache>

<cache name="somepackage.EntityB"
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="500"
        timeToLiveSeconds="5000"
        overflowToDisk="false"
        copyOnRead="false"
        copyOnWrite="false">

    </cache>

<cache name="somepackage.EntityC"
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="500"
        timeToLiveSeconds="5000"
        overflowToDisk="false"
        copyOnRead="false"
        copyOnWrite="false">

    </cache>
dilshan thambawita Send private email
Thursday, December 30, 2010
 
 
Hi,

Quoting your post: "Caused by: java.sql.BatchUpdateException: Data truncation: Data too long for column 'name' at row 1
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)"

This is a database issue...

HTH
Guy Pardon Send private email
Tuesday, January 04, 2011
 
 
But it should not insert any stuff into any of the tables if it fails (even its a database issue, might be a tx locking issue e.g. too) - the tx should rollback all changes made to all tables, right - shouldn't it?

@dilshan:
I tried to make a small test to verify your post - but hibernate does not even have success in creating the schema - your code postet seems to be wrong or incomplete.
Can you please make some "small!" maven2 test project which does show the problem? Let ehcache etc. out to make the case smallest as possible.
Torsten Krah Send private email
Tuesday, January 04, 2011
 
 
@Torsten: you have a point.

@dilshan: I think the problem might be JPA again: http://www.atomikos.com/Documentation/HibernateIntegration#With_JPA

HTH
Guy Pardon Send private email
Wednesday, January 05, 2011
 
 
Hi Guys,

Thank you for your feedback. I was able to resolve this issue. The issue was that I was using the Spring org.springframework.jdbc.datasource.DriverManagerDataSource with the atomikos transaction manager which was not correct.

I used the com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean instead and now things are working fine
dilshan thambawita Send private email
Tuesday, January 11, 2011
 
 
Thanks for the update!
Guy Pardon Send private email
Wednesday, January 12, 2011
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics