2011-05-12 6 views
1

Spring-JMS를 사용하면 DefaultMessageListenerContainer을 통해 외부 트랜잭션 컨텍스트 내에서 메시지를 수신 할 수 있습니다.TransactionManager를 사용하여 Spring JmsTemplate을 사용하여 메시지 작성

그러나 에 문서화 된 방법은 메시지가 JmsTemplate.send(…)를 통해 내가이 주어진 TransactionManager를 사용하도록 강제 할 수있는 방법을 볼 수 없습니다 물품.

누구나 올바른 방향으로 나를 가리킬 수 있습니까?


자세한 정보는 : 내가, 내가 아래의 조언을 의심 할 이유가 없다 동안 그래서

org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is oracle.jms.AQjmsException: could not use local transaction commit in a global transaction 
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316) 
    at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:168) 
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:469) 
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:534) 
Caused by: oracle.jms.AQjmsException: could not use local transaction commit in a global transaction 
    at oracle.jms.AQjmsSession.commitNoCheck(AQjmsSession.java:1053) 
    at oracle.jms.AQjmsSession.commit(AQjmsSession.java:1021) 
    at org.springframework.jms.support.JmsUtils.commitIfNecessary(JmsUtils.java:217) 
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:573) 
    at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:536) 
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:466) 
    ... 24 more 
Caused by: java.sql.SQLException: could not use local transaction commit in a global transaction 
    at oracle.jdbc.driver.PhysicalConnection.disallowGlobalTxnMode(PhysicalConnection.java:6647) 
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:3635) 
    at oracle.jdbc.driver.PhysicalConnection.commit(PhysicalConnection.java:3680) 
    at oracle.jdbc.OracleConnectionWrapper.commit(OracleConnectionWrapper.java:133) 
    at oracle.jms.AQjmsSession.commitNoCheck(AQjmsSession.java:1049) 
    ... 29 more 

: 트랜잭션 관리를 보장하는 것은에서 오라클 AQjmsFactory.getQueueConnectionFactory(dataSource) 결과에 대해 JmsTemplate.write를 사용하여, (WebSphereUowTransactionManager)로 볼 수 있습니다 AQ JMS가 커밋을 시도하지 못하게하는 방법을 파악할 수 없으므로 테스트 할 수 없습니다. 내가 더 배울수록 갱신 될 것이다.

답변

7

제 생각에 JMS 프로듀서는 이며 본질적으로 JTA를 통해이 처리됩니다. JMS MessageProducer을 통해 메시지를 보내면 스레드 로컬 JTA 트랜잭션이 사용됩니다 (존재하는 경우).

은 스프링 가이드 ( section 21.2.5)에 의해 암시된다

JmsTemplate 또한 분산 트랜잭션을 수행하기위한 JtaTransactionManager 및 XA 가능 JMS ConnectionFactory 함께 사용될 수있다. 이 작업을 수행하려면 JTA 트랜잭션 관리자와 적절하게 XA가 구성된 ConnectionFactory을 사용해야합니다. 는 JMS 세션을 만들 때 사용되는 트랜잭션 모드를 설정

:

JmsAccessor.setSessionTransacted ( JmsTemplate의 슈퍼 클래스) ( javadoc)에 의해 제안된다. 기본값은 "false"입니다. JTA 트랜잭션 내에서 create(Queue/Topic)Session(boolean transacted, int acknowledgeMode) 메소드에 전달 된 매개 변수는 고려되지 않습니다. J2EE 트랜잭션 컨텍스트에 따라 컨테이너는 이러한 값에 대해 자체 결정을 내립니다. 마찬가지로이 매개 변수는 로컬 관리되는 트랜잭션 내에서 고려되지 않습니다.이 경우 접근자가 기존 JMS 세션에서 작동하기 때문입니다.

이 플래그를 "true"로 설정하면 관리되는 트랜잭션 외부에서 실행될 때 간단한 로컬 JMS ​​트랜잭션이 사용되며 관리되는 트랜잭션 (XA 트랜잭션 제외)이 존재할 경우 동기화 된 로컬 JMS ​​트랜잭션이 사용됩니다. 후자는 기본 트랜잭션 바로 다음에 커밋되는 JMS 트랜잭션을 사용하여 기본 트랜잭션 (기본 JDBC 트랜잭션 일 수 있음)과 함께 관리되는 로컬 JMS ​​트랜잭션의 영향을받습니다.

그래서으로 (즉 JtaTransactionManager와 Spring의 트랜잭션 API를 사용하여)와 JmsTemplate.send(...)를 호출하면 트랜잭션에 바인딩 메시지를 보내는됩니다 JTA 트랜잭션을 시작합니다.

+0

감사합니다. Spring이 다른 비 Spring 프로세스에 의해 시작될 때 Spring은 트랜잭션을 찾을 수 있습니까? 내일 알게 될거야 ... – Synesso

+1

@ 시니 오네 : 네, 그렇습니다.JTA 트랜잭션은 Spring이 아닌 컨테이너에 의해 관리된다. – skaffman

관련 문제