1

메시지 (WAS 7.0, Java EE 5, EJB 3.0, JPA)에 대한 작업을 수행하는 MDB 및 일련의 상태 비 저장 EJB가 있습니다. (CMT를 사용하여)EJB 3.0 - CMT를 사용한 트랜잭션 독립적 인 EJB 호출 시퀀스

순서 :

  • MDB가 수락 메시지
  • MDB는
  • EJB1 함께 작업의 일부를 수행, 메시지와 함께 엔티티가
  • MDB는 EJB 1 통과 개체 ID를 호출 세부 계속 EJB1 성공 여부에 따라 메시지
  • ID를 전달하는 EJB2 또는 EJB5
  • EJB2는 EJB2를 수행합니다. ...

등 마지막 EJB (실행 시간은 몇 분)까지.

모든 트랜잭션은 하나의 트랜잭션에서 발생합니다. 따라서 EJB4에서 무언가가 발생하면이 트랜잭션에서 이전에 발생한 모든 것이 롤백됩니다. 모든 후속 호출에 REQUIRES_NEW를 사용하려고했지만 후속 호출에서 이전 호출의 변경 내용이 보이지 않는 것으로 보입니다. 또한 트랜잭션이 길어지고 때로는 시간이 초과됩니다. I는 별도의 독립적 인 트랜잭션을하려는

: EJB2

  • C 처리 EJB1에

    • , 수신 및 지속 메시지
    • B 처리 ... 그래서 EJB2의 실행이 실패하면 메시지가 DB에 남아 있어야하고 EJB1에서 실행 결과가 지속되어야합니다. 그것은 짧은과 시퀀스 indipendent 거래를 할 수 있습니다 -

      그래서 주요 문제는 CMT를 사용하여 무엇입니까?

      • 는 트랜잭션이 MDB에서 독립적으로 의 커밋 될 발신 한 수 더 일부 EJB1에 대한 호출의 결과? 더욱 - EJB1에 을 호출하기 전에 커밋되었습니다.?
      • REQUIRES_NEW 속성을 가진 EJB1 메소드 호출 내에서 MDB 내부에서 작성된 엔티티가 변경 될 수 있습니까?
      • 목표를 달성하기 위해 BTM 또는 WorkManager를 제외한 다른 방법이 있습니까?
  • 답변

    1

    REQUIRES_NEW에 문제가 없어야합니다.

    이 있던 경우 : 그냥 하나의 경고로 (TM)를 작동해야

    @EJB(..) 
    EJB1 ejb1; 
    @EJB(..) 
    EJB2 ejb2; 
    
    public void onMessage(Message message) { 
        Thing thing = getThingFromMessage(message); 
    
        persistThingStuff(thing); 
        ejb1.doThingStuffWithRequiresNew(thing); 
        ejb2.doThingStuffWithRequiresNew(thing); 
    } 
    

    .

    ejb2가 예외를 throw하면 ejb1의 작업은 커밋되지만 persistThingStuff는 롤백됩니다.

    하지만 당신은 뭔가를 할 경우 :

    public void onMessage(Message message) { 
        Thing thing = getThingFromMessage(message); 
    
        persistThingStuff(thing); 
        ejb1.doThingStuffWithRequiresNew(thing); 
        try { 
         ejb2.doThingStuffWithRequiresNew(thing); 
        } catch (Throwable t) { 
         youBetterLogThis(); 
        } 
    } 
    
    EJB2가 장기 실행 인 경우 그러나, MDB에 의해 수행 모든 작업이 아직 보류 및에되면, MDB의 작업을 불어에서 예외를 방지해야

    그것을 기다리는 열린 거래.

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public <T extends Runnable> T runInTransaction(T runner) { 
        runner.run(); 
        return runner; 
    } 
    

    그런 다음 우리는 반드시 이에 대한 구체적인 방법에 주석을 달 필요가 없습니다 :

    이 일을 많이 해결하기 위해, 우리는 유틸리티 EJB 기능을 가지고있다.

    이렇게하면 EJB1 이전에도 즉시 MDB 작업이 커밋됩니다.

    +0

    >> "EJB2가 오래 실행 중이면 MDB에서 수행 한 모든 작업이 아직 보류 중이고 열린 트랜잭션에서 대기 중입니다."--- 제안 된 접근 방식이 마음에 들지만 MDB 트랜잭션은 호출 to ejb1과 ejb2는 끝나기 때문에 doThingStuffWithRequiresNew 호출은 상대적으로 짧지 만 주요 변환은 여전히 ​​길다. 어떻게 든 비동기 ejbs에 대한 호출을하고 싶습니다. WorkManager? – aillusions

    +0

    이 경로를 사용할 수 있지만 MDB 작업이 커밋되고 EJB1이 커밋되면 EJB2에 대해 걱정할 필요가 없습니다. 다른 스레드와 마찬가지로 현재 MDB 스레드를 사용합니다. 그래서, 기본적으로, 당신은 이미 새로운 일없이 "자유로운"것을 얻고 있습니다. 트랜잭션을 JMS 서버에 보관하지만 메시지를 즉시 확인하고 트랜잭션을 기다리지 않고 수정할 수 있습니다 (MDB의 구성 옵션). –

    +0

    예, persistThingStuff()가 성공적으로 완료된 경우에만 JMS 서버에서 안전하게 메시지를 가져와야합니다. 나머지 로직은 그다지 중요하지 않습니다. 어떤 assync 알림, 심지어 다른 JMS 메시지, 지속 MDB 및 처리 EJB 사이에있을 가치가 보인다. 당신의 도움을 많이 주셔서 감사합니다! – aillusions