문제

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

그러나 문서화된 유일한 방법은 쓰다 메시지가 왔어요 JmsTemplate.send(…) 그리고 이것이 어떻게 주어진 것을 사용하도록 강제될 수 있는지 알 수 없습니다. TransactionManager.

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


더 많은 정보:트랜잭션 관리자가 사용 가능한지 확인(WebSphereUowTransactionManager), 사용 JmsTemplate.write 오라클을 상대로 AQjmsFactory.getQueueConnectionFactory(dataSource) 결과는 다음과 같습니다.

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

따라서 아래 조언을 의심할 이유가 없지만 AQ JMS가 커밋을 시도하지 않도록 하는 방법을 알 수 없기 때문에 테스트할 수 없습니다.자세한 내용은 업데이트하겠습니다.

도움이 되었습니까?

해결책

내가 이해한 바에 따르면 JMS 제작자는 본질적으로 JTA를 통해 거래되었습니다.JMS를 통해 메시지를 보내면 MessageProducer, 스레드 로컬 JTA 트랜잭션이 사용됩니다(있는 경우).

이는 Spring 매뉴얼(섹션 21.2.5):

JmsTemplate 와 함께 사용할 수도 있습니다. JtaTransactionManager XA 가능 JMS ConnectionFactory 분산 트랜잭션을 수행하기 위한 것입니다.이를 위해서는 JTA 트랜잭션 관리자와 적절하게 구성된 XA 트랜잭션 관리자를 사용해야 합니다. ConnectionFactory.

이는 또한 다음과 같이 제안됩니다. JmsAccessor.setSessionTransacted (수퍼클래스 JmsTemplate) (javadoc):

JMS 세션을 생성할 때 사용되는 트랜잭션 모드를 설정합니다.기본값은 "거짓"입니다. JTA 트랜잭션 내에서 전달된 매개변수는 create(Queue/Topic)Session(boolean transacted, int acknowledgeMode) 방법은 고려되지 않습니다.J2EE 트랜잭션 컨텍스트에 따라 컨테이너는 이러한 값에 대해 자체적으로 결정을 내립니다. 마찬가지로, 이 경우 접근자가 기존 JMS 세션에서 작동하기 때문에 이러한 매개변수는 로컬로 관리되는 트랜잭션 내에서도 고려되지 않습니다.

이 플래그를 "true"로 설정하면 관리되는 트랜잭션 외부에서 실행될 때 짧은 로컬 JMS ​​트랜잭션을 사용하고, 관리되는 트랜잭션(XA 트랜잭션 제외)이 있는 경우 동기화된 로컬 JMS ​​트랜잭션을 사용합니다.후자는 기본 트랜잭션(네이티브 JDBC 트랜잭션일 수 있음)과 함께 관리되는 로컬 JMS ​​트랜잭션의 효과를 가지며, JMS 트랜잭션은 기본 트랜잭션 바로 다음에 커밋됩니다.

따라서 JTA 트랜잭션을 시작하여(예:Spring의 트랜잭션 API를 사용하여 JtaTransactionManager) 그리고 전화 JmsTemplate.send(...), 해당 트랜잭션에 바인딩된 메시지를 보내게 됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top