4

Queue から ObjectMessage を受け取り、その情報を使用して JPA エンティティ オブジェクトを設定および永続化する onMessage メソッドがあります。しかし、エンティティ オブジェクトの永続化中に何か問題が発生すると、onMessage() が再実行されます。私の推測では、ObjectMessage をキューに押し戻しているため、onmessage が再び実行されています。このままでは無限ループに陥ります。onMessage() を停止して再度実行したり、実行回数を制御したりするにはどうすればよいですか。これが私が持っているコードです。saveAuditData(auditInfo) でエラーが発生しています。

public void onMessage(Message inMessage) {
   log.debug("Entering onMessage() Method.");
   AuditInfo auditInfo = null;
   try {
       ObjectMessage om = (ObjectMessage) inMessage;  
       auditInfo = (AuditInfo) om.getObject();
       log.debug("Message received : " + auditInfo.getApiUsed());
       log.debug("Calling saveAuditData().");
       saveAuditData(auditInfo);
       log.debug("Leaving onMessage() Method.");
   }
   catch (Exception e) {
       e.printStackTrace();
       log.debug("Error persisting Audit Info.",e);
       log.debug("Printing Audit Info:");
       log.debug(auditInfo.toString());
   }

}
private void saveAuditData(AuditInfo auditInfo) {
    log.debug("Entering saveAuditData() Method.");
    log.debug("Populating Audit Object.");
    IdmAudit idmAudit = new IdmAudit();
    idmAudit.setApiUsed("API");
    idmAudit.setAppClientIpAddress("localhost");
    idmAudit.setAuditActivity("activity1");
    idmAudit.setAuditData(auditInfo.getAuditData());
    idmAudit.setAuditGroup(AUDIT_GROUP);
    idmAudit.setAuditType("Type");
    idmAudit.setIdmAuditCreationDate(new Date());
    idmAudit.setLocationCd("Location");
    idmAudit.setPurgeDate(null);
    idmAudit.setSubscriberId(new BigDecimal(0));
    idmAudit.setSuccessInd("Y");
    idmAudit.setUserId(new BigDecimal(0));
    idmAudit.setAuditSource("Source");
    idmAudit.setVersionNumber(new BigDecimal(0));

    log.debug("Saving Audit.");
    entityManager.persist(idmAudit);
    entityManager.flush();
    log.debug("Leaving saveAuditData() Method.");
}
4

2 に答える 2

8

JMS メッセージを処理するためにコンテナー管理トランザクションがコンテナーによって開始されると、JDBC 接続で障害が発生したり、スレッドでスローされた例外が発生したりすると、グローバル XA トランザクションがロールバックされます。そのため、メッセージはキューに戻り、キューの構成 (再試行間の期間、メッセージを配信不能キューに移動する前の最大再試行回数) に従って後で再試行されます。

したがって、次のオプションがあります。

  • MDB デプロイメント記述子で「Bean 管理」トランザクション モードを選択し、ルックアップからjava:comp/UserTransaction呼び出しbeginまで、commitまたはrollback手動で UserTransaction を使用するので、例外処理に注意してください。

  • 「コンテナー管理」トランザクションを保持しますが、JMS メッセージの再配信カウント プロパティをクエリして、次に何をすべきかを決定します。失敗する可能性があるものを再試行するか、この手順をスキップしてデータベースにデータを保存します。JMS プロバイダーからメッセージの再配信情報を取得できます Message.getJMSRedelivered()Message.getLongProperty("JMSXDeliveryCount")

  • または、デプロイメント記述子saveAuditDataでトランザクションをサポートする EJB StatelessBean にメソッドを移動RequiresNewして、新しいトランザクションが作成され、MDB トランザクションに何が起こってもデータが保存されるようにします。このオプションは、前のオプションと組み合わせることができます。

于 2011-05-04T10:29:09.563 に答える