Uploaded image for project: 'Log4j 2'
  1. Log4j 2
  2. LOG4J2-3577

Log4j2 configuration during servlet context initialization does not work on Websphere Liberty appserver

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 2.17.1
    • None
    • Configuration
    • None
    • I am using Log4j 2.17.1 on Websphere Liberty 21.0.0.8.

    Description

      In my web application, log4j configures itself twice:

      1. before the servlet context is initialized
      2. during servlet context initialization

      (1) uses a log4j configuration that only consists of console appenders. (2) uses a full log4j configuration that consists of servlet appenders and servlet context lookups that would fail if initialized before the servlet context was available. The logger configuration from (2) should overwrite the logger configuration created in (1) for the rest of the application's lifecycle.

      However, this does not work on Websphere Liberty. Because Log4j associates a logger context with the classloader used to create it, the classloader used during (2) must be the same classloader that is used during the rest of the application's lifecycle.

      Liberty uses the following classloaders:

      • before servlet context initialization: AppClassLoader
      • during servlet context initialization: ThreadContextClassLoader
      • the rest of the application lifecycle: AppClassLoader

      This means that log messages produced during the rest of the application lifecycle do not go through the full log4j configuration created in (2) because the configuration from (2) is associated with the ThreadContextClassLoader whereas the rest of the application uses the AppClassLoader. All messages during the rest of the application lifecycle are logged with the configuration created in (1) because they have the same classloader.

      To workaround this, I have had to modify the source of Log4jWebInitializerImpl:initializeNonJndi to check if the classloader is an instance of com.ibm.ws.classloading.internal.ThreadContextClassLoader. If it is, I pass null as the classloader to Configurator:initialize to allow it to resolve the classloader via other means, which it ultimately computes as the AppClassLoader.

      I have attached my edited version of Log4jWebInitializerImpl.java

      This works on all other application servers that I have tested on, such as Tomcat, Weblogic, and JBoss.

      Attachments

        1. Log4jWebInitializerImpl.java
          14 kB
          Carl Froneberger

        Activity

          People

            pkarwasz Piotr Karwasz
            carlfroneberger Carl Froneberger
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated: