Spring, Websphere, JMS и Eclipselink Issue - PullRequest
       37

Spring, Websphere, JMS и Eclipselink Issue

2 голосов
/ 24 января 2012

У меня есть приложение, которое работает внутри 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
  }

Я работаю над усовершенствованием приложения, которое позволит выполнять вызовы через управляемый сообщениями Pojo, связанный с Websphere Queue.Через 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> 

Не уверен, что есть проблема с моей настройкой Spring, но я получаю сообщения через моего 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 Ответ

1 голос
/ 24 января 2012

Я наконец-то все заработал и решил опубликовать ответ.

На самом деле головоломка состоит из двух частей.

Во-первых, в Websphere вам нужно перейти к своему приложению.сервер -> TransactionService и отметьте / включите флажок «Принять эвристическую опасность».Это определенно помогло.Я использую WAS 7.

Во-вторых, вы ДОЛЖНЫ установить свойство eclipselink.target-server в вашем устройстве персистентности или в EntityManagerFactory.

Этот второй предмет определенно добился цели.Я проверял со свойством и без него.Без этого ничего не сохраняется.С этим все работает нормально.

Вот мой 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>
...