Signal a rollback from a JMS MessageListener

后端 未结 3 1592
粉色の甜心
粉色の甜心 2021-02-05 19:28

I\'ve been working with JMS and ActiveMQ. Everything is working wonders. I am not using spring, nor can I.

The interface javax.jms.MessageListener has only

相关标签:
3条回答
  • 2021-02-05 19:49

    You need to set the acknowledgment mode to Session.CLIENT_ACKNOWLEDGE, the client acknowledges a consumed message by calling the message's acknowledge method.

    QueueSession session = connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);

    Then, after processing the message to need to call the Message.acknowledge() method in order to remove that message.

    Message message = ...;
    // Processing message
    
    message.acknowledge();
    
    0 讨论(0)
  • 2021-02-05 20:02

    If you want to use SESSION_TRANSACTED as your acknowledgement mode, then you need to setup a RedeliveryPolicy on your Connection/ConnectionFactory. This page on ActiveMQ's website also contains some good info for what you might need to do.

    Since you aren't using Spring, you can setup a RedeliveryPolicy with something similar to the following code (taken from one of the above links):

    RedeliveryPolicy policy = connection.getRedeliveryPolicy();
    policy.setInitialRedeliveryDelay(500);
    policy.setBackOffMultiplier(2);
    policy.setUseExponentialBackOff(true);
    policy.setMaximumRedeliveries(2);
    

    Edit Taking your code snippet added to the answer, the following shows how this works with transactions. Try this code with the Session.rollback() method commented out and you'll see that using SESION_TRANSACTED and Session.commit/rollback works as expected:

    @Test
    public void test() throws Exception {
        final AtomicInteger atomicInteger = new AtomicInteger(0);
    
        BrokerService brokerService = new BrokerService();
    
        String bindAddress = "vm://localhost";
        brokerService.addConnector(bindAddress);
        brokerService.setPersistenceAdapter(new MemoryPersistenceAdapter());
        brokerService.setUseJmx(false);
        brokerService.start();
    
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(bindAddress);
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        redeliveryPolicy.setInitialRedeliveryDelay(500);
        redeliveryPolicy.setBackOffMultiplier(2);
        redeliveryPolicy.setUseExponentialBackOff(true);
        redeliveryPolicy.setMaximumRedeliveries(2);
    
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        activeMQConnectionFactory.setUseRetroactiveConsumer(true);
        activeMQConnectionFactory.setClientIDPrefix("ID");
    
        PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(activeMQConnectionFactory);
    
        pooledConnectionFactory.start();
    
        Connection connection = pooledConnectionFactory.createConnection();
        final Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
        Queue helloQueue = session.createQueue("Hello");
        MessageConsumer consumer = session.createConsumer(helloQueue);
        consumer.setMessageListener(new MessageListener() {
    
            public void onMessage(Message message) {
                TextMessage textMessage = (TextMessage) message;
                try {
                    switch (atomicInteger.getAndIncrement()) {
                        case 0:
                            System.out.println("OK, first message received " + textMessage.getText());
                            session.commit();
                            break;
                        case 1:
                            System.out.println("NOPE, second must be retried " + textMessage.getText());
                            session.rollback();
                            throw new RuntimeException("I failed, aaaaah");
                        case 2:
                            System.out.println("OK, second message received " + textMessage.getText());
                            session.commit();
                    }
                } catch (JMSException e) {
                    e.printStackTrace(System.out);
                }
            }
        });
        connection.start();
    
        {
            // A client sends two messages...
            Connection connection1 = pooledConnectionFactory.createConnection();
            Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            connection1.start();
    
            MessageProducer producer = session1.createProducer(helloQueue);
            producer.send(session1.createTextMessage("Hello World 1"));
            producer.send(session1.createTextMessage("Hello World 2"));
    
            producer.close();
            session1.close();
            connection1.stop();
            connection1.close();
        }
        JOptionPane.showInputDialog("I will wait, you watch the log...");
    
        consumer.close();
        session.close();
        connection.stop();
        connection.close();
        pooledConnectionFactory.stop();
    
        assertEquals(3, atomicInteger.get());
    }
    

    }

    0 讨论(0)
  • 2021-02-05 20:09

    If your session is transacted,then "acknowledgeMode" is ignored anyways..So, just leave your session transacted and use session.rollback and session.commit to commit or rollback your transaction.

    0 讨论(0)
提交回复
热议问题