body {height: 100%; color:#000000; font-size:12pt;
font-family:arial,helvetica,sans-serif;}Hi,
We have multiple Spring Boot 3 WEB apps (exploded WAR files) that need to log
to separate/distinct log files on the same Tomcat 10 server. I was able to
implement this successfully on Tomcat 7, log4j2, Spring 4.x using the following
doc: https://logging.apache.org/log4j/2.3.x/manual/logsep.html and
org.apache.logging.log4j.core.selector.JndiContextSelector. I'm running into
the following exception with the log4j-web-2.23.1.jar with the Tomcat 10/spring
boot deployments:
8-Jan-2025 16:41:17.363 SEVERE [main]
org.apache.catalina.core.StandardContext.listenerStart Error configuring
application listener of class
[org.apache.logging.log4j.web.Log4jServletContextListener]
java.lang.NoClassDefFoundError: javax/servlet/ServletContextListener
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
at
java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at
java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
at
java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
at
java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
at
java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
at
java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
at
java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:593)
at
java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:534)
at java.base/java.lang.Class.forName(Class.java:513)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1316)
at
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1144)
at
org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:491)
at
org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:473)
at
org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:143)
at
org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3922)
at
org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4422)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)
at
org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:599)
at
org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:571)
at
org.apache.catalina.core.StandardHost.addChild(StandardHost.java:654)
at
org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:969)
at
org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1911)
at
java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at
org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at
java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
at
org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:771)
at
org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:423)
at
org.apache.catalina.startup.HostConfig.start(HostConfig.java:1629)
at
org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:303)
at
org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:109)
at
org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:385)
at
org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:332)
at
org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:776)
at
org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:772)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)
at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1203)
at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1193)
at
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at
org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at
java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at
org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:749)
at
org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:203)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)
at
org.apache.catalina.core.StandardService.startInternal(StandardService.java:415)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)
at
org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:870)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)
at org.apache.catalina.startup.Catalina.start(Catalina.java:757)
at
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at
org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
at
org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
Caused by: java.lang.ClassNotFoundException:
javax.servlet.ServletContextListener
at
java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
at
java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:593)
at
java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
... 57 more
The root problem here is the following
classorg.apache.logging.log4j.web.Log4jServletContextListenerhas javax.*
imports rather than jakarta.* imports. Tomcat 10 uses Servlet 6.0 API/spec and
therefore does not support javax.* APIs. I reviewed the source code for the
latest 3.0.0 alpha log4j-web and it is still referencing javax.* packages in
the imports.
Please advise how to implement logging separation on the following specific
stack:
Tomcat 10.1.29Spring Boot 3.3.4log4j 2.23.1Spring 6.1.13Also, I'm currently
trying without a web.xml and I'm noticing only one log4j2-spring.xml file is
being loaded by the log4j2 classloader. So now I'm looking at the
dynamic/programmatic code route to reconfigure via the Configurator but that
doesn't seem to be working either."Log4j is initialized only once by using the
configuration file which is first found by the log4j bootstrapper. All other
(possible present) configuration files will not be taken into account. Learn
more on the precedences of log4j auto configuration in the appropriate
tutorials."
References:https://stackoverflow.com/questions/45185986/log4j2-logging-happening-in-the-wrong-path
https://stackoverflow.com/questions/42712130/two-applications-with-different-log4j2-xml-are-trying-to-log-into-same-logfilehttps://stackoverflow.com/questions/66711660/tomcat-10-x-throws-java-lang-noclassdeffounderror-on-javax-servlet
Arbi Sookazian | Sr Software Engineer | Medata, Inc.
5 Peters Canyon Road, Suite 250
Irvine, CA 92606
[email protected] | www.medata.com