Search code examples
apache-tomeeactivemq-artemis

ActiveMQ Artemis 2.10.1 ignoring retry settings in TomEE


I downloaded latest ActiveMQ Artemis 2.10.1 (Windows 10, JDK 8) and can't get the address-settings to take affect. Reading the documentation (not much) on line I edited the broker.xml by adding:

<address-settings>
    <address-setting match="BETATESTQ">
        <dead-letter-address>BETATESTQ_DLQ</dead-letter-address>
        <expiry-address>BETATESTQ_EXPIRY</expiry-address>
        <redelivery-delay>30000</redelivery-delay>
        <redelivery-delay-multiplier>1.5</redelivery-delay-multiplier>         
        <redelivery-collision-avoidance-factor>0.15</redelivery-collision-avoidance-factor>
        <max-redelivery-delay>100000</max-redelivery-delay>
        <max-delivery-attempts>999</max-delivery-attempts>      
    </address-setting>   
</address-settings>

<addresses>
    <address name="BETATESTQ_DLQ">
        <anycast>
            <queue name="BETATESTQ_DLQ" />
        </anycast>
    </address>   
    <address name="BETATESTQ_EXPIRY">
        <anycast>
            <queue name="BETATESTQ_EXPIRY" />
        </anycast>
    </address>   
    <address name="BETATESTQ">
        <anycast>
            <queue name="BETATESTQ" />
        </anycast>
    </address>  
</addresses>

Everything else is default broker.xml when create a broker.

It seems to always use default values for redelivery-delay, max-redelivery-delay, max-delivery-attempts. It does read the dead letter and expiry values correctly. I can see the message getting retried in TomEE logs and shows up in Artemis console and moves to dead letter queue when done.

I am not passing in and delivery or retry data when put it on the queue initially (using bare minimal Java J2EE code).

How can I get it to not ignore redelivery-delay, max-redelivery-delay, max-delivery-attempts?

I connected to the queue with Apache TomEE (not using built-in ActiveMQ 5.x in TomEE but pointing it to ActiveMQ Artemis)

JMS listener:

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.*;

@MessageDriven(name = "BETATESTQ", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "BETATESTQ"),
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") 
})
public class BetaTestQueueListener implements MessageListener, java.io.Serializable {
    private static final long serialVersionUID = 1L;     

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void onMessage(Message rcvMessage) {
        System.out.println("omMessage throw runtime exception");          
        throw new RuntimeException("trigger retry");
    }
}

12/20/19 - Working values I found for TomEE 8.0.0:

tomee.xml:

<?xml version="1.0" encoding="UTF-8"?>
<tomee>

    <Resource id="artemis" class-name="org.apache.activemq.artemis.ra.ActiveMQResourceAdapter">
        ConnectorClassName=org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory
        ConnectionParameters=host=127.0.0.1;port=61617;needClientAuth=false;sslEnabled=true;keyStorePath=../ssl/server_jks_keystore.jks;keyStorePassword=mypassword;trustStorePath=../ssl/client_jks_truststore.jks;trustStorePassword=mypassword;trustAll=true;verifyHost=false;wantClientAuth=false;needClientAuth=false;keyStoreProvider=JKS;trustSToreProvider=JKS
        UserName=admin
        Password=admin     
        JndiParams=java.naming.factory.initial=org.apache.openejb.core.OpenEJBInitialContextFactory
    </Resource>

    <Resource id="MyJmsConnectionFactory"
              class-name="org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory"
              constructor="uri,username,password"
              type="javax.jms.ConnectionFactory">
        uri=tcp://localhost:61617?needClientAuth=false;sslEnabled=true;keyStorePath=C:/apache-tomee-plus-8.0.0/ssl/server_jks_keystore.jks;keyStorePassword=mypassword;trustStorePath=C:/apache-tomee-plus-8.0.0/ssl/client_jks_truststore.jks;trustStorePassword=mypassword;trustAll=true;verifyHost=false;wantClientAuth=false;needClientAuth=false;keyStoreProvider=JKS;trustSToreProvider=JKS
        username=admin
        password=admin
        TransactionSupport=xa
        PoolMaxSize=20
        PoolMinSize=0   
    </Resource>     

    <Resource id="BETATESTQ_DLQ"
              class-name="org.apache.activemq.artemis.api.jms.ActiveMQJMSClient"
              constructor="name"
              factory-name="createQueue"
              type="javax.jms.Queue">
        name=BETATESTQ_DLQ
    </Resource> 
    <Resource id="BETATESTQ"
              class-name="org.apache.activemq.artemis.api.jms.ActiveMQJMSClient"
              constructor="name"
              factory-name="createQueue"
              type="javax.jms.Queue">
        name=BETATESTQ
    </Resource> 
    <Container id="mdb" type="MESSAGE">
        InstanceLimit = -1
        ResourceAdapter = artemis
        ActivationSpecClass = org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec
    </Container>
</tomee>

Java EE class to send JMS message:

import java.util.*;
import javax.jms.*;
import org.slf4j.*;

public final class JmsPublisherInstance2 implements java.io.Serializable { 
   private static final long serialVersionUID = 1L;
   private static final Logger LOG = LoggerFactory.getLogger(JmsPublisherInstance2.class);

   public void send( String msg,
                     ConnectionFactory connectionFactory,
                     Queue queue ) throws Exception { 
      Session session = null;
      MessageProducer producer = null;
      TextMessage message = null;
      Connection connection = null;
      try {     
            connection = connectionFactory.createConnection();       
            connection.start();
            session = connection.createSession(true, Session.SESSION_TRANSACTED);
            producer = session.createProducer(queue);
            message = session.createTextMessage(msg);
            producer.send(message);
            session.commit();
      }  catch (Exception e) {
         session.rollback();
         LOG.error(e.getMessage(), e);
         throw e;
      }  finally {
          if (session!=null ) {
              session.close();
          }
          if (connection!=null ) {
              connection.close();
          }
      }
   }
}

Java EE listener:

import java.io.*;
import javax.annotation.*;
import javax.ejb.*;
import javax.jms.*;

@MessageDriven ( name = "BetaTESTQMDB" , activationConfig = {
    @ActivationConfigProperty(propertyName="destinationType", propertyValue = "javax.jms.Queue") ,
    @ActivationConfigProperty(propertyName="destination", propertyValue = "BetaTESTQ"),
    @ActivationConfigProperty(propertyName="maxSession", propertyValue = "5"),
    @ActivationConfigProperty(propertyName="acknowledgeMode", propertyValue = "Auto-acknowledge")
})

public class BetaTestQueueListener implements MessageListener, java.io.Serializable { 
      private static final long serialVersionUID = 1L;

      @Resource(name="MyJmsConnectionFactory")
      private ConnectionFactory connectionFactory;

      @Resource
      private MessageDrivenContext mdbContext;

      @Resource(name = "BETATESTQ") 
      private javax.jms.Queue betaTestQ;      

      @TransactionAttribute(TransactionAttributeType.REQUIRED)
      public void onMessage(Message rcvMessage) {
            try {
                jmsInstance.send("test message", connectionFactory, betaTestQ);
            } catch (Throwable t) {
                t.printStackTrace();
                mdbContext.setRollbackOnly();
            }
      }
}

Solution

  • It seems likely that you're using the OpenWire JMS client. This complicates matters because, as I understand it, the OpenWire JMS client implements redelivery in the client itself and those redelivery semantics are configured on the client side not the broker side. The broker doesn't have a chance to apply any kind of redelivery policy because the OpenWire client handles everything and doesn't inform the broker of the delivery failures. This documentation may help you configure redelivery for your OpenWire client.

    That said, I recommend following this tutorial. It demonstrates how to integrate TomEE and ActiveMQ Artemis without building/deploying the JCA RA. This will allow you to use the Core JMS client rather than the OpenWire JMS client.

    If you want to go the RA route you can build the ActiveMQ Artemis JCA RA by running mvn verify from the examples/features/sub-modules/artemis-ra-rar/ directory. The RA will be in the target directory named artemis-rar-<version>.rar.