2011-12-07 11 views
3

JMSメッセージの送信とJTAトランザクションを同期する必要があります - クライアントJTAトランザクションコミット後にMDBをアクティブにする必要があります。 これはXAConnectionFactoryを使用すると可能ですが、私の例では機能しません。JTAトランザクションがコミットされる前のJMSメッセージのMDBアクティベーション

例のシナリオ:

  • Webサービスクライアントはコードでメッセージを送る= 0
  • MDBがメッセージ及びプリント受け取る:START:コード(NEW JTAトランザクション)
  • MDB増分コードと印刷:SEND: %コード+
  • MDBは新しいコード値でmessagを送って1%
  • のmdb睡眠
  • mdbファイルの印刷:ENDコード
  • MDB仕上げ(トランザクションがCOMMIT)

シナリオは、私は結果を期待コード< 10まで繰り返しである:

START: 0 
SEND: 1 
END: 0 
START: 1 
SEND: 2 
END: 1 
START: 2 
SEND: 3 
END: 2 
etc.. 

が、現在私が手:

... 
START: 4 
SEND: 5 
END: 3 
START: 5 
SEND: 6 
END: 4 
START: 6 
SEND: 7 
END: 5 
END: 6 

マイコード:

  • Webサービスクライアント

    @WebMethod 
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void publish() { 
        TestQueueUtil.sendToQueue(0); 
    } 
    
  • TestQueueUtil(JMSクライアント)

    public static void sendToQueue(Integer code) { 
        InitialContext initialContext; 
        XAQueueConnection queueConnection = null; 
        XAQueueSession queueSession = null; 
    
        try { 
        Hashtable env = new Hashtable(); 
        env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); 
        initialContext = new InitialContext(env); 
        XAConnectionFactory queueConnectionFactory = (XAConnectionFactory) initialContext.lookup("jms/dsk/ConnectionFactoryXA"); 
    
        queueConnection = (XAQueueConnection) queueConnectionFactory.createXAConnection(); 
        queueConnection.start(); 
    
        queueSession = queueConnection.createXAQueueSession(); 
        Queue queue = (Queue) initialContext.lookup("jms/dsk/TestQueue"); 
    
        //QueueSender sender = 
        MessageProducer producer = queueSession.createProducer(queue); 
        Message jmsMessage = queueSession.createMessage(); 
    
        jmsMessage.setIntProperty("code", code); 
        producer.send(jmsMessage); 
        producer.close(); 
        queueConnection.stop(); 
    
    } catch (Exception e) { 
        throw new RuntimeException("sendToQueue", e); 
    } finally { 
        if (queueSession != null) { 
         try { 
          queueSession.close(); 
         } catch (Exception e) { 
          //ignore 
         } 
        } 
        if (queueConnection != null) { 
         try { 
          queueConnection.close(); 
         } catch (Exception e) { 
          //ignore 
         } 
        } 
        } 
    
    } 
    
  • 私が間違って何TestQueueMDB

    @MessageDriven(mappedName = "jms/dsk/TestQueue", activationConfig = { 
         @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), 
         @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") 
    }) 
    public class TestQueueMDB implements MessageListener { 
    
        @Resource 
        protected MessageDrivenContext messageDrivenContext; 
    
        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
        public void onMessage(Message message) { 
         Integer code = null; 
         try { 
    
          code = message.getIntProperty("code"); 
          System.out.println("START: " + code); 
          if (code < 10) { 
           Integer newcode = code + 1; 
           System.out.println("SEND: " + newcode); 
           TestQueueUtil.sendToQueue(newcode); 
           Thread.sleep(2000); 
          } 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } finally { 
          System.out.println("END: " + code); 
         } 
        } 
    } 
    

答えて

4

MDBにトランザクションコンテキストがないことがわかりました。

私は

weblogic.transaction.TxHelper.getTransactionId() 

ヌル受信、およびmessageDrivenContext.getRollbackOnlyを(コールを呼び出すことにより、トランザクションIDをチェックする)ことを除い

java.lang.IllegalStateException: [EJB:010156]Illegal attempt to call EJBContext.getRollbackOnly() from an EJB that was not participating in a transaction. 

理由は、注釈

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 

た取得しますそれを取り外したり交換した後に

@TransactionAttribute(TransactionAttributeType.REQUIRED) 

すべて正常です。

:)

+0

これらは非常に奇妙な症状です。MDBがNOT_SUPPORTEDまたはREQUIREDトランザクションアノテーションのみを許可するのは事実ですが、REQUIRES_NEWを黙って無視するよりも、デプロイ時に例外がスローされると思います。それでも、興味深いフォローアップのために+1。 – MaDa

関連する問題