2014-12-05 3 views
1

봄, 최대 절전 모드 및 JMS를 사용하여 tomee에 배포하는 매우 간단한 응용 프로그램을 빌드하는 데 어려움을 겪고 있습니다. 나는 모든 구성이 정확하다고 믿는다. (mysql xa 데이터 소스와 xa 활성 mq 연결 팩토리를 가지고있다.) 그러나 기대했던대로 작동하지 않는다. 현재는 삽입 된 엔티티 관리자를 사용하여 쓰는 간단한 서비스가 있습니다. 그런 다음 트랜잭션 방식으로 주석 처리 된 하나의 메소드 (예 : 스프링 주석)에서 JMS에 푸시하지만 트랜잭션이 봄에 커밋되기 전에 내 메시지 수신기가 이러한 메시지를 전달 중입니다.Spring + tomee JTA 트랜잭션

JMS 템플릿과 xa 연결 팩토리를 직접 사용해 보았지만 제대로 작동하지 않았습니다. 템플리트는 jndi에서 수신 한 jta 트랜잭션 관리자로 구성됩니다. JMS가 전송하는 이유에 대한 힌트를 찾기 위해 데이터베이스에서 쓰는 것과 동일한 트랜잭션에 참여하지 않는 아이디어는 무엇입니까?

봄 구성 : 나는이 JmsTemplate와 XAConnectionFactory를 사용하지 않는 등 여러 가지 방법을 시도했습니다

<Resource id="ActiveMQResourceAdapter" type="ActiveMQResourceAdapter"> 
    BrokerXmlConfig=broker:(vm://localhost) 
</Resource> 

<Resource id="resources/jms/ConnectionFactory" type="javax.jms.ConnectionFactory"> 
    ResourceAdapter = ActiveMQResourceAdapter 
</Resource> 

<Resource id="resources/jms/XAConnectionFactory" class-name="org.apache.activemq.ActiveMQXAConnectionFactory"> 
    BrokerURL = vm://localhost 
    ResourceAdapter = ActiveMQResourceAdapter 
</Resource> 

<Resource id="resources/jms/PrintQueue" type="javax.jms.Queue"/> 
<Resource id="resources/jms/PersistQueue" type="javax.jms.Queue"/> 

<Resource id="MySQL Database" type="DataSource"> 
    JdbcDriver com.mysql.jdbc.jdbc2.optional.MysqlXADataSource 
    JdbcUrl jdbc:mysql://localhost/test 
    UserName test 
</Resource> 

(http://tomee-openejb.979440.n4.nabble.com/MDB-doesn-t-read-messages-td4666169.html에서 함께 자갈길)

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:encryption="http://www.jasypt.org/schema/encryption" 
    xmlns:jms="http://www.springframework.org/schema/jms" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
              http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd 
              http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
              http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd 
              http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd 
              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
              http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
              http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd 
              http://www.jasypt.org/schema/encryption http://www.jasypt.org/schema/encryption/jasypt-spring31-encryption-1.xsd 
              http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd" 
    default-autowire="byType" default-lazy-init="false"> 

    <context:component-scan annotation-config="false" base-package="org.superbiz" /> 

    <bean class="org.springframework.orm.jpa.DefaultJpaDialect" /> 
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> 

    <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" /> 
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> 
    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"> 
      <property name="alwaysUseJndiLookup" value="false" /> 
      <property name="jndiFactory" > 
        <ref local="jndiFactory"/> 
      </property> 
    </bean> 

    <bean id="jndiFactory" class="org.springframework.jndi.support.SimpleJndiBeanFactory"> 
      <property name="resourceRef" value="true" /> 
    </bean> 

    <bean id="PrintTemplate" class="org.springframework.jms.core.JmsTemplate"> 
      <property name="connectionFactory"> 
        <ref local="jmsFactory" /> 
      </property> 
      <property name="defaultDestinationName" value="resources/jms/PrintQueue" /> 
      <property name="deliveryPersistent" value="true"/> 
      <!-- <property name="sessionTransacted" value="true"/> --> 
      <!-- <property name="sessionAcknowledgeMode" value="0"/> --> 
    </bean> 

    <bean id="PersistTemplate" class="org.springframework.jms.core.JmsTemplate"> 
      <property name="connectionFactory"> 
        <ref local="jmsFactory" /> 
      </property> 
      <property name="defaultDestinationName" value="resources/jms/PersistQueue" /> 
      <property name="deliveryPersistent" value="true"/> 
      <!-- <property name="sessionTransacted" value="true"/> --> 
      <!-- <property name="sessionAcknowledgeMode" value="0"/> --> 
    </bean> 

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"> 
      <property name="defaultPersistenceUnitName" value="movie-unit" /> 
      <property name="persistenceContexts"> 
        <map> 
          <entry key="movie-unit" value="persistence/movie-unit" /> 
        </map> 
      </property> 
    </bean> 

    <context:component-scan base-package="org.superbiz.ejb" annotation-config="false"> 
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 
    </context:component-scan> 

    <jee:jndi-lookup id="jmsFactory" jndi-name="resources/jms/ConnectionFactory" expected-type="javax.jms.ConnectionFactory" /> 

    <tx:jta-transaction-manager /> 

    <tx:annotation-driven transaction-manager="transactionManager"/> 

    <bean id="printBean" class="org.superbiz.mdb.PrintBean"/> 
    <bean id="persistBean" class="org.superbiz.mdb.PersistBean"/> 

    <jms:listener-container container-type="default" connection-factory="jmsFactory" cache="none" transaction-manager="transactionManager" concurrency="1" receive-timeout="1000" prefetch="-1"> 
      <jms:listener destination="resources/jms/PrintQueue" ref="printBean" /> 
      <jms:listener destination="resources/jms/PersistQueue" ref="persistBean" /> 
    </jms:listener-container> 

</beans> 

tomee.xml이 sessionTransacted되도록 구성하고 아니, JMSTemplate을 제거하고 connectionFactory에서 connection/session/producer/message를 만들지 만 매번 문제가 발생했습니다. ConnectionFactory에서 연결/세션/생성자/메시지를 수동으로 생성하면 데이터베이스에 쓰려고하는 20 개의 항목이 서비스 트랜잭션이 완료되기 전에 다른 JMS 대기열로 보내지는 것을 알 수 있습니다.

나는 모든 것이 올바르게 구성되었다고 말할 수있는 한 (비록 이것이 많은 부분에서 나온 것이므로 분명히 틀릴 수도 있지만). 내 목표는 수동으로 연결/세션/etc를 직접 작성하는 대신 JMSTemplate을 사용할 수있게하는 것이지만,이 시점에서 왜 이런 일이 일어나고 있는지를 놓치고있어 어떤 아이디어라도 크게 감사 할 것입니다.

또한 최대 봄 JtaTransactionManager를 로깅을 충돌했고 나는하여 @Transactional 방법은

DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.superbiz.ejb.Movies.send]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '' 
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit 

그런 다음 나는 내 MDB의 코드에서 항목을 검색하려는 참조 호출 될 때 일어나는 다음을 참조 entityManager (간헐적으로 작동/실패 함). 그것은 내가 더이 경우 로깅

[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#1]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 

**bold** [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#0]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 

[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization 

[org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization 

[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [[email protected]] for key [[email protected]] to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] 

[org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [[email protected]] for key [[email protected]] to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] 

[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Participating in existing transaction 
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Getting transaction for [org.superbiz.mdb.PersistBean.onMessage] 
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [[email protected]] for key [[email protected]] bound to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] 
Persisted finished, but not yet committed 
Leaving persist, should commit 
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [org.superbiz.mdb.PersistBean.onMessage] 
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.jta.JtaTransactionManager - Triggering beforeCommit synchronization 
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.jta.JtaTransactionManager - Triggering beforeCompletion synchronization 
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [[email protected]] for key [[email protected]] from thread [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] 
**bold** [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit 

Entering print 
/***************** BROKEN ***************/ 
/*******************597852*****************/ 
/***************** BROKEN ***************/ 

을 마약 한

/***************** BROKEN ***************/ 
/*******************435265*****************/ 
/***************** BROKEN ***************/ 
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit 
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#0]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 

이 DefaultMessageListenerContainer 번호 1-1가 볼 실패하면 나는이

printing from MDB: director: director0title: title0year: 0 
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit 
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#0]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 

를 참조 성공하면 내 Persist bean과 0-1은 id로 엔티티를 검색 한 다음 내용을 인쇄하는 bean입니다.

이 글을 읽는 방법을 100 % 확신 할 수는 없지만, DMLC# 1-1에서 새로운 트랜잭션이 시작된 후에 DMLC# 1-1이 잘 커밋한다는 것은 흥미 롭습니다. 메시지. DMLC# 0-1이 엔터티를 데이터베이스에 보관해야하는 JMS 메시지를 받았기 때문에이 OR을 확인하기 위해 새 트랜잭션을 시작해야한다고 생각했을 것입니다.내 지속 콩 @Override @Transactional 공공 무효의 onMessage (메시지 메시지) { 끝난 TextMessage MSG = (끝난 TextMessage) 메시지의

내용; int x; tomee/lib 디렉토리에 추가 필요한 최대 절전 항아리와 바닐라 Tomee 1.7.1을 실행하는 내 인쇄 빈

public void onMessage(Message message) { 
    System.out.println("Entering print"); 
    final TextMessage textMessage = (TextMessage) message; 

    try { 
     long id = Long.parseLong(textMessage.getText()); 
     Movie movie = entityManager.find(Movie.class, id); 
     if(movie == null){ 
      System.out.println("/***************** BROKEN ***************/"); 
      System.out.println("/*******************" + id + "*****************/"); 
      System.out.println("/***************** BROKEN ***************/"); 

     } else { 
      System.out.println("updating: "+ movie); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

} 

전체 응용 프로그램이 https://github.com/jej2003/simple-spring에서 사용할 수의

try { 
     x = Integer.parseInt(msg.getText()); 
     Movie movie = new Movie("director" + x, "title" + x, x); 
     entityManager.persist(movie); 
     final long id = movie.getId(); 
     template.send(new MessageCreator() { 
      @Override 
      public Message createMessage(Session session) throws JMSException { 
       return session.createTextMessage(Long.toString(id)); 
      } 
     }); 
     System.out.println("Persisted finished, but not yet committed"); 
     System.out.println("Leaving persist, should commit"); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

} 

내용.

저는 정말로 여기를 잃었습니다. 아무도 Spring과 Tomee에서 JTA 트랜잭션을 실행할 수 없습니까?

+0

이와 같은 질문을 할 때 구성을 보여주고 더 많은 정보를 제공해야합니다 - "... 제대로 작동하지 않습니다 ..."그리고 그러한 주석은 그냥 잘라 내지 않습니다. 죄송합니다. 또한'TRACE' 로깅을 켜면 많은 정보가 노출됩니다. 'TRACE' 로그에서 그걸 알아낼 수 없다면, 어딘가에 게시하십시오. –

답변

0

많은 디버깅 후 JTA 구현에 실패가 아니라 JTA에 대한 전반적인 이해가 더 많았습니다. JTA는 두 트랜잭션이 모두 성공적으로 커밋되도록 보장하지만 트랜잭션의 순서는 분명히 시행하지 않습니다. 대답은 궁극적으로 스테판 니콜의 https://jira.spring.io/browse/SPR-12535에 제공되었습니다.

관련 문제