harry
harry

Reputation: 135

@Async giving me error in spring boot application

This is main application class:

@EnableAsync(proxyTargetClass = true)
@EnableDiscoveryClient
@SpringBootApplication
public class ProductApplication {

    public static void main(final String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }

    @Bean("threadPoolTaskExecutor")
    public TaskExecutor getAsyncExecutor() {
        final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("Async-");
        return executor;
    }

}

This is service class:

@Component
public class ProductServiceImpl implements ProductService {

    @Autowired
    ProductRepository productRepository;

    @Autowired
    private ProductHandler productHandler;

    @Async
    @Override
    public List<String> getAllCategories() {
        final List<String> finalList = new ArrayList<>();
        return finalList;
    }

}

This is the controller class:

@RestController
public class ProductResource {

    @Autowired
    private ProductServiceImpl productServiceImpl;

    @GetMapping("/categories")
    public ResponseEntity<List<String>> getAllCategories() {
        return new ResponseEntity<>(this.productServiceImpl.getAllCategories(), HttpStatus.OK);
    }
}

I have annotated the service implementation method with @Async but I get this error:

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.

If I try annotating the controller I get empty response to my get request. I have try every thing including setting proxyTargetClass to true.

Upvotes: 2

Views: 1853

Answers (1)

Nikolas
Nikolas

Reputation: 44496

As long as you use @Async annotation, you have to get familiar with the rules that have to be respected while using it:

  • The method must be public only
  • It cannot be called from a method within the same class (self-invocation)
  • If a return type is used, it has to be wrapped in Future<T>, ex. CompletableFuture<T>

So you get:

CompletableFuture<List<String>> categories = this.productServiceImpl.getAllCategories();

The further handling is driven by the implementation of Future where you can either block the execution or join more of them into a single response...

Upvotes: 3

Related Questions