Search code examples
javaservletstomcat8

Tomcat 8 Embedded - WebServlet - 'A child container failed during start'


I have an embedded Tomcat server that is serving static files just fine. But when I add the buildPath code required to get @WebServlet working, it doesn't work in one of my projects (there are plenty of differences between projects... about 50K lines worth).

I get the following error before web.xml is even read (I know this from strace -ff).

org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:367)
    at app.http.TomcatServer.startTomcat(TomcatServer.java:87)
    at app.main.MainTools.startServer(MainTools.java:277)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:793)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 4 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 6 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:947)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    ... 8 more

seemingly caused by this line:

ctx.setResources(resources);

which is needed to make @WebServlet work, as described here (indeed, WebServlet doesn't work without the setResources, in any project. I and others have some working projects that use the setResources).

strace shows that Tomcat is looking for some files in META-INF:

META-INF/services/java.nio.channels.spi.SelectorProvider
META-INF/services/javax.xml.parsers.SAXParserFactory
META-INF/services/org.apache.juli.logging.Log

While I don't have these files, I also have a working project that does not have these files, so they apparently are not required. I tried creating that log file, because it looked like maybe Juli was trying to tell me something. Alas, it opens the org.apache.juli.logging.Log but writes nothing to it.

strace also reveals that the main Tomcat thread (successfully) stats the following file right before printing the exception:

org/apache/catalina/core/ContainerBase$StartChild.class

Despite all of this activity, it's not stating or looking inside WEB-INF in any way! In fact, there are no accesses to any file named web.xml or pom.xml.

So all the various solutions involving changes to web.xml or pom.xml are irrelevant because Tomcat does not even open those files before generating the LifecycleException.

While others have seen LifecycleException, it appears that this is a new context. For example, others have seen a different form of the exception which has a more helpful exception. Still others are seeing a similar error in standalone Tomcat, but they have the luxury of $CATALINA logs. But I have not found other questions/solutions involving the above, very vague form of the exception in embedded Tomcat.

Also, I set the Java logging level to Level.ALL, and there is much output, but no obviously helpful information. If I grep for INFO and SEVERE I get:

2018.02.26 10:25:39.226 INFO: Initializing ProtocolHandler ["http-nio-8081"]
2018.02.26 10:25:39.241 INFO: Using a shared selector for servlet write/read
2018.02.26 10:25:39.249 INFO: Starting service [Tomcat]
2018.02.26 10:25:39.250 INFO: Starting Servlet Engine: Apache Tomcat/8.5.24
2018.02.26 10:25:39.309 SEVERE: A child container failed during start
2018.02.26 10:25:39.309 SEVERE: A child container failed during start
2018.02.26 10:25:39.312 SEVERE: Failed to start component [StandardServer[-1]]
2018.02.26 10:25:43.485 INFO: Starting shutdown.
2018.02.26 10:25:43.486 INFO: Starting shutdown.

Is there maybe some way I can enable better logging, or maybe call something in Tomcat to have it tell me about all these .jar etc. searches it's trying to do?

Please help. I am new to Tomcat embedded.


Solution

  • You need to combine two solutions:

    First of all, validate the mvn dependency:tree, this can list all dependencies that you have associate with this specific jar servlet-api:jar.

    If you find some dependency that is producing some conflict you can work in two ways:

    1. Remove o replace the dependency (Ex. jetty, camel).
    2. Mark the dependency like provided, that means that will be use for the jar in the point number 1.

    Is so clear that the second options can be the best, but sometimes you need to clean ups your dependencies.

    Note: Be sure that you are using the correct version and Id of the dependency that is listed in the mvn dependency:tree.

    `<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
    </dependency>`
    

    The mvn dependency:tree should produce:

    `+- javax.servlet:javax.servlet-api:jar:3.0.1:provided (scope not updated to 
    compile)`
    

    This only one kind of exception that can produce a jar conflict inside of the container, in this case servlet-api.jar.