Home > Software engineering >  How to inject a bean into CacheErrorHandler
How to inject a bean into CacheErrorHandler

Time:10-29

I'm on spring framework version 5.3.23, spring boot version 2.7.0

I know I can extend CachingConfigurerSupport to provide a CacheErrorHandler for handling cache layer errors. However, the interface of the bean creation is:

interface CachingConfigurer {
  public CacheErrorHandler errorHandler();
}

My problem is: we need to inject some other beans into this CacheErrorHandler bean. The interface does not allow me to do that. Is there another way to configure a CacheErrorHandler bean with injection? If I simply declare a regular CacheErrorHandler bean, would it be automatically discovered by the cache configuration?

Thanks.

CodePudding user response:

No, only get CacheErrorHandler from the CachingConfigurer bean

CodePudding user response:

Well, technically, the previous answer is wrong!

In fact, you can inject other bean dependencies/collaborators into Spring Cache infrastructure components, such as a CacheErrorHandler (Javadoc) when implementing the CachingConfigurer interface (Javadoc), although maybe not in a way you might expect.

I have demonstrated your use case in this test class.

In summary:

  • My test configuration implements the CachingConfigurer.

  • I override the errorHandler() method to return a "custom" CacheErrorHandler. Also see the TestCacheErrorHandler (custom) implementation, here.

  • As you can see, the TestCacheErrorHandler requires a Logger.

  • The Logger is declared and configured as a bean in the Spring container (ApplicationContext).

NOTE: Now, you could imagine the Logger being replaced by a sophisticated management/monitoring service using Micrometer, or perhaps a backend database. This was a test and I wanted to minimize the dependencies and complexity to focus on the problem at hand.

TIP: The key to this injection (autowiring), is that the bean method for the "mockLogger" bean is "proxied" by Spring (using CGLIB (class-based) proxy (as opposed to interface based proxying JDK Dynamic Proxies)). This allows the actual mockLogger bean to be inject and not some arbitrary object. This implicit in the @SpringBootConfiguration annotation declaration, where the proxyBeanMethods is by default, set to true. If I change this configuration to proxyBeanMethods set to false, the test will fail, since the CacheErrorHandler will get a reference to an unmanaged Logger. See the Javadoc for @SpringBootConfiguration for more details.

  • The test case method goes on to assert and verify that the proper interactions happen based on the bean invocations.

NOTE: I used mock Spring Cache infrastructure components to precisely control the Cache behavior, such as simulating an error that would necessarily involve custom CacheErrorHandler in my test. The mock infrastructure will also allow you to test other caching infrastructure components (such as a custom CacheResolver) or caching behaviors in a similar manner.

Ultimately, the test proves and demonstrates that you can inject other dependencies into caching infrastructure components, using preferably constructor injection (which is truly the only Thread-safe way to wire collaborators, especially in a multi-Threaded environment, such as a Web application, providing the this reference does not escape during construction of course ;-) ).

As 1 final test, I also tested and demonstrated that it is also possible to declare the "custom" CacheErrorHandler as a Spring "bean" managed by the Spring container and inject (autowire) additional dependencies (and here) using (field-based) setter injection (not recommended, but also possible).

The 2 key things in this test case is this and this.

If you have additional questions, please post in the comments, but I think the test class is pretty self-explanatory.

Cheers!

  • Related