Problem with Transaction Management [message #899460] |
Tue, 31 July 2012 23:59 ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Eclipse User![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=) |
|
|
|
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 #900225 is a reply to message #899671] |
Sun, 05 August 2012 19:12 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Eclipse User![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=) |
|
|
|
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 Go to previous message](theme/Solstice/images/up.png) |
Eclipse User![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=) |
|
|
|
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?
|
|
|
Powered by
FUDForum. Page generated in 0.04949 seconds