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, без необходимости в двух разных файлах конфигурации?

Ответ 1

Я думаю, вы пропустили точку JNDI. JNDI был в значительной степени написан для решения вашей проблемы!

Я думаю, вы можете подняться на уровень, поэтому вместо использования "userTransaction" или "transactionManager from JNDI" в зависимости от вашей ситуации. Почему бы не добавить "JtaTransactionManager" в JNDI. Таким образом вы нажимаете конфигурацию на JNDI, где она должна быть вместо создания еще большего количества файлов конфигурации [вроде этого уже недостаточно;)].

Ответ 2

Вы можете использовать PropertyConfigurerPlaceholder для ввода ссылок bean, а также простых значений.

Например, если вы вызываете свои beans "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>

Затем вы можете обменять менеджеров транзакций с помощью

  • transaction.strategy = jotm в файле свойств
  • -Dtransaction.strategy = jotm как системное свойство

Это один из возможных подходов. Для более полного примера см. blog.

Надеюсь, что это поможет.

Ответ 3

Если вы используете Spring 2.5, вы можете использовать < tx: jta-transaction-manager/ > . Я не использовал его с JBoss, но он должен работать для вас в соответствии с разделом 9.8. Интеграция с конкретным сервером приложений из справочного руководства Spring.

Ответ 4

Подход <tx:jta-transaction-manager/> будет искать менеджера транзакций в нескольких местах по умолчанию перечисленных здесь. Если ваш менеджер транзакций JBoss не находится в одном из этих мест, я предлагаю вам переместить его, если это возможно, или переместить его в Tomcat, чтобы оба контейнера имели свой TM в том же местоположении JNDI.

Ответ 5

Просто добавив свой опыт, чтобы не переусердствовать снова.

Как сказали bmatthews68, Chochos и эти плакаты, используйте <tx:jta-transaction-manager/> в вашем файле Spring bean; он определенно обеспечивает соответствующий уровень абстракции, и нет необходимости делать что-либо дополнительно на стороне Spring.

Что касается Tomcat, я объявил <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> в файле default/shared conf/context.xml, который привязывается к java:comp/UserTransaction. Поскольку это одно из мест, поиск которых осуществляется с помощью Spring, вам не нужно ничего делать.

Один из них: хотя, как и я, вы используете Maven, убедитесь, что вы исключаете какие-либо зависимости в банке javax.transaction:jta или задаете область действия provided. В противном случае вы столкнетесь с проблемами загрузчика классов.