2012-01-23 69 views
2

我有一个运行在Websphere内部的应用程序,并且我遇到了持久化JPA实体的问题。Spring,Websphere,JMS和Eclipselink问题

此前,该应用程序是建立与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队列的消息驱动指针进行调用。我可以通过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队列中取出,但没有数据。

有什么建议吗?

回答

1

我终于得到了这个工作,并认为我会发布答案。

实际上有2件拼图。

首先,在WebSphere中,你需要到你的应用服务器 - > TransactionService,检查/启用“接受启发式危险”复选框。这肯定有帮助。我正在为7

的第二件事,就是你必须设置属性eclipselink.target服务器的持久性单元或您的EntityManagerFactory上。

那第二个项目绝对是诀窍。我测试了财产,没有它。没有它,没有任何东西存在。有了它,一切正常。

这里是我的EntityManagerFactory,我使用的是属性占位符设置eclipselink.target服务器属性的值:

<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>