You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Ralph Goers (Jira)" <ji...@apache.org> on 2022/08/19 16:14:00 UTC

[jira] [Comment Edited] (LOG4J2-3577) Log4j2 configuration during servlet context initialization does not work on Websphere Liberty appserver

    [ https://issues.apache.org/jira/browse/LOG4J2-3577?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17581939#comment-17581939 ] 

Ralph Goers edited comment on LOG4J2-3577 at 8/19/22 4:13 PM:
--------------------------------------------------------------

This sounds like it is working as designed. By default, Log4j2 uses the ClassLoaderContextSelector.  Its purpose is to allow a logging configuration for every application when running in a servlet container. A "normal" servlet container like Tomcat would have:
* Bootstrap classloader
* Tomcat classloader
* App classloader

With this structure the ClassLoaderContextSelector allows one configuration for Tomcat while each app will have its own since they each have their own ClassLoader.

It sounds like the problem here is that WebSphere is creating the application's ClassLoader and then initialing the application's servlet context using a different ClassLoader, possibly on a different Thread.  So I don't think the change committed by Piotr is correct. Instead, we need to figure out how to get the Logging Configuration performed before servlet context initialization to locate the application's logging configuration instead of using the default. That basically means using the Servlet Context is useless for logging configuration.

It might make sense to create a WebSphereContextSelector to handle this.



was (Author: ralph.goers@dslextreme.com):
This sounds like it is working as designed. By default, Log4j2 uses the ClassLoaderContextSelector.  Its purpose is to allow a logging configuration for every application when running in a servlet container. A "normal" servlet container like Tomcat would have:
* Bootstrap classloader
* Tomcat classloader
* App classloader

With this structure the ClassLoaderContextSelector allows one configuration for Tomcat while each app will have its own since they each have their own ClassLoader.

It sounds like the problem here is that WebSphere is creating the application's ClassLoader and then initialing the application's servlet context using a different ClassLoader, possibly on a different Thread.  So I don't think the change committed by Piotr is correct. Instead, we need to figure out how to get the Logging Configuration performed before servlet context initialization to locate the application's logging configuration instead of using the default. That basically means using the Servlet Context is useless for logging configuration.


> Log4j2 configuration during servlet context initialization does not work on Websphere Liberty appserver
> -------------------------------------------------------------------------------------------------------
>
>                 Key: LOG4J2-3577
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3577
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Configuration
>    Affects Versions: 2.17.1
>         Environment: I am using Log4j 2.17.1 on Websphere Liberty 21.0.0.8.
>            Reporter: Carl Froneberger
>            Assignee: Piotr Karwasz
>            Priority: Major
>         Attachments: Log4jWebInitializerImpl.java
>
>
> In my web application, log4j configures itself twice:
>  # before the servlet context is initialized
>  # 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.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)