Skip to content

Common libraries in EARs, Glassfish logging

by Matthias Fraass on Oktober 14th, 2008

Even jBoss core developers can be wrong sometimes ;) . I stumbled upon Andreas’ blog entry and was puzzled to see him and some commentators suggest to put log4j libraries into an application server’s common library folder.

I think that such a thing is bad practice and should only be the last resort when having classpath problems. What if different applications on the server use different versions of these “common” libs?

There’s a solution to this with standard JVM technology.

For example, It’s possible to configure log4j independently:

  • put log4j.jar into you application’s classpath, e.g. WEB-INF/lib
  • put your log4j.xml or log4j.properties inside the classpath of your project (WEB-INF/classes)

Problem solved.

But for an EAR?
If you have an EAR including a EJB-JAR and WAR part, you can put these files in a common directory in the EAR and reference them with the Class-Path mechanism of the MANIFEST.MF.
For instance, you can have the following structure:

  • EAR
    • /library/log4j.jar
    • /classes/log4j.properties
    • /ejb.jar
    • /web.war

In order to include the log4j-files into your classpath, you have to put the following into the META-INF/MANIFEST.MF of the ejb.jar and war:

Class-Path: classes library/log4j.jar

Yes: it’s relative to the EAR, not to the ejb.jar.

That way the EJB-JAR and WAR have one common log4j.jar and one common place for configuring it (classes/log4j.properties).

This solution should work for all application servers and did serve me well for years.

Update:

JEE5 platform should support a simpler mechanism, according to the JEE5 spec, chapter EE8.2.1:

A .ear file may contain a directory that contains libraries packaged in JAR files. The library-directory element of the .ear file’s deployment descriptor contains the name of this directory. If a library-directory element isn’t specified, or if the .ear file does not contain a deployment descriptor, the directory named lib is used.

Thanks to Per Lindberg who gave that hint.

From → Coding

7 Comments
  1. Per Lindberg permalink

    Um, isn’t /lib a magic directory in an EAR? So you can put your external JARs there, and then you don’t have to specify it as Class-Path in META-INF/manifest.mf …?

  2. I’m not aware of that.
    http://onjava.com/pub/a/onjava/2001/07/25/ejb.html says that /lib is only magical in WEB-INF/ of a web application.

  3. No, you’re right! \o/

    It’s in the JEE5 spec, chapter EE 8.2.1:

    A .ear file may contain a directory that contains libraries packaged in JAR files. The library-directory element of the .ear file’s deployment descriptor contains the name of this directory. If a library-directory element isn’t specified, or if the .ear file does not contain a deployment descriptor, the directory named lib is used.

    Finally!
    Thanks for the hint!

  4. Mike permalink

    I think the information is pretty clear so far. The problem we faced is that we want to change the log4j settings dynamically at runtime. How to do that if the log4j.properties file is packed in an .ear file?

    Another problem is, that if the log4j.properties is located outside the .ear file but still in the classpath, how do you handle changes to the settings in a clustered environment? Do you have to update the file on every cluster-node? The last issues seems like a real shortcoming of properties-file approach in clusters – only using a shared folder seems a possible solution.

    Does anyone have some experience in this area of changing logging settings at runtime?

  5. Nils Peuser permalink

    This was of great help to me, thanks. I do not have a clustered environment, but our customer specified, that the WEB-INF/classes directory of our WAR file has to be empty and we needed a solution to have an accessible log4j properties file.
    With this knowledge here I can also use it for our EJB :)

  6. Rod permalink

    @Mike: log4j allows you to override where its properties are picked up from by including a “log4j.configuration” JVM property on your app server. I assume that in a clustered environment this setting would be replicated across all nodes (can anyone clarify this?).

    You may have to locate the properties file on a network share that’s accessible to all your nodes though.

  7. Rod permalink

    Thanks for the tip about the EAR/lib directory. Although I’ve just tried this on GlassFish 3.1 and have not (yet) been able to get it to work. What I’m hoping to do is drop a jar with specific implementations of a compile-time interface into this location, then get my ejb to instantiate these arbitrary implementations using Class.forname(…). Any idea why this would not work?

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS