2

To simplify the problem I've configured an MDB with only one session.

import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.slf4j.Logger;

@TransactionAttribute(TransactionAttributeType.REQUIRED)
@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/jms/queue/adwordsReportRequest"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "veiculo = 'adwords'"),
    @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1"),
    @ActivationConfigProperty(propertyName = "transactionTimeout", propertyValue = "7500") })

public class ReportRequestReceiveDispatcherAdwords implements MessageListener {

    @Resource
    private MessageDrivenContext mdc;

    @Inject
    private Logger logger;

    private Integer count = 0;

    public ReportRequestReceiveDispatcherAdwords() {
        // TODO Auto-generated constructor stub
    }

    public void onMessage(Message inMessage) {
        TextMessage msg = null;
        String text = null;
        try {
            if (inMessage instanceof TextMessage) {

                msg = (TextMessage) inMessage;
                text = msg.getText();

                if (count >= 10 && count <= 100) {
                    logger.error("Count: {} - {} -  Marcando como erro!", ++count, text);
                    throw new RuntimeException("teste de erro");
                } else
                    logger.info("Count: {} - {}", ++count, text);

            } else {
                logger.warn("Message of wrong type: " + inMessage.getClass().getName());
            }
        } catch (Exception e) {

            mdc.setRollbackOnly();
        }

    }

}

The Queue is configured with 3 attempts and 2 minutes of delay between them.

 <address-setting name="#" dead-letter-address="jms.queue.DLQ" expiry-address="jms.queue.ExpiryQueue" max-delivery-attempts="3" redelivery-delay="120000" max-size-bytes="10485760" page-size-bytes="2097152" message-counter-history-day-limit="10"/>

Executing this code with 600 messages in the queue:

14:10 --> it stopped the processing at the first error.
14:12 --> processes 3 messages and stops.
14:14 --> processes 10 messages and stops.
14:16 --> processes 14 messages and stops.
14:18 --> processes 10 messages and stops.
14:20 --> processes 16 messages and stops.
14:22 --> processes 9 messages and stops.
14:24 --> processes 8 messages and stops.
14:26 --> processes 7 messages and stops.
14:28 --> processes 6 messages and stops.
14:30 --> processes 6 messages and stops.
14:32 --> processes 6 messages and stops.
14:34 --> It goes out of the loop that generates error, so it finish the processing of the other messages until the queue is empty.

Why the MDB stops if still there is messages in the queue? When a message comes back to the queue after a rollback, it goes to the top blocking te rest? It's not making any sense to me. I couldn't find any doc where this behavior is described.

According to the specification:

Other subsequent messages will be delivery regularly, only the cancelled message will be sent asynchronously back to the queue after the delay. https://activemq.apache.org/artemis/docs/2.0.0/undelivered-messages.html

Camilla
  • 489
  • 5
  • 14
  • which app server? – Sabir Khan Jun 12 '17 at 04:36
  • Sorry.. I forgot to say. It's Wildfly. – Camilla Jun 12 '17 at 14:02
  • I think this is expected because you are rolling back that complete transaction `mdc.setRollbackOnly();`, what was your expectation with `mdc.setRollbackOnly();`, did you try not rolling back using `mdc.setRollbackOnly();`? – hagrawal7777 Jun 12 '17 at 14:36
  • If I don't use mdc.setRollbackOnly() it won't be retried, it will be commited. – Camilla Jun 14 '17 at 01:35
  • @Camilla You can set the transaction with auto commit as FALSE. Firstly, did you try to skip that see if you get remaining messages in the queue? – hagrawal7777 Jun 15 '17 at 09:12
  • @hagrawal, Thank you for your help but I'm not sure if I understood. With the rollback, I get remaining messages in the queue as expected. I want them to keep there. The problem is I just want those that generated errors to be processed after the ones that haven't been tried yet. – Camilla Jun 15 '17 at 23:59
  • See if this helps - http://www.mastertheboss.com/jboss-server/jboss-jms/jboss-jms-queue-example or http://www.mastertheboss.com/jboss-server/jboss-jms/connecting-to-an-external-wildfly-jms-server – Rao Jun 19 '17 at 13:51

0 Answers0