2013-08-27 2 views
1

TemporaryQueue를 통해 다른 모듈의 MDB와 메시지를 동기식으로 교환해야하는 EJB 모듈이 있습니다. EJB 컨테이너 (제 경우에는 Glassfish 4.0 임)는 트랜잭션 환경을 가정하고 BEAN 관리 트랜잭션을 사용해야하며 UserTransaction 객체를 사용하여 트랜잭션의 시작과 끝을 표시해야합니다.트랜잭션 환경의 JMS 요청/응답 패턴

내 코드의 외형이 같다 :

@Stateless 
@TransactionManagement(TransactionManagementType.BEAN) 
public class CommunicationJMSUtils { 
    @Resource 
    private UserTransaction ut; 
    @Inject 
    private JMSContext context; 
    @Resource(lookup = "jms/DestinationQueue") 
    private Queue destination; 
    private static final long JMS_COMMUNICATION_TIMEOUT = 5000; 

    public Map<String, String> getClientordersData(String id) throws JMSException { 

    try { 
      MapMessage mm = context.createMapMessage(); 
      ut.begin(); 
      TemporaryQueue replyQueue = context.createTemporaryQueue(); 

      mm.setJMSReplyTo(replyQueue); 

      mm.setStringProperty(<...>); 
      <...> 
      mm.setString(<...>); 
      <...> 

      context.createProducer().send(destination, mm); 
      ut.commit(); 

      ut.begin(); 
      ObjectMessage om = (ObjectMessage) context.createConsumer(replyQueue).receive(JMS_COMMUNICATION_TIMEOUT); 
      ut.commit(); 

      if (om != null) { 
       return om.getBody(Map.class); 
      } else { 
       throw new JMSException("Failed to receive reply within " + JMS_COMMUNICATION_TIMEOUT); 
      } 
     } catch (NotSupportedException | RollbackException | HeuristicMixedException | HeuristicRollbackException | SecurityException | IllegalStateException | SystemException ex) { 
     <...> 
     } 
    } 
} 

첫 번째 문제는 때때로이 코드 (수신 부분)이다 제외

MQJMSRA_DS4001: _checkDestination:Temporary Destination not owned by parent connectionId=1760697170479431168 

분명히 TemporaryQueue 생성되지만 실패 같은 JMSContext를 사용합니다.

두 번째 문제는이 코드의 "취약성"입니다. 첫 번째 트랜잭션 내에 context.createMapMessage()를 두거나 첫 번째 트랜잭션에서 TemporaryQueue를 이동하면이 스 니펫은 확실히 실패합니다.

유감스럽게도 JMS 자습서/문서는 실제로 해당 사용 사례를 다루지 않습니다. Java EE에서 JMS 2.0을 사용하여 JMS 요청/응답 패턴을 구현하는 올바른 방법은 무엇입니까?

답변

1
  • 동기 행동과 메시지로, 어떻게 든 JMS 충돌을 사용하여 (비동기식) 메시징은 자연에 의해 비동기 적입니다. JMS를 사용하는 대신 메서드를 호출합니다 (예 : 로컬 또는 원격 EJB). 무 상태 세션 빈과 MDB는 동일한 기능 (서비스 클래스)을 호출 할 수 있지만 두 가지 유형의 인터페이스 (동기화 & async).

  • 심지어 메소드를 호출하기위한 임시 큐를 작성,이 복잡성을 추가하지 않습니다 (이 문제를 일으키는).

  • UserTransaction

  • 모든 작업에 걸쳐해야한다. begincommit (및 rollback) 중 하나만 있어야합니다. 실제 트랜잭션 경계를 볼 수 없지만 첫 번째 TX의 리소스는 두 번째 TX ( replyQueue)에 사용됩니다. 임시 대기열이 첫 번째 commit 중에 삭제 될 것으로 예상됩니다.

  • 아마 관련 :는 "거래 장벽"으로 TransactionManagementType.BEAN 행위 가진 EJB. 그래서 그 대신 내가 동일한 기능을 제공하는 무 상태 세션 빈을 추가 건의 트랜잭션 처리를 고정 Why do EJB beans with bean-managed transactions act as a “transacation barrier”? here

,이 하나 (동기)를 호출 : 그것은 아마도 현재 트랜잭션을 중단합니다. 이 경우 컨테이너 관리 트랜잭션에서 작동하지 않아야하는 이유를 알지 못하므로 빈 경계를 넘어 실제로 트랜잭션이 발생합니다.

+0

비동기 메시징은 모듈 간 특정 인터페이스가 없도록 선택되었습니다. 나는 리모트 인터페이스가 같은 방법으로 어느 정도 사용될 수 있다는 것을 알고있다. 트랜잭션 간의 리소스 공유는 실제 문제이며 (일반적으로이 질문의 이유입니다). 참고 자료에서는 JMS를 사용하여 동기식 교환 패턴을 찾을 수 있지만 명확한 구현 예는 찾을 수 없습니다. 답장을 보내 주셔서 감사합니다. 건축 설계를 재고해야한다고 생각합니다. – vsviridov

+0

빈 관리 트랜잭션을 사용해야하는 이유는 분명하지 않습니다.비즈니스 메소드에서 다양한 트랜잭션에 대한 세분화 된 제어가 필요한 경우가 아니라면 컨테이너가 트랜잭션을 관리하도록하는 것이 좋습니다. –

+0

@IanEvans 귀하의 의견은 OP를위한 것 같습니다. 어쨌든 내 대답은 BMT의 일반적인 측면만을 다룹니다. 제안/결론은 또 다른 설계입니다 (CMT는이 경우 잘되어야합니다). – Beryllium

관련 문제