Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Problem with Transaction Management
Problem with Transaction Management [message #899460] Tue, 31 July 2012 23:59 Go to next message
Fericit Bostan is currently offline Fericit Bostan
Messages: 68
Registered: June 2010
Member
I'm using EclipseLink 2.4.0 in my project, which is a simple web base application running within Tomcat 7.0. I've deployed and configured Bitronix Transaction Manager into Tomcat per the documentation: http://docs.codehaus.org/display/BTM/Tomcat

and I've defined a datasource in Tomcat's JNDI that I can access via the application, Spring specifically.

I've got my persistence.xml as follows:
<?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="totaltag-pu" transaction-type="JTA">
		<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/totalTagDataSource</jta-data-source>
        <class>com.cadreon.it.totaltag.persistence.entity.AuditableEntity</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Advertiser</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Asset</class>
        <class>com.cadreon.it.totaltag.persistence.entity.DelayedJob</class>
        <class>com.cadreon.it.totaltag.persistence.entity.History</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Market</class>
        <class>com.cadreon.it.totaltag.persistence.entity.PixelProvider</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Pixel</class>
        <class>com.cadreon.it.totaltag.persistence.entity.S3LogLine</class>
        <class>com.cadreon.it.totaltag.persistence.entity.S3Log</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Segment</class>
        <class>com.cadreon.it.totaltag.persistence.entity.TotalTag</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Url</class>
        <class>com.cadreon.it.totaltag.persistence.entity.User</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Variable</class>
        <class>com.cadreon.it.totaltag.persistence.entity.Version</class>

		<shared-cache-mode>ALL</shared-cache-mode>

		<properties>
            <property name="eclipselink.cache.type.default" value="HardWeak" />
            <property name="eclipselink.cache.size.default" value="200" />
            <property name="eclipselink.flush-clear.cache" value="DropInvalidate" />

            <property name="eclipselink.jdbc.native-sql" value="true" />
            <property name="eclipselink.jdbc.cache-statements" value="true" />
            <property name="eclipselink.target-database" value="Auto" />
            <property name="eclipselink.weaving" value="static" />

            <property name="eclipselink.logging.exceptions" value="true" />
            <property name="eclipselink.logging.level" value="FINEST" />
            <property name="eclipselink.debug" value="ALL" />
            <property name="eclipselink.logging.level.sql" value="FINEST" />
            <property name="eclipselink.logging.level.cache" value="FINEST" />

            <property name="eclipselink.session.customizer" value="com.cadreon.it.totaltag.persistence.provider.JPAEclipseLinkSessionCustomizer" />
            <property name="eclipselink.target-server" value="org.eclipse.persistence.platform.server.tomcat.TomcatServer"/>
		</properties>

	</persistence-unit>
</persistence>


I've created a new Session Customizer, per the EclipseLink documentation, and a new ServerPlatform class.
public class TomcatServer extends ServerPlatformBase {
    private static final String SERVER_NAME_AND_VERSION =  "Tomcat v7.0";

    public TomcatServer(DatabaseSession newDatabaseSession) {
        super(newDatabaseSession);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.persistence.platform.server.ServerPlatformBase#getExternalTransactionControllerClass()
     */
    @SuppressWarnings("rawtypes")
    @Override
    public Class getExternalTransactionControllerClass() {
        if (externalTransactionControllerClass == null) {
            externalTransactionControllerClass = TomcatTransactionController.class;
        }

        return externalTransactionControllerClass;
    }

    /* (non-Javadoc)
     * @see org.eclipse.persistence.platform.server.ServerPlatformBase#getServerNameAndVersion()
     */
    @Override
    protected void initializeServerNameAndVersion() {        
        this.serverNameAndVersion = SERVER_NAME_AND_VERSION;
    }

}


My TransactionController class simply performed the lookup, via JNDI, to locate the TransactionManager:
public class TomcatTransactionController extends JTATransactionController {
    private static Logger logger = LoggerFactory.getLogger(TomcatTransactionController.class);

    public TomcatTransactionController() {
        super();
    }

    public TomcatTransactionController(TransactionManager transactionManager) {
        super(transactionManager);
    }

    /* (non-Javadoc)
     * @see org.eclipse.persistence.transaction.JTATransactionController#acquireTransactionManager()
     */
    @Override
    protected TransactionManager acquireTransactionManager() throws Exception {
        logger.debug("ENTERING: acquireTransactionManager");
        
        TransactionManager mgr = super.acquireTransactionManager();
        if(mgr == null) {
            try {
                // Bitronix binds to java:comp/UserTransaction within Tomcat.
                mgr = (TransactionManager) jndiLookup("java:comp/UserTransaction"); 
                
                setTransactionManager(mgr);
            }
            catch(Exception e) {
               logger.error(e.getMessage()); 
            }
        }
        
        logger.debug("EXITING: acquireTransactionManager");
        return mgr;
    } 
}


All the code executes as expected and seems to behave properly but when I attempt to access the database I get an exception from Bitronix, which tells me that I am attempting to access the datasource outside of a transaction.
Caused by: java.sql.SQLException: error enlisting a JdbcConnectionHandle of a JdbcPooledConnection from datasource jdbc/totalTagDataSource in state ACCESSIBLE with usage count 1 wrapping com.mysql.jdbc.jdbc2.optional.JDBC4MysqlXAConnection@66869470 on com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@1ae3e881
	at bitronix.tm.resource.jdbc.JdbcConnectionHandle.enlistResource(JdbcConnectionHandle.java:87)
	at bitronix.tm.resource.jdbc.JdbcConnectionHandle.prepareStatement(JdbcConnectionHandle.java:242)
	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 bitronix.tm.resource.jdbc.BaseProxyHandlerClass.invoke(BaseProxyHandlerClass.java:64)
	at $Proxy29.prepareStatement(Unknown Source)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1481)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1430)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:705)
	at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:587)
	... 84 more
Caused by: bitronix.tm.internal.BitronixSystemException: resource 'jdbc/totalTagDataSource' cannot be used outside XA transaction scope. Set allowLocalTransactions to true if you want to allow this and you know your resource supports this.
	at bitronix.tm.resource.common.TransactionContextHelper.enlistInCurrentTransaction(TransactionContextHelper.java:78)
	at bitronix.tm.resource.jdbc.JdbcConnectionHandle.enlistResource(JdbcConnectionHandle.java:85)
	... 95 more



I've defined my transactionManager in Spring as I would usually do and I've annotated my classes so that Spring will perform its transactionManager per the documentation:

	<context:annotation-config />
	<context:component-scan base-package="com.cadreon.it.totaltag" />

	<tx:jta-transaction-manager/>
	<tx:annotation-driven />

	<bean id="emf"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
	</bean>


But no matter what I try it appears that no transaction is started when accessing the DataSource. Is there something I am missing in EclipseLink or did I not implement something that I should have to allow for EclipseLink to participate in the Global TX?

Thanks for the assistance..
Chris
Re: Problem with Transaction Management [message #899671 is a reply to message #899460] Wed, 01 August 2012 18:08 Go to previous messageGo to next message
James Sutherland is currently offline James Sutherland
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Are you sure that Spring is starting a JTA transaction through your transaction manager before you are accessing JPA?

It seems that it does not. Try starting a JTA transaction directly.


James : Wiki : Book : Blog : Twitter
Re: Problem with Transaction Management [message #900225 is a reply to message #899671] Sun, 05 August 2012 19:12 Go to previous messageGo to next message
Fericit Bostan is currently offline Fericit Bostan
Messages: 68
Registered: June 2010
Member
I managed to identify the issue. It seems that I had a reference to embedded-glassfish container that was causing some class loading issues. Once I removed it as a dependency, I was able to identify the issues with the Spring TX configuration as well as some code that someone checked in that was attempting to perform DB access outside of a global TX. After correcting this the application loads and transactions behave normally.

Thanks for the help...
Re: Problem with Transaction Management [message #1130149 is a reply to message #900225] Wed, 09 October 2013 09:03 Go to previous message
Dheeraj Gupta is currently offline Dheeraj Gupta
Messages: 1
Registered: October 2013
Junior Member
Again facing the same exception "Internal Exception: java.sql.SQLException: error enlisting a JdbcConnectionHandle of a JdbcPooledConnection from datasource jdbc/totalTagDataSource in state ACCESSIBLE with usage count 1 wrapping". It seems that this exception is not consistent and we are getting this particularly when there are a large number of records to be processed.

Any pointers?
Previous Topic:second level cache without persistence.xml
Next Topic:How to create POJOs with JAXB and JPA Annotations from XSD?
Goto Forum:
  


Current Time: Thu Oct 23 13:51:26 GMT 2014

Powered by FUDForum. Page generated in 0.01665 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software