Tomcat 7, Bitronix, Spring JTA, JPA

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Tomcat 7, Bitronix, Spring JTA, JPA

Mathrusse, Chris (SFO-CAD)
I've got Tomcat 7 configured with Bitronix successfully. I also have my DataSource configured and bound into Tomcat's JNDI.

My application is using JPA, (EclipseLink specifically)  and Spring. I have my persistence.xml defined as follows:

<persistence-unit name="totaltag-pu" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/totalTagDataSource</jta-data-source>

I have things wired together in Spring and it loads the JPA context successfully but the problem is that when I wire things together, per the Spring documentation with the following values:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emf"/>
</bean>

  <bean id="emf"

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

</bean>   


I get the following exception from BTM, telling me that the datasource cannot be used outside of an XA transaction. 

 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.

This makes sense because the JpaTransactionManager is not supporting JTA.

But if I change my Spring TX Manager configuration to be the following:

    <tx:jta-transaction-manager/>

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

When I perform an operation on the EntityManager and it flushes I get BTM telling me that there are no resources enlisted.
Jul 26, 2012 4:03:10 PM bitronix.tm.twopc.Preparer prepare
WARNING: executing transaction with 0 enlisted resource

This tells me that the Transaction Manager is being used correctly but the DataSource is not getting enlisted in the transaction. 

So what is the correct configuration? I can't seem to figure out how to pull the two pieces together correctly.

Thanks for the help...
Chris




------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Chris Mathrusse | Senior Software Developer
653 Front Street, San Francisco, CA  94111 
| o:  415.262.3340  |  f:  415.274.8242 email: [hidden email]
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## iidwfi ##
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

pastedGraphic.pdf (14K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Tomcat 7, Bitronix, Spring JTA, JPA

Ludovic Orban-2
I suppose you need to configure EclipseLink to make use of the
transaction manager.

Since EclipseLink doesn't support BTM out of the box, you'll have to
create subclasses of these two classes:

http://www.eclipse.org/eclipselink/api/2.3/org/eclipse/persistence/platform/server/ServerPlatformBase.html
http://www.eclipse.org/eclipselink/api/2.3/org/eclipse/persistence/transaction/JTATransactionController.html

and configure EclipseLink to use them with a persistence unit
property, like this:

<property name="toplink.server.platform.class.name"
value="YOUR_SERVER_PLATFORM"/>


I'm not sure this will solve your problem but as I've never used
EclipseLink nor heard of any user reporting that he successfully used
it, we'll probably have to grope a bit in the dark here.

Spring definitely isn't helping as its abstractions provide a load of
confusion when setting up a new project so I would advise your to
first try to make EclipseLink work without Spring before integrating
the two together.


On Fri, Jul 27, 2012 at 1:11 AM, Mathrusse, Chris (SFO-CAD)
<[hidden email]> wrote:

> I've got Tomcat 7 configured with Bitronix successfully. I also have my
> DataSource configured and bound into Tomcat's JNDI.
>
> My application is using JPA, (EclipseLink specifically)  and Spring. I have
> my persistence.xml defined as follows:
>
> <persistence-unit name="totaltag-pu" transaction-type="JTA">
> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
>         <jta-data-source>jdbc/totalTagDataSource</jta-data-source>
>
> I have things wired together in Spring and it loads the JPA context
> successfully but the problem is that when I wire things together, per the
> Spring documentation with the following values:
>
> <bean id="transactionManager"
> class="org.springframework.orm.jpa.JpaTransactionManager">
>     <property name="entityManagerFactory" ref="emf"/>
> </bean>
>
>   <bean id="emf"
>
> class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
> <property name="persistenceXmlLocation"
> value="classpath:META-INF/persistence.xml" />
>
> </bean>
>
>
> I get the following exception from BTM, telling me that the datasource
> cannot be used outside of an XA transaction.
>
>  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.
>
> This makes sense because the JpaTransactionManager is not supporting JTA.
>
> But if I change my Spring TX Manager configuration to be the following:
>
>     <tx:jta-transaction-manager/>
>
> <bean id="emf"
> class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
> <property name="persistenceXmlLocation"
> value="classpath:META-INF/persistence.xml" />
> </bean>
>
> When I perform an operation on the EntityManager and it flushes I get BTM
> telling me that there are no resources enlisted.
> Jul 26, 2012 4:03:10 PM bitronix.tm.twopc.Preparer prepare
> WARNING: executing transaction with 0 enlisted resource
>
> This tells me that the Transaction Manager is being used correctly but the
> DataSource is not getting enlisted in the transaction.
>
> So what is the correct configuration? I can't seem to figure out how to pull
> the two pieces together correctly.
>
> Thanks for the help...
> Chris
>
>
>
>
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> Chris Mathrusse | Senior Software Developer
> 653 Front Street, San Francisco, CA  94111
> | o:  415.262.3340  |  f:  415.274.8242 | email: [hidden email]
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> ## iidwfi ##
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>     http://xircles.codehaus.org/manage_email
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Tomcat 7, Bitronix, Spring JTA, JPA

Mathrusse, Chris (SFO-CAD)
Hi Ludovic,

I managed to get things working with very little effort. So here is the run down:

Tomcat 7.0 configured per the BTM documentation.
DataSource defined in <TOMCAT_HOME>/conf/context.xml

    <Resource name="jdbc/myDataSource" auth="Container" type="javax.sql.DataSource"
                factory="bitronix.tm.resource.ResourceObjectFactory" uniqueName="jdbc/myDataSource" />


The application's web.xml file:

  <resource-ref>
    <res-ref-name>jdbc/myDataSource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
  </resource-ref>  



The application's persistence.xml file:
<persistence-unit name="my-pu" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/myDataSource</jta-data-source>
        <properties>
            <property name="eclipselink.session.customizer" value="com.cadreon.it.persistence.provider.JPAEclipseLinkSessionCustomizer" />
            <property name="eclipselink.target-server" value="org.eclipse.persistence.platform.server.tomcat.TomcatServer"/>
</properties>

The Spring applicationContext.xml file:
    <tx:annotation-driven transaction-manager="jtaTransactionManager" />

    

    <bean id="jtaTransactionManager"
    class="org.springframework.transaction.jta.JtaTransactionManager" autowire="constructor" >
        <property name="userTransactionName" value="java:comp/UserTransaction"/>
    </bean>

   


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



And lastly, I did need to implement several classes so that EclipseLink would have access to the TransactionManager, as noted above in the persistence.xml file:
I had to implement the JPAEclipseLinkSessionCustomizer as documented on the EclipseLink wiki : http://wiki.eclipse.org/EclipseLink/Examples/JPA/Tomcat_Web_Tutorial

I next had to implement a JTATransactionController that EclipseLink uses to acquire the TransactionManager.

public class TomcatTransactionController extends JTATransactionController {
    @Override
    protected TransactionManager acquireTransactionManager() throws Exception {
        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()); 
            }
        }      
        return mgr;
    } 
}


And the last class that I implemented was one that extends ServerPlatformBase the from EclipseLink.
The TomcatServer class can reside within any package that you like, but I followed the packaging standard set forth by EclipseLink.

public class TomcatServer extends ServerPlatformBase {

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

    @SuppressWarnings("rawtypes")
    @Override
    public Class getExternalTransactionControllerClass() {
        if (externalTransactionControllerClass == null) {
            externalTransactionControllerClass = TomcatTransactionController.class;
        }
        return externalTransactionControllerClass;
    }
}

That's it. Once I completed these steps EclipseLink was able to access BTM and everything worked.

Thanks for the assistance...
Chris



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

pastedGraphic.pdf (14K) Download Attachment
ATT00001.htm (8K) Download Attachment