Search code examples
javajmxactivemq-artemis

Throws JMSException errors when connecting to a broker via JMX in ActiveMQ Artemis


I have a code to connect to the ActiveMQ Artemis broker via the JMX protocol using some kind of login/password authorization

 public static MBeanServerConnection connectBroker(String brokerUrl, String user, String password) {

        QueueConnection connection = null;
        try {
            QueueConnectionFactory cf = new ActiveMQQueueConnectionFactory(brokerUrl);
            connection = cf.createQueueConnection();
            connection.start();
            HashMap env = new HashMap();
            String[] creds = {user, password};
            env.put(JMXConnector.CREDENTIALS, creds);
            JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(BuildGet.JMX_URL),env);

            return connector.getMBeanServerConnection();
        } catch (JMSException | IOException e) {
            throw new RuntimeException(e);
        }
    }

And this code gives these errors:

Caused by: java.lang.RuntimeException: javax.jms.JMSException: Failed to create session factory
    at jmxClientUIPConsole.BuildGet.connectBroker(BuildGet.java:81)
    at jmxClientUIPConsole.gui.DConsoleFrameController.connectBroker(DConsoleFrameController.java:41)
    ... 56 more
Caused by: javax.jms.JMSException: Failed to create session factory
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:867)
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createQueueConnection(ActiveMQConnectionFactory.java:335)
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createQueueConnection(ActiveMQConnectionFactory.java:331)
    at jmxClientUIPConsole.BuildGet.connectBroker(BuildGet.java:72)
    ... 57 more
Caused by: ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ219007: Cannot connect to server(s). Tried with all available servers.]
    at org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:701)
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:865)
    ... 60 more

But if you make a method without authorization then everything works:

public static MBeanServerConnection connectBroker(String brokerUrl) {

        QueueConnection connection = null;
        try {
            QueueConnectionFactory cf = new ActiveMQQueueConnectionFactory(brokerUrl);
            connection = cf.createQueueConnection();
            connection.start();
            JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(BuildGet.JMX_URL));

            return connector.getMBeanServerConnection();
        } catch (JMSException | IOException e) {
            throw new RuntimeException(e);
        }
    }

Here is my management.xml:

<management-context xmlns="http://activemq.apache.org/schema">
   <connector connector-port="13682" connector-host="192.168.1.135"/>
   <authorisation>
      <allowlist>
         <entry domain="hawtio"/>
      </allowlist>
      <default-access>
         <access method="list*" roles="view,update,amq,guest,test"/>
         <access method="get*" roles="view,update,amq,guest,test"/>
         <access method="is*" roles="view,update,amq,guest,test"/>
         <access method="set*" roles="update,amq,guest,test"/>
         <access method="*" roles="amq,guest,test"/>
      </default-access>
      <role-access>
         <match domain="org.apache.activemq.artemis">
            <access method="list*" roles="view,update,amq,guest,test"/>
            <access method="get*" roles="view,update,amq,guest,test"/>
            <access method="is*" roles="view,update,amq,guest,test"/>
            <access method="set*" roles="update,amq,guest,test"/>
            <access method="*" roles="amq,guest,test"/>
         </match>
      </role-access>
   </authorisation>
</management-context>

I pass the login amq and password amq to the method. Maybe I'm passing the wrong login and password? Why can an error occur when connecting to a broker?

Now the method looks like this:

public static MBeanServerConnection connectBroker(String brokerUrl, String user, String password) {
    try {
        Map<String, String[]> env = new HashMap();
        String[] creds = {user, password};
        env.put(JMXConnector.CREDENTIALS, creds);
        JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + brokerUrl + ":13682/jmxrmi"), env);
        return connector.getMBeanServerConnection();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

But if I leave login and password empty, then for some reason it can connect, although I left these authorization fields empty for the test. Why isn't an error thrown when the field data is empty?


Solution

  • The stack-trace indicates that the exception is coming from your invocation of javax.jms.QueueConnectionFactory.createQueueConnection() so it doesn't appear to have anything to do with your JMX connection. The exception is being thrown before it even gets to JMXConnectorFactory.connect().

    It's important to note that this connectBroker method is leaking a JMS connection every time it is invoked (assuming it is successful). This is because you create a JMS connection, but you don't close it or return it from the method. I recommend removing the JMS connection from that method entirely as it servers no real purpose.