Deployment of custom MBean causes java.net.MalformedURLException: Unsupported protocol: remote+http in JBoss EAP 7.3.0 and later

Solution Unverified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 7.3
    • 7.4
    • 8.0

Issue

When deploying the following custom MBean code, deployment succeeds up to JBoss EAP 7.2.9 but fails for 7.3.0 and later (including 7.4).

public class ConfigService extends ServiceMBeanSupport implements ConfigServiceMBean {
    private static final String JMX_URL = "service:jmx:remote+http://127.0.0.1:9990";

    @Override
    protected void startService() throws Exception {
        JMXServiceURL serviceURL = new JMXServiceURL(JMX_URL);
        try (JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL, null)) {  // java.net.MalformedURLException: Unsupported protocol: remote+http on JBoss EAP 7.3.0 or later, but it works up to 7.2.9
            MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
            ...

Log of reproduction:

16:12:11,980 WARN  [org.jboss.example.mbean.support.ConfigService] (MSC service thread 1-4) WFLYSYSJMX0006: Starting failed jboss.support:name=ConfigBean: java.net.MalformedURLException: Unsupported protocol: remote+http
	at java.management/javax.management.remote.JMXConnectorFactory.newJMXConnector(JMXConnectorFactory.java:366)
	at java.management/javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:269)
	at deployment.SampleMBean.sar//org.jboss.example.mbean.support.ConfigService.startService(ConfigService.java:22)
	at org.jboss.as.system-jmx@7.4.13.GA-redhat-00001//org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:255)
        ...

Resolution

This is a known issue This content is not included.JBEAP-25937 and is expected to be fixed in a future cumulative patch to JBoss EAP 7.4.z and 8.0.z. There are several workarounds.

Option#1. Use ManagementFactory.getPlatformMBeanServer() instead of remote-jmx

import org.jboss.system.ServiceMBeanSupport;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;

public class SampleService extends ServiceMBeanSupport implements SampleServiceMBean {
    @Override
    protected void startService() throws Exception {
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        ObjectName objectName = ObjectName.getInstance("jboss.as:management-root=server");
        String attributeName = "serverState";
        Object result = mBeanServer.getAttribute(objectName, attributeName);
        System.out.println("serverState = " + result);
    }
}

Option#2. Temporarily replace thread's context class loader to application modules's classloader

ClassLoader old = Thread.currentThread().getContextClassLoader();
try {
    Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
    JMXServiceURL serviceURL = new JMXServiceURL(JMX_URL);
    try (JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL, null)) {
        MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
        ObjectName objectName = ObjectName.getInstance("jboss.as:management-root=server");
        String attributeName = "serverState";
        Object result = connection.getAttribute(objectName, attributeName);
        System.out.println("serverState = " + result);
    }
} finally {
    Thread.currentThread().setContextClassLoader(old);
}

This workaround requires the following jboss-deployment-structure.xml for *.sar deployment
resources/META-INF/jboss-deployment-structure.xml

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
  <deployment>
    <dependencies>
      <module name="org.jboss.remoting-jmx" services="import"/>
  </deployment>
</jboss-deployment-structure>

Option#3. Use singleton-session-bean instead of ServiceMBeanSupport

The JBoss Service Archive (sar) deployment is not part of the Java EE specification. It is now recommended to rewrite to singleton-session-bean covered by Java EE spec. For more details, please check Are service archives (sar), jboss-service.xml, JBoss MBeans, jboss-beans.xml recommended in JBoss EAP 6+. In ejb-jar/war deployments, Thread's context classloader is always the classloader of the application module.

Root Cause

The implementation of sar deployment has been moved from org.jboss.as.jmx to org.jboss.as.sar module by This content is not included.WFCORE-4179 and This content is not included.WFLY-11239 fixed in JBoss EAP 7.3.0. As of JBoss EAP 7.2.9 and earlier, the thread context classloader for ServiceMBeanSupport is org.jboss.as.jmx, not application deployment module. But org.jboss.as.jmx module depended on org.jboss.remoting-jmx. Consequently, before JBoss EAP 7.2.9, remote JMX calls are available from custom MBeans with ServiceMBeanSupport.

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.