Async Spring Boot con Kotlin no funciona

Intento crear un Servicio de spring que realice una operación de forma asíncrona y devuelva un ListenableFuture . Quiero que se active la callback de falla cuando la operación falla; mi bash de hacer esto es usar AsyncResult.forExecutionException como se ve a continuación:

 @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) } } } 

El punto de input:

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

La implementación de Spring RestController es la siguiente:

 @RestController @RequestMapping("/users") class UserController @Autowinetworking constructor( val client: UserClientService ) { @RequestMapping(method = arrayOf(RequestMethod.GET)) fun getUser(@RequestParam(value = "email") email: String): DefernetworkingResult<ResponseEntity<User>> { val result = DefernetworkingResult<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; } } 

El problema es que la callback fallida en el UserController nunca se desencadena cuando se lanza una exception en la UserClientService REST de UserClientService . En cambio, la callback de éxito se desencadena con el argumento de success como null .

¡En Kotlin, puedo verificar si el éxito es nulo usando el success!! – Esto arroja una exception que luego desencadena la callback de failure con el argumento de failure que es el NPE.

La pregunta es ¿cómo puedo activar la callback fallida en el UserController cuando se ha producido una exception en UserClientService ?

La actualización A parece que todo se ejecuta en el mismo hilo "http-nio-8080-exec-XXX" independientemente de si uso @Async o no; vea los comentarios.

Esto todo funciona si:

A) el método fetchUser se declara open , es decir, no es final para que Spring pueda proxy la llamada

…o…

B) creas una interfaz IUserClientService y la usas en el constructor UserController :

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

Ahora el UserClientService implementa la interfaz:

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

Y finalmente el UserController :

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

No estoy seguro de si esto es porque estoy usando Kotlin. Los ejemplos que he visto no requieren la implementación de una interfaz.