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

Nick Williams edited comment on LOG4J2-223 at 5/28/13 9:10 PM:
---------------------------------------------------------------

Okay, based on all of this, here are my suggestions on how I would improve this 
(sorry for my scarcity lately ... trying to catch up on chapters for the book). 
These suggestions are based on the following goals:

# Design web application support so that users of simple Log4j configurations 
(not using JNDI lookups for logging configuration) don't have to do any 
additional configuration to get Log4j to "just work" in a Servlet container. 
This goal is made with the understanding that this is only possible for users 
of Servlet 3.0, 3.1, or higher. Users of Servlet 2.5 will have to manually 
configure listeners and filters. It's the only way.
# Eliminate the need for web applications to have an additional JAR just to 
support proper configuration.
# Improve the documentation considerably so that it is abundantly clear how 
Log4j works in web applications.

With these goals in mind, here are my recommendations:

* Get rid of the log4j-web module and move this stuff into log4j-core. We'll 
need [~timothyjward]'s input on how this could impact OSGi support. In theory, 
I don't think we should have a problem. No other Log4j classes will refer to 
the listener or filter. These classes will only ever get loaded BY the Servlet 
container, in which case the Servlet API will already be loaded, so I don't 
think it would be possible to get {{NoClassDefFoundError}} s.
* Create a {{/META-INF/web-fragment.xml}} file with the contents noted below. 
This will ensure that the Log4j fragment is loaded before any other fragments.
* Create a {{Log4jWebInitializer}} class (doesn't implement any interfaces, 
package-private) to properly initialize and de-initialize Log4j in a Servlet 
container. It works like this: If the context parameters currently required by 
the {{JNDIContextFilter}} exist, it initializes Log4j the way 
{{JNDIContextFilter}} currently does. If they don't exist, it initializes Log4j 
the way {{Log4jContextListener}} currently does.
* Create a {{Log4jServletContainerInitializer implements 
ServletContainerInitializer}} and a 
{{/META-INF/services/javax.servlet.ServletContainerInitializer}} file to go 
along with it. This initializer:
** Initializes Log4j properly using the {{Log4jWebInitializer}}.
** Installs a private listener to de-initialize Log4j when the container shuts 
down the application using the {{Log4jWebInitializer}}.
** Installs the {{NamedContextFilter}} (renamed from {{JNDIContextFilter}}), 
which doesn't do any initialization/deinitialization, it just does what it 
currently does for {{doFilter}}.
* Change the existing {{Log4jContextListener}} to use the 
{{Log4jWebInitializer}}.
* Create a new manual page directly under the "MANUAL" menu heading on the 
homepage that explains how to use Log4j in a Servlet container:
** If you're using Servlet 3.0 or higher, it "just works," but if you're also 
using JNDI you need to create the proper context parameters.
** If you're using Servlet 2.5, you MUST add the {{Log4jContextListener}} (and 
the {{NamedContextFilter}} and context parameters if you're using JNDI) to your 
deployment descriptor.

Now, to address some questions:

# "What to do about JBoss 5, which doesn't support web-fragment.xml?" JBoss 5 
doesn't support web-fragment.xml because it's a Servlet 2.5 container, not a 
Servlet 3.0 container. Users of JBoss 5 would follow the Servlet 2.5 
instructions just like all other users. Users of JBoss 6, 7, 8, etc., would 
follow the Servlet 3.0 instructions ("don't do anything").
# "A container with multiple web applications. The Log4j jars are in the Tomcat 
classpath and they all share the same configuration file." versus "A container 
with multiple web applications. Each has their own copy of the log4j jars and 
each has their own configuration file." Easy! The 
{{Log4jServletContainerInitializer}} will get executed for every application, 
whether the Log4j JARs are in the Tomcat classpath or in /WEB-INF/lib (this is 
per the Servlet specification). Each application will get its own context. 
Regardless of where the JARs are, that context will load the application's 
configuration file if it has its own, and will load the shared configuration if 
it doesn't have its own.

Thoughts?

{code:xml|title=web-fragment.xml}<web-fragment ... metadata-complete="true">
    <name>log4j</name>
    <distributable/>
    <ordering>
        <before>
            <others/>
        </before>
    </ordering>
</web-fragment>{code}
                
      was (Author: beamerblvd):
    Okay, based on all of this, here are my suggestions on how I would improve 
this (sorry for my scarcity lately ... trying to catch up on chapters for the 
book). These suggestions are based on the following goals:

# Design web application support so that users of simple Log4j configurations 
(not using JNDI looks for logging) don't have to do any additional 
configuration to get Log4j to "just work" in a Servlet container. This goal is 
made with the understanding that this is only possible for users of Servlet 
3.0, 3.1, or higher. Users of Servlet 2.5 will have to manually configure 
listeners and filters. It's the only way.
# Eliminate the need for web applications to have an additional JAR just to 
support proper configuration.
# Improve the documentation considerably so that it is abundantly clear how 
Log4j works in web applications.

With these goals in mind, here are my recommendations:

* Get rid of the log4j-web module and move this stuff into log4j-core. We'll 
need [~timothyjward]'s input on how this could impact OSGi support. In theory, 
I don't think we should have a problem. No other Log4j classes will refer to 
the listener or filter. These classes will only ever get loaded BY the Servlet 
container, in which case the Servlet API will already be loaded, so I don't 
think it would be possible to get {{NoClassDefFoundError}} s.
* Create a {{/META-INF/web-fragment.xml}} file with the contents noted below. 
This will ensure that the Log4j fragment is loaded before any other fragments.
* Create a {{Log4jWebInitializer}} class (doesn't implement any interfaces, 
package-private) to properly initialize and de-initialize Log4j in a Servlet 
container. It works like this: If the context parameters currently required by 
the {{JNDIContextFilter}} exist, it initializes Log4j the way 
{{JNDIContextFilter}} currently does. If they don't exist, it initializes Log4j 
the way {{Log4jContextListener}} currently does.
* Create a {{Log4jServletContainerInitializer implements 
ServletContainerInitializer}} and a 
{{/META-INF/services/javax.servlet.ServletContainerInitializer}} file to go 
along with it. This initializer:
** Initializes Log4j properly using the {{Log4jWebInitializer}}.
** Installs a private listener to de-initialize Log4j when the container shuts 
down the application using the {{Log4jWebInitializer}}.
** Installs the {{NamedContextFilter}} (renamed from {{JNDIContextFilter}}), 
which doesn't do any initialization/deinitialization, it just does what it 
currently does for {{doFilter}}.
* Change the existing {{Log4jContextListener}} to use the 
{{Log4jWebInitializer}}.
* Create a new manual page directly under the "MANUAL" menu heading on the 
homepage that explains how to use Log4j in a Servlet container:
** If you're using Servlet 3.0 or higher, it "just works," but if you're also 
using JNDI you need to create the proper context parameters.
** If you're using Servlet 2.5, you MUST add the {{Log4jContextListener}} (and 
the {{NamedContextFilter}} and context parameters if you're using JNDI) to your 
deployment descriptor.

Now, to address some questions:

# "What to do about JBoss 5, which doesn't support web-fragment.xml?" JBoss 5 
doesn't support web-fragment.xml because it's a Servlet 2.5 container, not a 
Servlet 3.0 container. Users of JBoss 5 would follow the Servlet 2.5 
instructions just like all other users. Users of JBoss 6, 7, 8, etc., would 
follow the Servlet 3.0 instructions ("don't do anything").
# "A container with multiple web applications. The Log4j jars are in the Tomcat 
classpath and they all share the same configuration file." versus "A container 
with multiple web applications. Each has their own copy of the log4j jars and 
each has their own configuration file." Easy! The 
{{Log4jServletContainerInitializer}} will get executed for every application, 
whether the Log4j JARs are in the Tomcat classpath or in /WEB-INF/lib (this is 
per the Servlet specification). Each application will get its own context. 
Regardless of where the JARs are, that context will load the application's 
configuration file if it has its own, and will load the shared configuration if 
it doesn't have its own.

Thoughts?

{code:xml|title=web-fragment.xml}<web-fragment ... metadata-complete="true">
    <name>log4j</name>
    <distributable/>
    <ordering>
        <before>
            <others/>
        </before>
    </ordering>
</web-fragment>{code}
                  
> IllegalStateException thrown during Tomcat shutdown
> ---------------------------------------------------
>
>                 Key: LOG4J2-223
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-223
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.0-beta5
>            Reporter: Ralph Goers
>            Priority: Critical
>             Fix For: 2.0-beta7
>
>         Attachments: log4j-223.war
>
>
> {noformat}Apr 25, 2013 3:03:33 PM org.apache.catalina.core.StandardServer 
> await
> INFO: A valid shutdown command was received via the shutdown port. Stopping 
> the Server instance.
> Apr 25, 2013 3:03:33 PM org.apache.coyote.AbstractProtocol pause
> INFO: Pausing ProtocolHandler ["http-nio-8080"]
> Apr 25, 2013 3:03:33 PM org.apache.coyote.AbstractProtocol pause
> INFO: Pausing ProtocolHandler ["ajp-nio-8009"]
> Apr 25, 2013 3:03:33 PM org.apache.catalina.core.StandardService stopInternal
> INFO: Stopping service Catalina
> Apr 25, 2013 3:03:33 PM org.apache.coyote.AbstractProtocol stop
> INFO: Stopping ProtocolHandler ["http-nio-8080"]
> Apr 25, 2013 3:03:33 PM org.apache.coyote.AbstractProtocol stop
> INFO: Stopping ProtocolHandler ["ajp-nio-8009"]
> Apr 25, 2013 3:03:33 PM org.apache.coyote.AbstractProtocol destroy
> INFO: Destroying ProtocolHandler ["http-nio-8080"]
> Apr 25, 2013 3:03:33 PM org.apache.coyote.AbstractProtocol destroy
> INFO: Destroying ProtocolHandler ["ajp-nio-8009"]
> Apr 25, 2013 3:03:33 PM org.apache.catalina.loader.WebappClassLoader loadClass
> INFO: Illegal access: this web application instance has been stopped already. 
>  Could not load org.apache.logging.log4j.core.config.NullConfiguration.  The 
> eventual following stack trace is caused by an error thrown for debugging 
> purposes as well as to attempt to terminate the thread which caused the 
> illegal access, and has no functional impact.
> java.lang.IllegalStateException
>       at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1351)
>       at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1310)
>       at 
> org.apache.logging.log4j.core.LoggerContext.stop(LoggerContext.java:171)
>       at 
> org.apache.logging.log4j.core.LoggerContext$ShutdownThread.run(LoggerContext.java:389)
> Exception in thread "Thread-18" java.lang.NoClassDefFoundError: 
> org/apache/logging/log4j/core/config/NullConfiguration
>       at 
> org.apache.logging.log4j.core.LoggerContext.stop(LoggerContext.java:171)
>       at 
> org.apache.logging.log4j.core.LoggerContext$ShutdownThread.run(LoggerContext.java:389)
> Caused by: java.lang.ClassNotFoundException: 
> org.apache.logging.log4j.core.config.NullConfiguration
>       at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1465)
>       at 
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1310)
>       ... 2 more{noformat}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to