Blog Archives
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 :).
Glassfish Source Code
The source code of glassfish can be downloaded using the svn url – https://svn.java.net/svn/glassfish~svn. If you want to download the source code for a specific version of glassfish, browse the svn repository and add the relevant tag suffix. For e.g. to download the source code for glassfish 3.1 use the url – https://svn.java.net/svn/glassfish~svn/tags/3.1.
By the way – To know the version of the glassfish server used for deployment, use the command – asadmin version. The output of the command would include the build version to help you figure out the tag to be used while downloading the source code.
Using Logback in Glassfish v3 – Part II
In my previous post I listed out ways to configure logback in glassfish v3. After researching out and understanding logback more I realized that there is a simpler way.
Logback searches for the logback configuration file (first logback.groovy then logback-test.xml and then logback.xml if the former one is not found) in the classpath. Hence one can just place the logback.xml in the deployed application war and that’s it. No jvm-option called -Dlogback.configurationFile is needed.
If there is no logback.xml found in the classpath, logback configures itself using BasicConfigurator which will cause the logging output to be directed to the console. The minimal configuration involves a consoleAppender attached to the root logger which has a default log level of DEBUG. In glassfish v3, anything logged to the Console i.e. System.out or System.error is sent to the log file via a logger named “javax.enterprise.system.std.com.sun.enterprise.v3.services.impl”. A message to System.err is logged at Level.SEVERE. A message to System.out is logged at Level.INFO.
See the last logger in the below image.
Using Logback in Glassfish v3
The article provides details on how to integrate custom logging framework like slf4j and logback in glassfish v3. The steps required to achieve this are
1. Add a jvm option
-Dlogback.configurationFile=${com.sun.aas.instanceRoot}/config/logback.xml
from the admin console i.e. server-config -> JVM Settings -> JVM Options
2. Place your logback.xml file under <domain-directory>/config.
The logs would be created relative to <domain-directory>/config.
Adding new loggers in Glassfish v3
Glassfish uses java util logging and below are two ways through which one can add new loggers for their application or third party api’s.
1. Set log-levels command
By executing the ‘asadmin set-log-levels org.springframework=FINE’ command a new logger for springframework is added. The logger gets added as soon as the command executes successfully.
2. Modifying the logging.properties
By modifying the logging.properties present in the domain/config folder as –
org.springframework.level=FINE.
The logger gets added as soon as the properties file is saved.
No glassfish server restarts are required in any of the above approaches. The log statements can be seen in the same old server.log file. The newly added logger is visible in the admin console under Configurations->server-config->Logger Settings->Log levels. Any further modifications to the log levels can be done through this admin console UI.