Search code examples
jmsactivemq-artemis

Can't use management API with JMS to change address settings


I am quite new to the world of JMS and ActiveMQ Artemis, and I'm struggling to make use of the management API to send a JMS message to my stand alone broker.

I am using ActiveMQ Artemis 2.38.0.

I want to update the address settings without using broker.xml, but I keep getting null as a reply, and the settings clearly don't change when I go to test them.

I followed along with a similar post and was able to come up with this bit of code:

try (JMSContext context = activeMQConnectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)) {
            //You MUST explicitly create this queue for management operations.
            Queue managementQueue = context.createQueue("activemq.management");

            Message message = context.createMessage();
            JMSManagementHelper.putOperationInvocation(
                message,
                ResourceNames.BROKER,    // Targetted Resource
                "addAddressSettings",    // Operation to invoke
                "ri.trips1",             // Address match
                null,                    // Dead letter address (DLA)
                null,                    // Expiry address
                -1L,                     // Expiry delay
                true,                    // Last value queue
                7,                       // Max delivery attempts
                -1L,                     // Max size bytes
                0,                       // Page size bytes
                -1,                      // Page max cache size
                1000L,                   // Redelivery delay
                1.0,                     // Redelivery multiplier
                -1L,                     // Max redelivery delay
                -1L,                     // Slow consumer threshold
                false,                   // Slow consumer policy
                null,                    // Slow consumer notification interval
                -1L,                     // Min large message size
                -1L,                     // Consumer window size
                null,                    // Auto-create queues
                true,                    // Auto-create addresses
                false,                   // Auto-delete queues
                false,                   // Auto-delete addresses
                true                     // Auto-delete created queues
            );
            context.createProducer().send(managementQueue, message);

            Message response = context.createConsumer(managementQueue).receive(5000);
            if (response != null && JMSManagementHelper.hasOperationSucceeded(response)) {
                System.out.println("Address settings applied successfully.");
            } else {
                System.err.println("Failed to apply address settings");
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }

The code block here is always resolving to failed because the response is always null. However, it is creating the address activemq.management just fine.


Solution

  • The problem here is the way you're sending the request and receiving the reply. There's nothing to correlate the request with the response so you're not actually receiving a response. You could use a QueueRequestor as is demonstrated in the management example from ActiveMQ Artemis or you could stick with the JMSContext and correlate the response yourself, e.g.:

    try (JMSContext context = activeMQConnectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)) {
       // You MUST explicitly create this queue for management operations.
       Queue managementQueue = context.createQueue("activemq.management");
    
       Message message = context.createMessage();
       JMSManagementHelper.putOperationInvocation(message, ResourceNames.BROKER, ...);
       Queue responseQueue = context.createTemporaryQueue();
       message.setJMSReplyTo(responseQueue);
       context.createProducer().send(managementQueue, message);
       Message response = context.createConsumer(responseQueue).receive(5000);
       if (response != null && JMSManagementHelper.hasOperationSucceeded(response)) {
          System.out.println("Address settings applied successfully.");
       } else {
          System.err.println("Failed to apply address settings");
       }
    } catch (JMSException e) {
       e.printStackTrace();
    }
    

    Also, it's worth noting that the addAddressSettings method you're using is deprecated. I encourage you to use this one instead which takes flexible JSON input, e.g.

    try (JMSContext context = activeMQConnectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)) {
       //You MUST explicitly create this queue for management operations.
       Queue managementQueue = context.createQueue("activemq.management");
       Message message = context.createMessage();
       String json = """
          {
             "maxDeliveryAttempts": "7",
             "maxSizeBytes": "-1",
             "pageSizeBytes": "0",
             "redeliveryDelay": "1000"         
          }
          """;
       JMSManagementHelper.putOperationInvocation(message, ResourceNames.BROKER, "addAddressSettings", "ri.trips1", json);
       Queue responseQueue = context.createTemporaryQueue();
       message.setJMSReplyTo(responseQueue);
       context.createProducer().send(managementQueue, message);
    
       Message response = context.createConsumer(responseQueue).receive(5000);
       if (response != null && JMSManagementHelper.hasOperationSucceeded(response)) {
          System.out.println("Address settings applied successfully.");
       } else {
          System.err.println("Failed to apply address settings");
       }
    } catch (JMSException e) {
       e.printStackTrace();
    }