Конфигурация Spring JTA TransactionManager: поддержка Tomcat и JBoss
У меня есть веб-приложение, использующее JPA и JTA с Spring. Я хотел бы поддержать как JBoss, так и Tomcat. При работе на JBoss я хотел бы использовать собственный TransactionManager JBoss, а при работе на Tomcat я хотел бы использовать JOTM.
У меня оба сценария работают, но теперь я обнаружил, что мне нужны две отдельные конфигурации Spring для двух случаев. С JOTM мне нужно использовать Spring JotmFactoryBean
:
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<bean class="org.springframework.transaction.jta.JotmFactoryBean"/>
</property>
</bean>
Однако в JBoss мне просто нужно получить "TransactionManager" из 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>
Есть ли способ настроить это так, чтобы использовать соответствующий TransactionManager - JBoss или JOTM - без необходимости двух разных файлов конфигурации?
5 ответов
Я думаю, что вы упустили из виду JNDI. JNDI была написана для решения вашей проблемы!
Я думаю, что вы можете поднять его на уровень, поэтому вместо использования "userTransaction" или "TransactionsManager from JNDI" в зависимости от вашей ситуации. Почему бы не добавить "JtaTransactionManager" в JNDI. Таким образом, вы перемещаете конфигурацию в JNDI, где она должна быть, вместо того, чтобы создавать еще больше файлов конфигурации [как будто их уже недостаточно;) ].
Вы можете использовать PropertyConfigurerPlaceholder для вставки ссылок на компоненты, а также простых значений.
Например, если вы называете ваши bean-компоненты "jotm" и "jboss", то вы можете ввести свою TM следующим образом:
<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>
Затем вы можете поменять менеджеров транзакций, используя
- транзакция.strategy=jotm в файле свойств
- -Dtransaction.strategy=jotm как системное свойство
Это один из возможных подходов. Смотрите мой блог для более полного примера.
Надеюсь это поможет.
Если вы используете Spring 2.5, вы можете использовать
<tx:jta-transaction-manager/>
подход будет искать менеджер транзакций в нескольких местах по умолчанию, перечисленных здесь. Если ваш менеджер транзакций JBoss находится не в одном из этих мест, я предлагаю вам переместить его, если это возможно, или переместить его в Tomcat, чтобы оба контейнера имели свои TM в одном и том же месте JNDI.
Просто добавив сюда свой опыт, чтобы мне больше не пришлось переживать его снова.
Как сказал bmatthews68, Чочос и эти авторы <tx:jta-transaction-manager/>
в вашем файле Spring bean; он определенно обеспечивает соответствующий уровень абстракции, и нет необходимости делать что-то дополнительное на стороне Spring.
Что касается Tomcat, я объявил <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" />
по умолчанию / общий conf/context.xml
файл, который привязывается к java:comp/UserTransaction
, Поскольку это одно из мест, которое ищет Spring, вам не нужно больше ничего делать.
Однако, есть одна проблема: если вы, как и я, используете Maven, убедитесь, что вы исключаете любые зависимости от javax.transaction:jta
банку или установите область действия provided
, В противном случае у вас будут проблемы с загрузчиком классов.