jmsactivemq-artemis

Failed to remote connect via JMX to embedded ActiveMQ Artemis


I am using embedded ActiveMQ Artemis 2.38.0 for testing. I created embedded ActiveMQ Artemis as follows:

Configuration mqConfig = new ConfigurationImpl();
server = new EmbeddedActiveMQ();
mqConfig.addAcceptorConfiguration("tcp", "tcp://127.0.0.1:61616");
mqConfig.setSecurityEnabled(false);
mqConfig.setJMXManagementEnabled(true);
mqConfig.setMessageCounterEnabled(true);
mqConfig.setMessageCounterSamplePeriod(500);
mqConfig.setMessageCounterMaxDayHistory(1);
server.setConfiguration(mqConfig);
server.start();

After creating this embedded server I created several queues. Then I use JMX remote access to get the Queue depth:

JMXServiceURL url = new JMXServiceURL(jmxUrl);
JMXConnector jmxc = JMXConnectorFactory.connect(url);
....

jmxUrl is service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi.

However, I got this error:

Caused by: java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: 
    java.net.ConnectException: Connection refused: connect]

I suspect that JMX is not running. I am stuck.

I want to use JMX to get queue depth for queues created on embedded ActiveMQ Artemis server in tests only.

This application is old Spring Boot application, I am trying to upgrade it to Spring Boot 3.x from Spring Boot 2.x, and Java from 11 to 17. This used to use embedded ActiveMQ Classic. It does not work with Spring Boot 3.x so I switch to embedded ActiveMQ Artemis. Now the JMX does not work for this embedded ActiveMQ Artemis.

I searched all the examples in this https://github.com/apache/activemq-artemis-examples/tree/main repo, but I could not find any examples for embedded ActiveMQ Artemis + JMX.

I do need an embedded ActiveMQ Artemis + JMX for tests.


Solution

  • The EmbeddedActiveMQ will not manage its own MBean server. However, you can create one yourself and pass it to EmbeddedActiveMQ using the setMbeanServer method. The broker will then take this MBean server and register all of its MBeans in it, e.g.:

    MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
    LocateRegistry.createRegistry(1099);
    JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"), Map.of("jmx.remote.protocol.provider.pkgs", "javax.management.remote.rmi", "jmx.remote.server.default.class", "javax.management.remote.rmi.RMIServerImpl"), mbeanServer);
    connectorServer.start();
    
    Configuration mqConfig = new ConfigurationImpl();
    server = new EmbeddedActiveMQ();
    // customize your EmbeddedActiveMQ here
    server.setMbeanServer(mbeanServer);
    server.start();
    

    Then you can establish a JMX connection with a client URL like this:

    service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
    

    That said, if the code that's trying to get the queue depth in the same JVM as your EmbeddedActiveMQ then you can simply do something like this to get the depth of a queue named foo:

    System.out.println("Queue depth for \"foo\": " + server.getActiveMQServer().locateQueue("foo").getMessageCount());