Missing Structured Failure Report in Spring Boot WAR Deployments
0 reputation · 27 Dec 2021, 00:27 UTC
0 reputation · 27 Dec 2021, 00:27 UTC
When a Spring Boot application fails to start, the framework normally logs a structured failure analysis report that includes a description and suggested action.
However, when the same application is packaged as a WAR and deployed to an external servlet container (e.g., Tomcat, Jetty), the container’s lifecycle may surface the raw exception without invoking SpringBoot’s FailureAnalyzer chain, leaving the diagnostic report absent from the logs.
This raises uncertainty about whether the missing report indicates a gap in the built‑in analysis or simply a deployment‑mode limitation, and whether adding a domain‑specific FailureAnalyzer would provide useful guidance.
Does Spring Boot emit a FailureAnalyzer report for startup failures that occur during external‑container WAR deployment?
Under what circumstances does the container suppress or replace the structured analysis output?
Should a custom FailureAnalyzer be registered to capture deployment‑specific failures, and how can its invocation be confirmed in this mode?
Spring Boot will emit a FailureAnalyzer report only when the failure occurs after the SpringApplication instance has been created and the context refresh is attempted. In a WAR deployed to an external servlet container (Tomcat, Jetty, etc.) this happens if the exception is thrown during the SpringBootServletInitializer‑driven startup. If the exception occurs earlier – e.g., during ServletContainerInitializer processing, class‑loading issues, or before Spring’s logging system is initialized – the container logs the raw exception and the FailureAnalyzer chain is not invoked, so no structured report appears.
SpringApplication.run(...) throws an exception.SpringBootServletInitializer creates the SpringApplication and calls run; any exception thrown from that point triggers the FailureAnalyzer chain.org.apache.catalina.core.StandardContext logging) can intercept and log exceptions before Spring gets a chance to run its analyzers.System.err and be missed in the container’s log files.ERROR level).logging.level.org.springframework.boot.diagnostics=DEBUG to application.properties (or via -Dlogging.level.org.springframework.boot.diagnostics=DEBUG on the JVM).onStartup completes. Examine the container’s early‑startup logs for class‑not‑found, missing servlet‑container‑initializer, or bean‑definition‑loading errors.FailureAnalyzer (annotate with @Component or declare in META-INF/spring.factories) and ensure it is on the classpath of the WAR. Its analyze method will be called only for failures that reach the SpringApplication refresh step.log.error("[CustomAnalyzer] triggered for {}", failure.getMessage());) inside your analyzer and verifying it appears in the logs when the failure occurs.Knowing whether the exception is thrown before or after SpringBootServletInitializer’s onStartup method would determine if a custom FailureAnalyzer can help. If you can share the exact stack trace or the phase (e.g., "ServletContainerInitializer", "context refresh", "bean creation"), I can advise whether adding a FailureAnalyzer is appropriate or if the issue must be resolved at the container or class‑path level.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 27 Dec 2021, 05:38 UTC
One clarification worth adding to the existing answer: unlike auto-configurations, which moved from META-INF/spring.factories to .imports files in Spring Boot 3.x, FailureAnalyzer registration did not migrate. In both Boot 2.x and 3.x, custom analyzers are still declared in META-INF/spring.factories under the key org.springframework.boot.diagnostics.FailureAnalyzer. Creating a .imports file for an analyzer will simply leave it undiscovered — a silent failure that is easy to misread as a WAR-deployment problem.
For confirming invocation in WAR mode, the most reliable check is the formatted APPLICATION FAILED TO START banner in the container logs (e.g., Tomcat's catalina.out). If the banner is absent even though the failure clearly occurred after SpringBootServletInitializer began running, suspect container-level interception or logging initialization order rather than a registration issue. A deliberate failure triggered by a missing required property is a good controlled test, since it fails late enough for the analyzer chain and logging to be fully active.