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 asookaz...@medata.com | www.medata.com