Thursday, March 29, 2012

Optimal Java EE Webapp Logging Configuration for JBoss AS7 Deployment

I used to configure logging (via SLF4J) in my Java EE web applications like this:

<properties>
    <slf4j.version>1.6.4</slf4j.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>${slf4j.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
    </dependency>
</dependencies>

Although in practice this works well, it's not efficient because I'm bundling my own SLF4J libraries with my webapp, and direct them to JDK Logging, which is handled properly by JBoss AS 7.1.

Note that there's nothing wrong with the above configuration, because makes the webapp very portable across Application Servers (even servlet containers like Tomcat).

Thanks to Joshua Davis, I got the perfect logging configuration for JBoss AS7:

<properties>        <slf4j.version>1.6.4</slf4j.version></properties>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.1</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${slf4j.version}</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

<version>${slf4j.version}</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-jdk14</artifactId>

<version>${slf4j.version}</version>

<scope>provided</scope>

</dependency>

</dependencies>

</dependencyManagement>

Dependencies:

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-jdk14</artifactId>

</dependency>


Since SLF4J is already defined as a JBoss 'module', then all that we need to do is to reference the module from the WAR file.1 The simplest way is to get Maven to list the dependency in META-INF/MANIFEST.MF:

<plugin>

  <groupId>org.apache.maven.plugins</groupId>

  <artifactId>maven-war-plugin</artifactId>

  <version>2.2</version>

  <configuration>

    <archive>

      <manifestEntries>

        <Dependencies>org.slf4j, org.apache.commons.logging</Dependencies>

      </manifestEntries>

    </archive>

  </configuration>

</plugin>

This will generate a META-INF/MANIFEST.MF file that has this line in it:

Dependencies: org.slf4j, org.apache.commons.logging


This tweak saves space, RAM, and probably increases webapp performance a bit too. :-)


To learn more about Java Web Development using Java EE 6, I highly recommend The Java EE 6 Tutorial: Basic Concepts (4th Edition) (Java Series) by Eric Jendrock, Ian Evans, Devika Gollapudi and Kim Haase.