WebSphere and Jakarta Commons Logging

Background

Jakarta Commons Logging (JCL) is an API for logging that acts as a façade for developers. It allows for developers to write to a common API, and deployers of the software to control the implementation via configuration. A common technique is to configure JCL to use Log4J, jdk logging, or simple logging to implement the API behind JCL. This allows an IT organization to bring in software written by others, and still allow it to conform to their standards.

For all currently supported releases of WebSphere, the runtime provides the Jakarta Commons Logging (JCL) API classes. In order to avoid customer breakage, the version has not been changing through time. As a result of this, certain software (ie: Spring) has a prerequisite for a version of JCL higher than our current 1.0.3 version.

Audience

This impacts all stack products and 3rd party products that use WebSphere as their base, and use Jakarta Commons Logging or use software that uses Jakarta Commons Logging. One caveat is that, if any software on top of WebSphere is including JCL or Log4J … or if the software that uses JCL is not loaded by the application class loader, further steps may need to be taken as described in the remainder of this paper.

For any stack product, third party product, or other code sitting on top of WebSphere, if they package or replace Jakarta Commons Logging or Log4J, a separate or additional solution may be needed.

Problems Addressed

This addresses problems that can occur when software requires newer version of Jakarta Commons Logging than what is included in the WebSphere runtime, or when the default configuration is to be over-ridden by a customer configuration. This paper describes how, without any IBM support assistance, most applications and stack products can do some simple configuration to optimize the usage of JCL and the various back end logging systems used with it.

Caveat

There is currently a known issue with Web Services Feature Pack which should be addressed in PMR 72352,122,000.

ParentLast ClassLoading, the simple solution

For a customer to use JCL in an application (directly or via software that they use), they need not provide the JCL runtime so long as the 1.0.3 version and the default back end implementation (jdk14logging and merging the logs in with WebSphere logs) is acceptable. If either of these is not the case, then some configuration actions must take place. It should be noted, that if you are willing to set classloading policy for you application and module to be PARENT_LAST, that what you provide in your application (relative to jcl jar, log4j jar, and jcl properties) will be used. If you are OK with PARENT_LAST classloading, then you simplify take the path in the Admin Console:

Applications -> Enterprise Applications -> <Select Your Application> -> Manage Modules -<Select your module(s)> . Them modify the classloading policy to specify application class loader first as shown in Figure 1.

Figure 1: Setting ParentLast classloading for an application.

This will result in the jars and configurations supplied in your application to be used before anything provided by WebSphere. One small caveat here is that WebSphere’s 1.0.3 level commons-logging.properties file has no priority which defaults to 0. If the application commons-logging.properties specifies a negative number for priority and uses a jcl 1.1.1 jar (unlikely but possible scenario), then the WebSphere properties will be used.

JCL 1.0.3 with Log4J

If JCL 1.0.3 is sufficient for your needs, then this can be accomplished without changing ClassLoading behavior in the following manner:

  • Provide the Log4J jar and JCL 1.0.3 jar in your applications WEB-INF/lib directory
  • Provide a file called org.apache.commons.logging.LogFactory in your META-INF/services directory. This file should have one line as specified here (just the text):
  • org.apache.commons.logging.impl.Log4jFactory

JCL 1.1.1 with Log4J

WebSphere 6.02 and WebSphere 6.1

In these releases, the process is to create a Shared Library with all that you need, create a class loader to that references only that shared library, has a classloading policy of ParentLast, and is attached to that server. This is best done in the following manner:

Moving files into a single directory

Move the commons-logging-1.1.1.jar, the log4j jar, and commons-logging.properties file into a single directory. That should be all that is in that directory. Figure 2 shows Windows Explorer viewing that directory containing those 3 files and only those 3 files.

Figure 2: 2 jars and one properties file in a single directory

commons-logging.properties

In our scenario, our commons-logging.properties file looks like this:

priority=1

org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

Note that priority is a newer parm and that the default is 0. The properties file with the highest priority found in the classpath will be used (if the jcl in the classpath is 1.1 or higher).

Creating the Shared Library

To create the shared Library, using the Admin Console, select Environment -> Shared Libraries. From this panel, select the server scope (on the right), and select the New button. Note that shared libraries can be defined at server, node, or cell scope. It may be beneficial when defining a shared library at cell scope, to use variables in the name and over-ride those variables at the node level.

Figure 3: Shared Library creation part 1

In the New Shared Library panel shown in Figure 4, do the following:

  1. Provide a Name (I chose jcl111). This will be referenced in a later step.
  2. Optionally, provide a description
  3. For the classpath, specify the directory that you created early that contains the 2 jar files and the one properties file
  4. Leave Native Library Path empty and select OK.

The following image shows the 6.1 panel filled in as described. After pressing OK, Save the configuration.

Figure 4: Shared Library creation part 2

Creating the ServerScoped ClassLoader that references the new Shared Library

In the Admin Console, select Servers -> Application Servers, then select the Server that contains your application (saServer1 in my case) as shown in Figure 5.

Figure 5: ClassLoader creation part 1

When the configuration for your server is displayed; expand Java and Process Management and select Class Loader as shown in Figure 6.

Figure 6: ClassLoader creation part 2

On the resulting panel (Figure 7), select a Class Loader order of Classes loaded with application class loader first. Then select the link for Shared library references.

Figure 7: ClassLoader creation part 3

After that selection, you will need to select the Add button to reach the panel in Figure 8. Select the name of the Shared Library that you created earlier, select OK, and Save the configuration..

Figure 8: ClassLoader creation part 4

At this point, your configuration should properly load your version of Jakarta Commons Logging, your version of Log4J, and your commons-logging.properties configuration file. For this all to take affect, you will need to recycle your server.

WebSphere 7.0 and higher

The process described under WebSphere 6.1 and 6.02 is notably easier in WebSphere 7.0 thanks to a new facility called Isolated Shared Libraries. In this case, as you create the Shared Library (just as in 6.1) there is a checkbox at the bottom of the panel as seen in Figure 9.

Figure 9: WebSphere 7.0 Isolated Shared Libraries

By selecting that checkbox, no new ClassLoader needs to be created. Then this Isolated Shared Library can be added as a Shared Library Reference to your application and modules by selecting: Applications -> Application Types -> WebSphere Enterprise Applications -> <Select Your Application> -> and from that panel select Shared Library References under the References section. This will bring you to the panel shown in Figure 10.

Figure 10: Shared Library References

Simply select the application, then the Reference shared libraries button. Then you will see a panel as shown in Figure 11.

Figure 11: Shared Library Reference Add and Remove

This shows the available shared libraries. Simply select those you want to add, select the right arrow, press OK, and save your changes. Do this for the application and the module.

Summary

So in summary, if the Jakarta Commons Logging 1.0.3 is sufficient for your needs, then using it with the default (jdk14logger) implementation or the Log4J is a relatively simple process. It is also relatively simple to use your own version if you can use ParentLast class loading in your application.

If neither of those is true, then the best technique is to create a Shared Library containing JCL, Log4J, and your properties file. Then create a classLoader that is server scoped and references your shared library. WebSphere V7.0 greatly simplifies this process with the introduction of Isolated Shared Libraries.