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.