3
votes

I am trying to run a function in background asynchronously. For this I am trying Spring's @Async annotation but my application is unable to start after putting this annotation on the function.

I tried

@EnableAsync(proxyTargetClass = true)

but still no luck.

Below is the message I am getting on application start.


APPLICATION FAILED TO START


Description:

The bean 'MyBatchSyncProcessor' could not be injected as a 'com.a.b.c.service.MyBatchSyncProcessor' because it is a JDK dynamic proxy that implements: com.a.b.c.service.BaseSyncProcessor

Action:

Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.

Please help me out in getting this application up and running.

2
Are you trying to Autowire or Inject com.a.b.c.service.MyBatchSyncProcessor somewhere in your code? - Ervin Szilagyi
Add your code first! - ikos23
Yes, through constructor I am trying to do autowiring. - San
You should inject the interface instead of the implementation. I'm guessing com.a.b.c.service.BaseSyncProcessor is an interface. - Ervin Szilagyi
@San The class with @Async method maybe :) Don't think it makes sense to add String.java source code or smth. like that. - ikos23

2 Answers

2
votes

Don't inject your service implementation (MyBatchSyncProcessor) - inject its interface BaseSyncProcessor.

1
votes

Although the first answer is correct, it doesn't really touches on why:

From https://www.fatalerrors.org/a/0dx20j8.html :

Async registers a Configuration configuration class with Spring using Spring's ImportSelector method, and injects a BeanPostProcessor, which calls the postProcessAfterInitialization method after the bean is instantiated to generate dynamic proxies for the object (if the target class implements an interface, the JDK proxy is used by default, otherwise CGLib is used)

When you combine this with :

(https://www.tutorialspoint.com/difference-between-jdk-dynamic-proxy-and-cglib-proxy-in-spring)

JDK dynamic proxy is available with the JDK. It can be only proxy by interface so target class needs to implement interface. In your is implementing one or more interface then spring will automatically use JDK dynamic proxies.

Now it becomes apparent that once you add the @EnableAsync aspect, you need to inject the interface BaseSyncProcessor rather than its implementation MyBatchSyncProcessor, in beans that use the @Async annotation.