1. Overview
A FailureAnalyzer in Spring Boot offers a way to intercept exceptions that occur during the startup of an application causing an application startup failure.
The FailureAnalyzer replaces the stack trace of the exception with a more readable message represented by a FailureAnalysis object that contains a description of the error and a suggested course of action.
Boot contains a series of analyzers for common startup exceptions such as PortInUseException, NoUniqueBeanDefinitionException, and UnsatisfiedDependencyException. These can be found in the org.springframework.boot.diagnostics package.
In this quick tutorial, we’re going to take a look at how we can add our own custom FailureAnalyzer to the existing ones.
2. Creating a Custom FailureAnalyzer
To create a custom FailureAnalyzer, we’ll simply extend the abstract class AbstractFailureAnalyzer – which intercepts a specified exception type and implement analyze() API.
The framework provides a BeanNotOfRequiredTypeFailureAnalyzer implementation that deals with the exception BeanNotOfRequiredTypeException only if the bean being injected is of a dynamic proxy class.
Let’s create a custom FailureAnalyzer that deals with all exceptions of type BeanNotOfRequiredTypeException. Our class intercepts the exception and creates a FailureAnalysis object with helpful description and action messages:
public class MyBeanNotOfRequiredTypeFailureAnalyzer extends AbstractFailureAnalyzer<BeanNotOfRequiredTypeException> { @Override protected FailureAnalysis analyze(Throwable rootFailure, BeanNotOfRequiredTypeException cause) { return new FailureAnalysis(getDescription(cause), getAction(cause), cause); } private String getDescription(BeanNotOfRequiredTypeException ex) { return String.format("The bean %s could not be injected as %s " + "because it is of type %s", ex.getBeanName(), ex.getRequiredType().getName(), ex.getActualType().getName()); } private String getAction(BeanNotOfRequiredTypeException ex) { return String.format("Consider creating a bean with name %s of type %s", ex.getBeanName(), ex.getRequiredType().getName()); } }
3. Registering the Custom FailureAnalyzer
For the custom FailureAnalyzer to be considered by Spring Boot, it is mandatory to register it in a standard resources/META-INF/spring.factories file that contains the org.springframework.boot.diagnostics.FailureAnalyzer key with a value of the full name of our class:
org.springframework.boot.diagnostics.FailureAnalyzer=\ com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer
4. Custom FailureAnalyzer in Action
Let’s create a very simple example in which we attempt to inject a bean of an incorrect type to see how our custom FailureAnalyzer behaves.
Let’s create two classes MyDAO and MySecondDAO and annotate the second class as a bean called myDAO:
public class MyDAO { }
@Repository("myDAO") public class MySecondDAO { }
Next, in a MyService class, we will attempt to inject the myDAO bean, which is of type MySecondDAO, into a variable of type MyDAO:
@Service public class MyService { @Resource(name = "myDAO") private MyDAO myDAO; }
Upon running the Spring Boot application, the startup will fail with the following console output:
*************************** APPLICATION FAILED TO START *************************** Description: The bean myDAO could not be injected as com.baeldung.failureanalyzer.MyDAO because it is of type com.baeldung.failureanalyzer.MySecondDAO$$EnhancerBySpringCGLIB$$d902559e Action: Consider creating a bean with name myDAO of type com.baeldung.failureanalyzer.MyDAO
5. Conclusion
In this quick tutorial, we’ve focused on how implementing a custom Spring Boot FailureAnalyzer.
As always, the full source code of the example can be found over on GitHub.