我有一个在Websphere内部运行的应用程序,我遇到了持久化JPA实体的问题。
以前,应用程序使用RESOURCE_LOCAL持久性单元,Spring JpaTransactionManager以及在代码中显式提交的事务进行设置。
TransactionStatus transactionStatus = transactionManager.getTransaction( new DefaultTransactionDefinition() );
try {
entityManager.persist( someJpaEntity );
}
catch( Exception exception ) {
transactionManager.rollback( transactionStatus );
throw exception;
}
try {
transactionManager.commit( transactionStatus );
}
catch( TransactionException exception ) {
exception
}
我正在开发一个应用程序增强功能,允许通过链接到Websphere队列的Message Driven Pojo进行调用。我能够通过spring设置配置,允许我的应用程序通过JMS队列接收消息。 spring配置看起来像:
<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="QueueConnectionFactory"/>
<jee:jndi-lookup id="jmsQueue" jndi-name="DIQueue" />
<!-- A dynamic resolver -->
<bean id="jmsDestResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"/>
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="jmsConnectionFactory"/>
</property>
<property name="destinationResolver">
<ref bean="jmsDestResolver"/>
</property>
</bean>
<bean id="messageListener" class="my.app.FileMessageListener" />
<bean id="exListener" class="my.app.JmsExceptionListener" />
<bean id="msgListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="destination" ref="jmsQueue" />
<property name="messageListener" ref="messageListener" />
<property name="transactionManager" ref="transactionManager" />
<property name="taskExecutor" ref="myTaskExecutor" />
<property name="exceptionListener" ref="exListener" />
</bean>
<bean id="myTaskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
</bean>
不确定我的弹簧设置是否存在问题,但我确实通过我的Active MQ代理接收消息,因此我觉得这部分很好。
现在,问题是,当我通过JMS收到消息时,我会调用上面的代码来插入JPA实体。当代码运行时,我会得到消息“无法在两阶段事务中提交单相资源”或类似的东西。我明白的是Spring JpaTransactionManager不能用于XA或JTA事务。
所以,我努力转移到Spring JtaTransactionManager。
我改变了我能想到的所有东西来使用JTA,这是我宣布我的交易经理的地方:
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
更新了我的持久性XML:
<persistence-unit name="AppUnit" transaction-type="JTA">
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<jta-data-source>java:APPDS</jta-data-source>
然而,没有任何作用。我的代码运行无例外,但没有任何内容持久存储到数据库中。消息从JMS队列中删除,但没有数据。
有什么建议吗?
答案 0 :(得分:1)
我终于有了这个工作,并且认为我会发布答案。
这个拼图实际上有2件。
首先,在Websphere中,您需要转到您的应用服务器 - &gt; TransactionService,并选中“Accept Heuristic Hazard”复选框。这肯定有帮助。我正在运行WAS 7。
第二件事是,您必须在持久性单元或EntityManagerFactory上设置属性eclipselink.target-server。
第二项绝对可以解决问题。我测试了属性,没有它。没有它,没有任何东西持续存在有了它,一切正常。
这是我的EntityManagerFactory,我使用属性占位符来设置eclipselink.target-server属性的值:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="MyUnit" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform">
<value>${app.databasePlatform}</value>
</property>
<property name="showSql">
<value>${app.showSql}</value>
</property>
</bean>
</property>
<!-- THIS DID THE TRICK -->
<property name="jpaPropertyMap">
<map>
<entry key="eclipselink.target-server" value="${app.targetServer}"/>
</map>
</property>
</bean>