Async Spring Boot с использованием Kotlin не работает

Я пытаюсь создать Spring Service, которая выполняет операцию асинхронно и возвращает ListenableFuture . Я хочу, чтобы обратный вызов отказа срабатывал, когда операция AsyncResult.forExecutionException неудачно – моя попытка сделать это заключается в использовании AsyncResult.forExecutionException как показано ниже:

 @Service open class UserClientService { @Async fun fetchUser(email: String): ListenableFuture<User> { val uri = buildUri(email) val headers = buildHeaders() try { val result = restTemplate.exchange(uri, HttpMethod.GET, HttpEntity<Any>(headers), User::class.java) return AsyncResult.forValue(result.body) } catch (e: RestClientException) { return AsyncResult.forExecutionException(e) } } } 

Пункт входа:

 @SpringBootApplication @EnableAsync open class UserProxyApplication fun main(args: Array<String>) { SpringApplication.run(UserProxyApplication::class.java, *args) } 

Реализация Spring RestController выглядит следующим образом:

 @RestController @RequestMapping("/users") class UserController @Autowired constructor( val client: UserClientService ) { @RequestMapping(method = arrayOf(RequestMethod.GET)) fun getUser(@RequestParam(value = "email") email: String): DeferredResult<ResponseEntity<User>> { val result = DeferredResult<ResponseEntity<User>>(TimeUnit.SECONDS.toMillis(10)) client.fetchUser(email).addCallback( { success -> result.setResult(ResponseEntity.ok(success)) }, { failure -> result.setResult(ResponseEntity(HttpStatus.NOT_FOUND)) } ) return result; } } 

Проблема заключается в том, что обратный вызов сбоя в UserController никогда не запускается, если в UserClientService REST UserClientService . Вместо этого обратный вызов успеха запускается с аргументом success равным null .

В Котлине я могу проверить, является ли успех нулевым, используя success!! – это генерирует исключение, которое затем запускает обратный вызов failure аргументом failure являющимся NPE.

Вопрос в том, как я могу вызвать обратный вызов сбоя в UserController когда в UserClientService произошло UserClientService ?

Обновление A Кажется, что все выполняется в том же потоке «http-nio-8080-exec-XXX», независимо от того, использую ли я @Async или нет – см. Комментарии.

    Все это работает, если:

    A) метод fetchUser объявляется open , то есть не окончательным, так что Spring может проксировать вызов

    …или…

    B) вы создаете интерфейс IUserClientService и используете его в конструкторе UserController :

     interface IUserClientService { fun fetchUser(email: String): ListenableFuture<User> } 

    Теперь UserClientService реализует интерфейс:

     @Service open class UserClientService : IUserClientService { @Async override fun fetchUser(email: String): ListenableFuture<User> { // ... rest as shown in question ... 

    И, наконец, UserController :

     @RestController @RequestMapping("/users") class UserController @Autowired constructor( val client: IUserClientService ) { @RequestMapping(method = arrayOf(RequestMethod.GET)) fun getUser(@RequestParam(value = "email") email: String): DeferredResult<ResponseEntity<User>> { // ... rest as shown in question ... 

    Не уверен, что это потому, что я использую Kotlin. Примеры, которые я видел, не требуют реализации интерфейса.