Spring + Websphere 8.5: невозможно найти имя JNDI [java:comp/websphere/ExtendedJTATransaction]

Существует Websphere AS 8.5, в котором работает XA Datasource. Также есть приложение Spring, которое должно работать в этой среде и подключаться к источнику данных. Контекст приложения загружается сервлетом, и приложение использует RmiExporters для предоставления доступа RMI к некоторым службам (которые совместно используются в отдельном потоке), а все методы DAO отмечены @Transactional.

Если я пытаюсь что-то записать в базу данных из основного потока (например, во время инициализации любого класса), это работает правильно. Но если я пытаюсь написать (или прочитать с помощью HQL SELECT-запроса) что-то через вызов RMI, я вижу исключение:

org.hibernate.service.jndi.JndiException: Unable to lookup JNDI name [java:comp/websphere/ExtendedJTATransaction]
at org.hibernate.service.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:68)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter$TransactionAdapter.<init>(WebSphereExtendedJtaPlatform.java:156)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter$TransactionAdapter.<init>(WebSphereExtendedJtaPlatform.java:152)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.getTransaction(WebSphereExtendedJtaPlatform.java:124)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.getStatus(WebSphereExtendedJtaPlatform.java:119)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115)
at org.hibernate.service.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy.canRegisterSynchronization(TransactionManagerBasedSynchronizationStrategy.java:56)
at org.hibernate.service.jta.platform.internal.AbstractJtaPlatform.canRegisterSynchronization(AbstractJtaPlatform.java:148)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.attemptToRegisterJtaSync(TransactionCoordinatorImpl.java:240)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.pulse(TransactionCoordinatorImpl.java:268)
at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1202)
at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:178)
at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:179)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:174)
at com.ibm.ws.jpa.management.JPAEMFactory.createEntityManager(JPAEMFactory.java:297)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:202)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:211)
at com.sun.proxy.$Proxy414.persist(Unknown Source)

Реальная конфигурация следующая:

блок сохранения в файле persistence.xml:

<provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/oracledatasource</jta-data-source>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
        <property name="hibernate.archive.autodetection" value="class" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.format_sql" value="true" />
        <property name="connection.pool.size" value="5" />
        <property name="current_session_context_class" value="managed" />
        <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
        <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory" />
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
        <property name="hibernate.cache.use_second_level_cache" value="false" />
        <property name="hibernate.cache.use_query_cache" value="false" />
        <property name="hibernate.generate_statistics" value="true" />
        <property name="hibernate.enable_lazy_load_no_trans" value="true" />
    </properties>

Конфигурация весны выглядит так:

<tx:jta-transaction-manager />
<tx:annotation-driven />

<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
    <property name="persistenceUnits">
        <map>
            <entry key="pu1" value="persistence/pu1" />
        </map>
    </property>
</bean>
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/pu1"/>

Что я могу попытаться исправить эту проблему?


person darkled    schedule 21.06.2013    source источник
comment
Есть ли вложенное исключение из Hibernate, которое показывает, какая проблема возникла на самом деле? Можете ли вы изменить код, чтобы добавить дополнительную диагностику?   -  person Brett Kail    schedule 22.06.2013
comment
Нет, это была настоящая ошибка. Диагностика показывает, что java:comp/websphere/ExtendedJTATransaction живет в потоке, которым управляет контейнер JavaEE (в данном случае Websphere), а RmiExpoter живет в другом потоке, где нет контекста с такого рода транзакциями. Надеюсь пока хватит.   -  person darkled    schedule 24.06.2013
comment
Ах, в вашем объяснении мне не хватало тонкости неосновного потока. Я недостаточно знаю о Spring/Hibernate, чтобы знать, существует ли исправление, но я бы предложил изменить код Hibernate, чтобы выполнить поиск из основного потока, а затем сохранить объект ExtendedJTATransaction.   -  person Brett Kail    schedule 24.06.2013


Ответы (1)


Фактическое решение состояло в том, чтобы использовать JPATransactionManager Spring с LOCAL_RESOURCE блоком персистентности.

person darkled    schedule 18.07.2013