Spring JTA TransactionManager config: Supporting both Tomcat and JBoss

折月煮酒 提交于 2019-12-04 08:47:35

问题


I have a web application using JPA and JTA with Spring. I would like to support both JBoss and Tomcat. When running on JBoss, I'd like to use JBoss' own TransactionManager, and when running on Tomcat, I'd like to use JOTM.

I have both scenarios working, but I now find that I seem to need two separate Spring configurations for the two cases. With JOTM, I need to use Spring's JotmFactoryBean:

<bean id="transactionManager" 
 class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="userTransaction">
        <bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
    </property>
</bean>

In JBoss, though, I just need to fetch "TransactionManager" from JNDI:

<bean id="transactionManager" 
 class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager">
        <bean class="org.springframework.jndi.JndiObjectFactoryBean">
             <property name="resourceRef" value="true" />
             <property name="jndiName" value="TransactionManager" />
             <property name="expectedType" 
               value="javax.transaction.TransactionManager" />
        </bean>
    </property>
</bean>

Is there a way to configure this so that the appropriate TransactionManager - JBoss or JOTM - is used, without the need for two different configuration files?


回答1:


I think you have missed the point of JNDI. JNDI was pretty much written to solve the problem you have!

I think you can take it up a level, so instead of using the "userTransaction" or "transactionManager from JNDI" depending on your situation. Why not add the "JtaTransactionManager" to JNDI. That way you push the configuration to the JNDI where it is supposed to be instead of creating even more configuration files [ like there aren't enough already ;) ].




回答2:


You can use PropertyConfigurerPlaceholder to inject bean references as well as simple values.

For example if you call your beans 'jotm' and 'jboss' then you could inject your TM like:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE">
    <property name="location" value="classpath:/path/to/application.properties"/>
</bean>
<bean id="jotm">...</bean>
<bean id="jboss">...</bean>
<bean id="bean-requiring-transaction-manager">
    <property name="transactionManager" ref="${transaction.strategy}"/>
</bean>

Then you can swap transaction managers using

  • transaction.strategy=jotm in a properties file
  • -Dtransaction.strategy=jotm as a system property

This is one possible approach. See my blog for a more complete example.

Hope this helps.




回答3:


If you are using Spring 2.5 you can use <tx:jta-transaction-manager/>. I have not used it with JBoss but it should work for you according to section 9.8 Application server-specific integration from the Spring reference manual.




回答4:


The <tx:jta-transaction-manager/> approach will look for a transaction manager in several default locations listed here. If your JBoss transaction manager is not in one of those locations, I suggest you move it, if possible, or move it in Tomcat so that both containers have their TM in the same JNDI location.




回答5:


Just adding my experience here so I don't have to re-suffer the experience again.

As bmatthews68, Chochos and these posters have said, use <tx:jta-transaction-manager/> in your Spring bean file; it definitely provides the appropriate level of abstraction and there's no need to do anything extra on the Spring side.

As for Tomcat, I declared <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> in the default/shared conf/context.xml file, which binds to java:comp/UserTransaction. As this is one of the places searched for by Spring, you shouldn't need to do anything else.

One gotcha though: if like me you use Maven, make sure you exclude any dependencies on the javax.transaction:jta jar or set the scope to provided. Otherwise you will experience classloader issues.



来源:https://stackoverflow.com/questions/117751/spring-jta-transactionmanager-config-supporting-both-tomcat-and-jboss

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!