3

要件:onMessage()正常に実行されるまでメッセージをキューに保持したい。の実行中に何らかの例外が発生しonMessage()、それがハンドルされていない場合、メッセージはリスナーに再配信される必要があります。

アプリケーション サーバーとして Glassfish v2 を使用しています。OpenMQConnectionFactory と JmsTemplate を使用してメッセージをキューに送信しています。 私は MDB を使用していないことに注意してください。

<bean id="openMQConnectionFactory"
    class="com.is.br.util.OpenMqConnectionFactoryBean">
    <property name="imqAddressList" value="mq://localhost:7676" />
    <property name="imqDefaultUsername" value="admin" />
    <property name="imqDefaultPassword" value="admin" />
</bean>

応答モードとして AUTO_ACKNOWLEDGE を試しましたが、例外がスローされたメッセージが再配信されないときにリスナーで試しました。

MessageProducer.java

public void sendMessage(最終文字列 responseStream) {

    System.out.println("Enter into IsJmsProducer.sendMessage method");

    try {
        MessageCreator creator = new MessageCreator() {
            public Message createMessage(Session session) {
                ObjectMessage message = null;
                try {
                    message = session.createObjectMessage(responseStream);
                    } catch (Exception e) {
                    System.out.println("Unable create a JMSMessage");
                }
                return message;
            }
        };

        System.out.println("Sending message to destination: " + this.destination.toString());
        this.jmsTemplate.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE);

        this.jmsTemplate.send(this.destination, creator);
        System.out.println("SendMessage to queue successfully.");           
    } catch (Exception ex) {
        System.out.println("SendMessage to queue Fail." + ex);
    }
    System.out.println("Exit from IsJmsProducer.sendMessage method");

}

サンプルJMSConsumer.java

public class SampleJMSConsumer implements MessageListener {

    @Override
    public void onMessage(Message message) {
        throw new RuntimeException();
   }
}

次にthis.jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);、私が呼び出したリスナーで 試してみましたが、まだメッセージを呼び出しmessage.acknowledge();catchブロックで再配信されません。session.recover()

サンプルJMSConsumer.java

public class SampleJMSConsumer implements MessageListener  {

    @Override
    public void onMessage(Message message) {

        ObjectMessage objectMessage = (ObjectMessage) message;
        Object object;
        try {
            object = objectMessage.getObject();
            if (object instanceof String) {
                System.out.println("Message received - " + object.toString());
                throw new JMSException("JMS exception");
            }
            message.acknowledge();
        } catch (JMSException e) {
               session.recover();
        }
    }

}

プログラムをデバッグ モードで実行し、ブローカ管理コンソールのキューでメッセージを送信すると、メッセージの数を確認できますが、onMessage() が呼び出されるとすぐに、メッセージの数が 1 つ減ります。つまり、メッセージが消費され、キューから削除されます。そのメッセージは「配信済み」と見なされますか? 例外が発生したときにメッセージが再配信されない理由を理解してください。

前もって感謝します。

4

4 に答える 4

1

Client Acknowledge はあなたに適しています。onMessage() メソッドでは、処理が終了したら、Acknowledge を呼び出す必要があります。それ以外の場合は、例外がある場合は Acknowledge() を呼び出しません。

Session.Recovery() は、メッセージ配信を停止して再開します。メッセージの配信は、最後の未確認メッセージから行われます。

于 2012-07-16T07:23:55.287 に答える
1

これは設計によるもので、onmessage が呼び出されたときに配信されると思います。例外について何かしたい場合は、try catch を使用して処理できます。

メッセージが再びキューに入れられたと仮定すると、とにかく消費されたときに同じ例外が発生する可能性があります。

ack メカニズムは、正しい配信を保証するものでなければなりません。おそらく、あなたが求めているのは、プロデューサー側に新しいメッセージを送信するように依頼する拒否メカニズムですか?

于 2012-07-16T06:42:44.713 に答える
0

コンシューマーで作成されたセッションは、セッション モードを AUTO_ACK / DUPS_OK_ACK に設定する必要があります。コンシューマーを開始するためのコードを共有していません。Producer でセッション モードを設定していますが、Consumer では設定していません。

于 2014-08-20T13:14:09.947 に答える
0

OpenMQ のデフォルトのセッション モードを確認することをお勧めします。接続を開くと変更できない場合があるため、接続を開くときに指定する必要があります。

于 2012-07-16T07:06:55.247 に答える