Enabling Logback JMX MBean In Glassfish

Logback support for JMX can be enabled by just adding a <jmxconfigurator/> tag in the configuration file but this is not how a web application should register the logback MBean if you web application is deployed in a glassfish application server. If you do it you would get the below error message on accessing the logback MBean through JConsole –

Problem invoking getLoggerLevel : java.lang.IllegalStateException: WEB9031: WebappClassLoader unable to load resource[java.lang.Object], because it has not been started or was always stopped”

The root cause is an integration issue between logback and glassfish. On startup glassfish instantiates two classloaders for each of the deployed web application. The first one is a temporary one which is later destroyed.

When your web-application classes get loaded with this temporary classloader, logback initialization gets triggered (if the Logger instances are declared as static instances in your application classes which is mostly the case) like I explain in my older post. During this initialization process logback creates a JMX MBean instance (JMXConfigurator.class) and registers it with the MBean server. At certain point glassfish destroys the temporary classloader and nullifies all the static or final fields from the loaded classes. At a later step a new classloader is instantiated which would be the actual classloader for the web application. This classloader starts & loads the web context and the deployment continues.

The above mentioned error is displayed because while nullifying the classes during the destroy step of the temporary classloader, the registered MBean is not unregistered and logback does not re-register the MBean during the logback initialization step (which is triggered after the actual class loader is instantiated) since a MBean with that name was already registered. Here is short snippet of code from the JMXConfiguratorAction class which does the MBean registration.

    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    if(!MBeanUtil.isRegistered(mbs, objectName)) {
      // register only of the named JMXConfigurator has not been previously
      // registered. Unregistering an MBean within invocation of itself
      // caused jconsole to throw an NPE. (This occurs when the reload* method
      // unregisters the
      JMXConfigurator jmxConfigurator = new JMXConfigurator((LoggerContext) context, mbs,
          objectName);
      try {
        mbs.registerMBean(jmxConfigurator, objectName);
      } catch (Exception e) {
        addError("Failed to create mbean", e);
      }
     }

A mystery would be to understand the reason behind glassfish creating a temporary classloader(It is hard to figure it out exactly from the source code 🙂 ).
One simple workaround that can be implemented to resolve this issue is not add the <jmxConfigurator/> tag in the logback configuration file and to manually register the logback jmx mbean in a servlet context listener. Have a look at JMXConfiguratorAction.class for more details on how to register the logback MBean.

This note could be a good addition to the well documented Logback manual :).

Advertisements

Posted on April 29, 2011, in glassfish, jmx, logback and tagged , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: