Bug 39055

Summary: Firewall access for JSR 160 JMX with Java 5
Product: Tomcat 5 Reporter: George Lindholm <George.Lindholm>
Component: UnknownAssignee: Tomcat Developers Mailing List <dev>
Severity: enhancement CC: ivanfm
Priority: P2    
Version: 5.5.16   
Target Milestone: ---   
Hardware: Other   
OS: other   

Description George Lindholm 2006-03-21 23:04:21 UTC
http://tomcat.apache.org/tomcat-5.5-doc/monitoring.html states:

  Note:The JSR 160 JMX-Adaptor opens a second data protocol port. That is a
problem when you have installed a local firewall.

This can be fixed by using a custom JMXConnectorServer to control both
ports thus allowing firewall access.

Eg. This is a GLP I threw together to try it out:

public class JMXPortServer extends HttpServlet {
  static JMXConnectorServer cs;
  static String jmxHost;
  static {
    try {
      final InetAddress host = InetAddress.getLocalHost();
      jmxHost = host.getHostName();
      final int jmxPort =
      final int jmxPort2 = jmxPort + 1;

      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

      HashMap env = new HashMap();
      final String sslProperty = "com.sun.management.jmxremote.ssl";
      String value = System.getProperty(sslProperty);
      if (Boolean.getBoolean(value)) {
        SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
        SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
        env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
        env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);

      final String passwordFileProperty =
      value = System.getProperty(passwordFileProperty);
      if (value != null) {
        env.put("jmx.remote.x.password.file", value);

      final String jmxUrl = "service:jmx:rmi://" + jmxHost + ":" + jmxPort2
+"/jndi/rmi://" + jmxHost + ":" + jmxPort + "/server";
      final JMXServiceURL url = new JMXServiceURL(jmxUrl);
      cs = JMXConnectorServerFactory.newJMXConnectorServer(
          url, env, mbs);

      try {
        LogService.log(LogService.INFO, "JMXPrtServer started on " + jmxUrl);
      } catch (IOException ex) {
        LogService.log(LogService.ERROR, ex);
    } catch (Exception ex) {

I tell tomcat to load the servlet through web.xml and start the
JVM with:

-Dcom.sun.management.jmxremote -Dorg.jasig.portal.jmxPort=7087

I then run jconsole on my desktop with:

  jconsole service:jmx:rmi://host:7088/jndi/rmi://host:7087/server

and, bingo, JMX access.

It would be be better if this was built into Tomcat as a configuration
option, rather than having to do it as part of every Tomcat instance.

I haven't tried out the ssl connection code (I got this code from
Comment 1 George Lindholm 2006-03-27 23:46:23 UTC
*** Bug 39057 has been marked as a duplicate of this bug. ***
Comment 2 Yoav Shapira 2006-04-13 19:34:47 UTC
If you submit a patch to Tomcat that does this, rather than a completely
separate servlet, it would be greatly appreciated.
Comment 3 Yoav Shapira 2006-12-24 19:02:04 UTC
I guess that's a no on the patch, but that's OK.  I still think this sample code
is valuable, so I've updated the monitoring documentation page you reference to
add a link to this page in Bugzilla.  That way users will be shown this
workaround code.

I think things are improving in this area anyways in Java 6, so we may not want
to include this type of code in the distro core anyhow.
Comment 4 Peter Rossbach 2007-06-04 23:21:59 UTC
OK, feature is cool, but implementation has some bugs.
Juergen Herrmann send me a better code contribution.
Please check the new JMXAdaptorLifecycleListener ( Tomcat 5.5 Revision 544401).

<Server ...>
<Listener className="org.apache.catalina.mbeans.JMXAdaptorLifecycleListener"
          namingPort="8083" port="8084" host="myhost" />