skip to content

What does a FailureAnalysis contain, and how do built-in analyzers like the port-in-use and missing-bean analyzers use it?

level: middleimportance: should knowfreq 40%

answer

  1. description + action + cause
  2. AbstractFailureAnalyzer<T> walks the cause chain
  3. PortInUseException -> WebServerPortInUseFailureAnalyzer
  4. NoSuchBeanDefinitionException -> missing bean analyzer
  5. return null = skip, non-null = stop

basics

~20 s

FailureAnalysis holds three things: a description (what went wrong), an action (how to fix it), and the original cause. The port-in-use analyzer describes the busy port; the missing-bean analyzer names the required bean and suggests defining it.

solid answer

~40 s

A `FailureAnalysis` is a value object with three fields: `description` (a human sentence about what failed), `action` (concrete remediation steps), and `cause` (the original `Throwable`, so the full error is still available). Built-in analyzers each target one exception type. `WebServerPortInUseFailureAnalyzer` catches `PortInUseException`, reads the port number, and tells you to stop the conflicting process or change `server.port`. `NoSuchBeanDefinitionFailureAnalyzer` catches `NoSuchBeanDefinitionException`, names the missing bean type, explains where it was needed, and suggests defining it or adding the relevant auto-configuration. Analyzers typically extend `AbstractFailureAnalyzer<T>`, which walks the exception chain to find the target cause of type `T` and hands it to the analyzer. If an analyzer doesn't recognize the failure it returns `null`, letting the next one try.

go deeper

for a junior

Know the three fields: description, action, cause.

for a middle

Explain AbstractFailureAnalyzer<T> chain-walking and name port-in-use + missing-bean analyzers.

for a senior

Discuss null-vs-non-null semantics and why you match your own exception type inside wrappers.

for a principal

Reason about analyzer ordering and designing exception types that analyzers can reliably match.

## The FailureAnalysis object `org.springframework.boot.diagnostics.FailureAnalysis` is a plain value holder. Its main constructor is: ```java new FailureAnalysis(String description, String action, Throwable cause) ``` - **description** — one or more sentences saying *what* went wrong, in operator language. - **action** — *what to do* about it (change a property, add a dependency, free a port). - **cause** — the underlying throwable, retained so nothing is lost and tooling can still inspect it. ## AbstractFailureAnalyzer — the base class you almost always use Most analyzers don't implement the raw `FailureAnalyzer` interface directly. They extend: ```java public abstract class AbstractFailureAnalyzer<T extends Throwable> implements FailureAnalyzer { protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause); } ``` `AbstractFailureAnalyzer` implements `analyze(Throwable failure)` by **searching the exception chain** (cause-by-cause) for the first throwable assignable to `T`. If it finds one, it calls your `analyze(rootFailure, cause)`; if not, it returns `null` and the failure is passed to the next analyzer. This is important because the real cause is often wrapped several layers deep (e.g. a `BeanCreationException` wrapping your exception). ## Built-in analyzer examples - **Port in use**: `WebServerPortInUseFailureAnalyzer` targets `PortInUseException`. It extracts `getPort()` and produces a description like "Web server failed to start. Port 8080 was already in use" and an action to stop the process or set a different `server.port`. - **Missing bean**: `NoSuchBeanDefinitionFailureAnalyzer` targets `NoSuchBeanDefinitionException`. It reports the required bean type and the injection point that needed it, and suggests defining a bean of that type. It can even hint that a needed auto-configuration was excluded or conditionally skipped. - **Ambiguous bean**: `NoUniqueBeanDefinitionFailureAnalyzer` — two candidates for one injection point, suggesting `@Primary`/`@Qualifier`. - **Bad config props**: `BindValidationFailureAnalyzer` / `BindFailureAnalyzer` for `@ConfigurationProperties` binding/validation errors. - **Circular reference**: `BeanCurrentlyInCreationFailureAnalyzer`. ## Returning null vs. a FailureAnalysis Returning `null` means "not my failure, skip me." Returning a `FailureAnalysis` means "I've explained this; stop and report it." The **first** analyzer to return a non-null analysis wins; the rest are not consulted for that failure. ## Gotcha Because `AbstractFailureAnalyzer` matches on the exception **type** anywhere in the chain, you register an analyzer against your *own* exception type, not against the generic wrapper Spring throws around it.

  • Why extend AbstractFailureAnalyzer<T> instead of implementing FailureAnalyzer directly?
    Because your target exception is usually buried inside wrapper exceptions (like BeanCreationException). AbstractFailureAnalyzer walks the whole cause chain to find the throwable of type T for you, and returns null automatically when it isn't present.
  • What happens if two analyzers both recognize the same failure?
    The first one (by registration/order) to return a non-null FailureAnalysis wins; the remaining analyzers are not invoked for that failure.

context