I work on a company-wide framework (reusable libraries) for all Spring Boot applications in a large enterprise. We support hundreds of Boot microservices based on the framework. This context limits certain solutions available to me (more below).
What are my options to intercept BeanCreationException
s that happen during auto-wiring of a Spring Boot app startup?
Context (probably too much for most readers to care):
During autowiring BeanCreationException
can occur due to typical, but foreseeable, mistakes or choices made by developers. One of those is the use of @Resource
to auto-wire fields. This is a somewhat common practice in our company but has subtle "gotchas," especially its behavior compared to using @Autowire
*.
One of my team's purposes is improving Developer Experience - including helping prevent, or at least highlight, common mistakes. To that end, when a BeanCreationException
is thrown due to something that can be explained in our context, we'd like to offer a more specific error message than the default. For example, with @Resource
you can (easily?) get BeanNotOfRequiredTypeException
due to the name-first matching that Spring does. I want to intercept that and throw with a more specific message or at least log out our custom message in addition to the exception.
Due to my situation not in a specific application/service, no solution that involves changing the usage of @Resource
or modifying the main Application class, is feasible. I need to provide a plug-and-play solution to the hundreds of apps/services we support. Ideally something I can inject from the library or that requires a minimal (ie, config-only) update to every service.
*@Autowire
matches first based on the type of the declared field, whereas @Resource
matches first based on bean name.
Thanks to the comment by @m-deinum I was able to accomplish what I needed by writing a FailureAnalyzer
and registering it. There are several good tutorials about doing so, but here's the gist of what I did.
Wrote a class that extends AbstractFailureAnalyzer<T>
, where T
is the type of exception I wanted to handle. In the situation of the original question, that was BeanNotOfRequiredTypeException
.
a. In my case, the exception type BeanNotOfRequiredTypeException
contains plenty of details about the problem so I was easily able to filter down to the exact scenario(s) I was interested in. Specifically, BeanNotOfRequiredTypeException.getRequiredType()
and BeanNotOfRequiredTypeException.getActualType()
.
Registered my custom analyzer in the META-INF/spring.factories file, like this:
org.springframework.boot.diagnostics.FailureAnalyzer=my.fully.qualified.package.ClassTypeMismatchAnalyzer