Q: Tomcat 9.0.50 and log4j2 issue I have upgraded from log4j1.2 to to log4j2.17. After upgrading 3 jar files (log4j-core-2.17.1.jar, log4j-api-2.17.1.jar, log4j-1.2-api-2.17.1.jar) app is working fine.
Now when I want to remove the bridge ('log4j-1.2-api-2.17.1.jar') between log4j1.2 and log4j2.17.
When I remove this jar file, I get an error on server start-up. Does tomcat9 support log4j2 only with the bridge ?
SEVERE [main] org.apache.catalina.startup.HostConfig.deployDescriptor Error deploying deployment descriptor [D:\Project\tomcat\conf\Catalina\localhost\project.xml]
    java.lang.IllegalStateException: Error starting child
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:731)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:700)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:696)
        at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:690)
        at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1889)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
        at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:583)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:473)
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1618)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:319)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
        at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:948)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1388)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:921)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:437)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:934)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:772)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)
    Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/compass]]
        at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:728)
        ... 37 more
    Caused by: java.lang.NoClassDefFoundError: Lorg/apache/log4j/Logger;
        at java.base/java.lang.Class.getDeclaredFields0(Native Method)
        at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3061)
        at java.base/java.lang.Class.getDeclaredFields(Class.java:2248)
        at org.apache.catalina.util.Introspection.getDeclaredFields(Introspection.java:104)
        at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:269)
        at org.apache.catalina.startup.WebAnnotationSet.loadApplicationServletAnnotations(WebAnnotationSet.java:137)
        at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:69)
        at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:332)
        at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:989)
        at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:303)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5135)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        ... 38 more
    Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1407)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1215)
        ... 51 more


A: Your problem occurs during the Servlet 3.0 annotation scanning phase of your application's startup:

*

*first Tomcat scans your application's classpath for classes annotated with @WebServlet and other similar annotations,

*then Tomcat uses reflection to inject fields into the previously discovered classes. Reflection actually loads and validates all those classes and here your application fails.

Finding out which library is responsible for this is not easy: look for libraries containing servlets or a META-INF/web-fragment.xml file.
You can mitigate the problem by adding metadata-complete="true" to your web.xml descriptor:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="true">
    ...
</web-app>

