1

I'm using Tomcat 10 (actually TomEE but it uses Tomcat 10 underneath) and I'm trying to setup log4j2 logging. I have this half working in that logging to the console happens (I have log output in catalina.log). What I can't get working is the 'Servlet' appender. From the log4j2 docs I have this as my config

<Configuration status="DEBUG" name="MyBlog">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <Servlet name="Servlet">
            <PatternLayout pattern="%m%n%ex{none}"/>
        </Servlet>
    </Appenders>
    <Loggers>
        <Root level="DEBUG">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="Servlet"/>
        </Root>
    </Loggers>

</Configuration>

and in my web.xml I have

    <context-param>
        <param-name>log4jContextName</param-name>
        <param-value>myblog</param-value>
    </context-param>

I have three log4j2 jars deployed, log4j-core, log4j-api and log4j-web and it's version 2.17.1.

I'm seeing three errors in the logs:

2022-01-18 17:42:59,381 http-nio-8080-exec-16 ERROR No servlet context is available
2022-01-18 17:42:59,383 http-nio-8080-exec-16 ERROR Null object returned for Servlet in Appenders.
2022-01-18 17:42:59,386 http-nio-8080-exec-16 ERROR Unable to locate appender "Servlet" for logger config "root"

Any help gratefully received

After adding -Dlog4j2.debug=true

I see this

DEBUG StatusLogger ServletAppender$Builder(logThrowables="null", ignoreExceptions="null", PatternLayout(%m%n%ex{none}), name="Servlet", Configuration(MyBlog), Filter=null, ={})
ERROR StatusLogger No servlet context is available
DEBUG StatusLogger Building Plugin[name=appenders, class=org.apache.logging.log4j.core.config.AppendersPlugin].
ERROR StatusLogger Null object returned for Servlet in Appenders.
DEBUG StatusLogger createAppenders(={Console, })
DEBUG StatusLogger Building Plugin[name=AppenderRef, class=org.apache.logging.log4j.core.config.AppenderRef].
DEBUG StatusLogger createAppenderRef(ref="Console", level="null", Filter=null)
DEBUG StatusLogger Building Plugin[name=AppenderRef, class=org.apache.logging.log4j.core.config.AppenderRef].
DEBUG StatusLogger createAppenderRef(ref="Servlet", level="null", Filter=null)
DEBUG StatusLogger Building Plugin[name=root, class=org.apache.logging.log4j.core.config.LoggerConfig$RootLogger].
DEBUG StatusLogger createLogger(additivity="null", level="DEBUG", includeLocation="null", ={Console, Servlet}, ={}, Configuration(MyBlog), Filter=null)
DEBUG StatusLogger Building Plugin[name=loggers, class=org.apache.logging.log4j.core.config.LoggersPlugin].
DEBUG StatusLogger createLoggers(={root})
ERROR StatusLogger Unable to locate appender "Servlet" for logger config "root"

BTW I get similar output if I set the log-level to DEBUG in the console appender

1 Answers1

2

Due to the namespace changes between Java EE 8 and Jakarta EE 9 (cf. Eclipse website for example) you need to use log4j-jakarta-web instead of log4j-web.

In Maven format you require:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-jakarta-web</artifactId>
    <version>2.17.1</version>
</dependency>

Edit: There seems to be a small bug in log4j-jakarta-web, which prevents the ServletContainerInitializer to start. I added PR #723. In the meantime you can declare a Log4jServletContextListener in your web.xml:

  <listener>
    <description>Initializes Log4j 2.x</description>
    <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
  </listener>
Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43
  • Thanks for replying but I'm still seeing the error – Kevin Jones Jan 18 '22 at 20:11
  • You can try running the server with `-Dlog4j2.debug=true` to see if the `ServletContainerInitializer` that comes with `log4j-jakarta-web` is running. – Piotr P. Karwasz Jan 18 '22 at 21:52
  • I've update the original question – Kevin Jones Jan 19 '22 at 08:11
  • There was a bug in `log4j-jakarta-web`. I modified my answer accordingly. – Piotr P. Karwasz Jan 20 '22 at 02:14
  • Thanks Piotr. One other thing, when I do a log.debug it is labelled as 'DEBUG' in the console output but 'INFO' in the Servlet output, is that what you'd expect? – Kevin Jones Jan 20 '22 at 10:10
  • Yes, that is expected. [`ServletContext#log`](https://jakarta.ee/specifications/servlet/5.0/apidocs/jakarta/servlet/servletcontext#log(java.lang.String)) does not have a level parameter. Tomcat assigns `INFO` to each message logged this way. That is why the `Servlet` appender is rarely used. A better option is to [replace Tomcat's logging system with Log4j 2.x](https://logging.apache.org/log4j/2.x/log4j-appserver/index.html). – Piotr P. Karwasz Jan 20 '22 at 10:28