Shaddy Baddah created LOG4J2-459:
------------------------------------

             Summary: Race condition on Web app configuration prevents 
${web:initParam. lookup
                 Key: LOG4J2-459
                 URL: https://issues.apache.org/jira/browse/LOG4J2-459
             Project: Log4j 2
          Issue Type: Bug
          Components: Core
    Affects Versions: 2.0-beta9
            Reporter: Shaddy Baddah
            Priority: Minor


I am happy for someone to challenge me on this assertion, but I cannot see how 
${web:initParam.*} notation in XML configuration could ever work in 2.0-beta9 
at least. Well at least for bootstrapped config.

I have a Web application that includes an XML configfile in the WAR at:

WEB-INF/classes/log4j2.xml

The file looks something like this:

?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<File name="file" fileName="${web:initParam.myapp.logdir}/myapp.log" 
append="true">
        <PatternLayout pattern="%d [%t] %-5p %c - %m%n"/>
</File>
</Appenders>
<Loggers>
<Root level="warn">
<AppenderRef ref="file"/>
 </Root>
</Loggers>
</Configuration>

For the uninitiated, a recap on how ${web:initParam.myapp.logdir} is resolved, 
to the best of my understanding.

The ${web: prefix will indicate to log4j2 that it should use the WebLookup 
class to resolve what comes after it; initParam.myapp.logdir.

WebLookup will then check if that key is prefixed with initParam. (as well as 
another attr type prefix), and seeing that it is, will use the remainder as the 
real key name: myapp.logdir.

It then calls getInitParameter() with that key on the ServletContext for the 
parent web application. That should pluck a value that could, for example, be 
configured in the web.xml like this:

     <context-param>
    <param-name>myapp.logdir</param-name>
    <param-value>c:/myapp_logs</param-value>
    </context-param>

However, this is where there is a race condition. To get the ServletContext , 
the WebLookup.lookup() method will call its own getServletContext() method. 
This in term attempt to get the ServletContext from the LogManager singleton, 
which stores it as an untyped (java.lang.Object) externalContext concept.

For a Web App, this externalContext is not being set ahead of the bootstrapping 
parse of the XML config file.The problem can be seen in the sequencing of 
instructions in the Configurator.initialize() method:

    public static LoggerContext initialize(final String name, final ClassLoader 
loader, final URI configLocation,
                                           final Object externalContext) {

        try {
            final org.apache.logging.log4j.spi.LoggerContext context = 
LogManager.getContext(loader, false, configLocation);
            if (context instanceof LoggerContext) {
                final LoggerContext ctx = (LoggerContext) context;
                ContextAnchor.THREAD_CONTEXT.set(ctx);
                if (externalContext != null) {
                    ctx.setExternalContext(externalContext);
                }

This line:

            final org.apache.logging.log4j.spi.LoggerContext context = 
LogManager.getContext(loader, false, configLocation);

kicks-off the boostrapped parse of the XML config, that in turn utilizes 
WebLookup.lookup().

You can see however that ctx.setExternalContext(externalContext) is called 
after.

Simple reasoning suggests that this initialization could be moved ahead. 
However this code applies to non-web apps too, and being not familiar with the 
design and intentions, I'd be very appreciative of someone looking into a fix 
for this.

Thanks.





--
This message was sent by Atlassian JIRA
(v6.1#6144)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to