Java Can';无法让ActiveMQ重新发送我的消息

Java Can';无法让ActiveMQ重新发送我的消息,java,activemq,Java,Activemq,我有一个用Java编写的单线程ActiveMQ使用者。我要做的就是从队列中接收()消息,尝试将其发送到web服务,如果成功,则确认()。如果web服务调用失败,我希望消息留在队列中,并在超时后重新发送 除了重新发送部分,它或多或少都在工作:每次我重新启动我的消费者时,它都会收到一条仍然在队列中的消息,但在发送失败后,消息永远不会重新发送 我的代码如下所示: public boolean init() throws JMSException, FileNotFoundException, IOEx

我有一个用Java编写的单线程ActiveMQ使用者。我要做的就是从队列中接收()消息,尝试将其发送到web服务,如果成功,则确认()。如果web服务调用失败,我希望消息留在队列中,并在超时后重新发送

除了重新发送部分,它或多或少都在工作:每次我重新启动我的消费者时,它都会收到一条仍然在队列中的消息,但在发送失败后,消息永远不会重新发送

我的代码如下所示:

public boolean init() throws JMSException, FileNotFoundException, IOException {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
    RedeliveryPolicy policy = new RedeliveryPolicy();
    policy.setInitialRedeliveryDelay(500);
    policy.setBackOffMultiplier(2);
    policy.setUseExponentialBackOff(true);

    connectionFactory.setRedeliveryPolicy(policy);
    connectionFactory.setUseRetroactiveConsumer(true); // ????
    Connection connection = connectionFactory.createConnection();

    connection.setExceptionListener(this);
    connection.start();

    session = connection.createSession(transacted, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
    destination = session.createQueue(subject); //???

    consumer = session.createConsumer(destination);
    //consumer.setMessageListener(this); // message listener had same behaviour

}

private void process() {
    while(true) {
        System.out.println("Waiting...");
        try {
            Message message = consumer.receive();
            onMessage(message);
        } catch (JMSException e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void onMessage(Message message) {
    System.out.println("onMessage");
    messagesReceived++;

    if (message instanceof TextMessage) {
        try {
            TextMessage txtMsg = (TextMessage) message;
            String msg = txtMsg.getText();

            if(!client.sendMessage(msg)) {
                System.out.println("Webservice call failed. Keeping message");
                //message.
            } else {
                message.acknowledge();
            }

            if (transacted) {
                if ((messagesReceived % batch) == 0) {
                    System.out.println("Commiting transaction for last " + batch + " messages; messages so far = " + messagesReceived);
                    session.commit();
                }
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}
我目前没有使用事务(也许我应该?)

我肯定我错过了一些简单的东西,很快就会拍我的额头,但我似乎不知道这是怎么回事。谢谢


编辑:本人无法回答此问题,因为没有足够的代表:

好的,经过更多的实验,结果证明事务是实现这一点的唯一方法。以下是新代码:

public boolean init() throws JMSException, FileNotFoundException, IOException {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
    RedeliveryPolicy policy = new RedeliveryPolicy();
    policy.setInitialRedeliveryDelay(1000L);
    policy.setMaximumRedeliveries(RedeliveryPolicy.NO_MAXIMUM_REDELIVERIES);

    connectionFactory.setRedeliveryPolicy(policy);
    connectionFactory.setUseRetroactiveConsumer(true);
    Connection connection = connectionFactory.createConnection();

    connection.setExceptionListener(this);
    connection.start();

    session = connection.createSession(transacted, ActiveMQSession.CLIENT_ACKNOWLEDGE);
    destination = session.createQueue(subject);

    consumer = session.createConsumer(destination);
}

@Override
public void onMessage(Message message) {
    System.out.println("onMessage");
    messagesReceived++;

    if (message instanceof TextMessage) {
        try {
            TextMessage txtMsg = (TextMessage) message;
            String msg = txtMsg.getText();

            if(client.sendMessage(msg)) {
                if(transacted) {
                    System.out.println("Call succeeded - committing message");
                    session.commit();
                }
                //message.acknowledge();
            } else {
                if(transacted) {
                    System.out.println("Webservice call failed. Rolling back message");
                    session.rollback();
                }
            }

        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}
现在,按照重新交付策略的规定,消息每1000毫秒重新发送一次


希望这对其他人有帮助!:)

您不必使用事务,CLIENT\u ACK/Session.recover()也可以使用

发生以下任何情况时,消息将重新传递到客户端:

  • 使用事务会话并调用rollback()
  • 在调用commit之前,事务处理会话已关闭
  • 会话正在使用客户端确认,并调用了session.recover()

参见

确实很有帮助。非常感谢。哇,这救了我。显然,activemq通常会在10秒左右的时间内把事情“放回队列”,除非你像以前那样指定1。这对初学者很有帮助。特别是为什么你提到了代码> 1000毫秒< /代码>。如果使用单独的确认模式(像你原来的那样),连接必须关闭,否则ActuMeMQMaseAc食神会认为它是一个复制品,并自动忽略它。@ MartinSerrano -谢谢!这就解释了为什么我转发的邮件无法送达!我试了第三点,你用下面的方式建议的<代码>会话会话=connection.createSession(false,Session.CLIENT\u确认)。在业务代码之后,我想将消息重新发送到
Activemq
,然后只有我可以再次处理消息(哪个进程失败了)。为此,我这样写<代码>会话.recover()。但在对该程序进行评估后,Activemq不会向订阅者发送消息。有关我尝试的内容的更多信息,请查看此