在调用onMessage()时,在JMS异步消息处理中,消息从队列中删除

时间:2012-07-16 06:10:37

标签: java jms messagebroker openmq

要求:我希望消息在队列中持久存在,直到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(final String 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");

}

SampleJMSConsumer.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()仍然消息不是重新发送。

SampleJMSConsumer.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()调用的消息数量减少了一个。这意味着消息被消耗并从队列中删除。该消息是否被视为“已交付”?  请帮助我理解为什么在发生异常时邮件不是重新发送的?

提前致谢。

4 个答案:

答案 0 :(得分:1)

我认为这是设计的,当onmessage被调用时会传递。如果你想对异常做一些事情,你可以使用try catch来处理它。

假设消息再次被放入队列,你可能会在消费时遇到同样的异常。

ack机制应该是关于确保正确交付。也许你所追求的是拒绝机制,你要求prpoducerside发送新消息?

答案 1 :(得分:1)

客户确认适合您。在onMessage()方法中,一旦处理结束,你需要调用Acknowledge,否则如果有任何异常,则不要调用Acknowledge()。

Session.Recovery()停止并重新启动邮件传递。消息的传递将来自最后一条未确认的消息。

答案 2 :(得分:0)

我建议验证OpenMQ的默认会话模式是什么。可能会发生这种情况,一旦您打开连接,您就无法对其进行更改,因此必须在连接打开时指定。

答案 3 :(得分:0)

在使用者中创建的

会话应将会话模式设置为AUTO_ACK / DUPS_OK_ACK。您尚未共享启动消费者的代码。您正在生产者中设置会话模式,但不是消费者。