Excepción de puntero nulo en Spring Proxy Class y Kotlin

Estoy enfrentando algunos problemas con kotlin junto con la spring.

Tengo un bean de controller (sin una interfaz btw) que tiene un bean de service autoalambrado a través del constructor primario.

Funciona perfectamente a less que use annotations de almacenamiento en caching para el controller. Aparentemente, el almacenamiento en caching genera una class de proxy bajo el capó que trata sobre el almacenamiento en caching.

Mi código se ve así:

@RestController @RequestMapping("/regions/") open class RegionController @Autowinetworking constructor(val service: RegionService) { @RequestMapping("{id}", method = arrayOf(RequestMethod.GET)) @Cacheable(cacheNames = arrayOf("regions")) fun get(@PathVariable id: Long): RegionResource { return this.service.get(id) } } 

El problema ahora es una exception de puntero nulo cuando se ejecuta el método, en realidad this.service es null que técnicamente no es posible ya que es una variable no nula en kotlin.

Supongo que los proxies de class generados por la spring inicializan la class con valores nulos en lugar del bean autocableado. Esta debe ser una trampa común usando kotlin y spring. ¿Cómo evadiste este problema?

En Kotlin, tanto las classs como los miembros son finales por defecto.

Para que la biblioteca de proxy ( CGLIB , javaassist ) pueda proxy de un método, debe declararse como no final y en una class no final ( ya que esas bibliotecas implementan el proxy mediante la creación de subclasss ). Cambie su método de controller a:

 @RequestMapping("{id}", method = arrayOf(RequestMethod.GET)) @Cacheable(cacheNames = arrayOf("regions")) open fun get(@PathVariable id: Long): RegionResource { return this.service.get(id) } 

Es probable que vea una advertencia en la console sobre los methods de RegionController que no están sujetos a proxying.

El complemento del comstackdor Kotlin

El equipo de Kotlin ha reconocido esta dificultad y ha creado un complemento que marca los candidatos de proxy AOP estándar, por ejemplo, @Component con open .

Puede habilitar el complemento en su build.gradle :

 plugins { id "org.jetbrains.kotlin.plugin.spring" version "1.1.60" } 

Pronto esto podría no ser un problema por más time.

Hay un trabajo en progreso que cualquier lib (incluyendo la spring, por ejemplo) puede especificar una list de annotations de un file en META-INF. Una vez que una class se anota con uno de estos, se abrirá de manera pnetworkingeterminada para la class misma y todas sus funciones. Esto también es cierto para las classs henetworkingadas de una class anotada.

Para get más información, consulte https://github.com/Kotlin/KEEP/pull/40#issuecomment-250773204.

  • Exception Handler no funciona con `spring-boot-starter-data-rest`
  • Spring MVC Error 404 Bad Request Kotlin
  • No se puede publicar contenido web dynamic con Spring Boot y Kotlin
  • Spring Boot .mustache Extensión de file
  • Tenga la security de que multiparte es nulo en el controller de descanso
  • Spring Boot e Hibernate. Manejar la fábrica de sesiones
  • No se puede conectar a Remote Mongo DB mediante Springboot
  • Spring Data JPA / Hibernate "No se puede ubicar Attribute con el nombre de stack"
  • ¿Por qué Kotlin con Spring MVC JSON devuelve un object vacío?
  • No puedo excluir MongoAutoConfiguration en Springboot-Kotlin (MongoSocketOpenException)
  • Integración de HTML y CSS con Kotlin y Spring MVC