Currently I try to rewrite my Java Spring Boot Application with Kotlin. I encountered a problem that in all of my classes which are annotated with @Service
the dependency injection is not working correctly (all instances are null
). Here is an example:
@Service @Transactional open class UserServiceController @Autowired constructor(val dsl: DSLContext, val teamService: TeamService) { //dsl and teamService are null in all methods }
Doing the same in Java works without any problems:
@Service @Transactional public class UserServiceController { private DSLContext dsl; private TeamService teamService; @Autowired public UserServiceController(DSLContext dsl, TeamService teamService) { this.dsl = dsl; this.teamService = teamService; }
If I annotate the component with @Component
in Kotlin everything works fine:
@Component open class UserServiceController @Autowired constructor(val dsl: DSLContext, val teamService: TeamService) { //dsl and teamService are injected properly }
Google provided many different approaches for Kotlin and @Autowired
which I tried but all resulted in the same NullPointerException
I would like to know what the difference between Kotlin and Java is and how I can fix this?
The field annotated @Autowired is null because Spring doesn't know about the copy of MileageFeeCalculator that you created with new and didn't know to autowire it.
When @Autowired doesn't work. There are several reasons @Autowired might not work. When a new instance is created not by Spring but by for example manually calling a constructor, the instance of the class will not be registered in the Spring context and thus not available for dependency injection.
The @Autowired annotation provides more fine-grained control over where and how autowiring should be accomplished. The @Autowired annotation can be used to autowire bean on the setter method just like @Required annotation, constructor, a property or methods with arbitrary names and/or multiple arguments.
Kotlin @Autowired constructor injection This annotation instructs the Spring framework to inject the owner dependency into the Car bean.
I just bumped into exactly same issue - injection worked well, but after adding @Transactional annotation all the autowired fields are null.
My code:
@Service @Transactional open class MyDAO(val jdbcTemplate: JdbcTemplate) { fun update(sql: String): Int { return jdbcTemplate.update(sql) } }
The problem here is that the methods are final by default in Kotlin, so Spring is unable to create proxy for the class:
o.s.aop.framework.CglibAopProxy: Unable to proxy method [public final int org.mycompany.MyDAO.update(...
"Opening" the method fixes the issue:
Fixed code:
@Service @Transactional open class MyDAO(val jdbcTemplate: JdbcTemplate) { open fun update(sql: String): Int { return jdbcTemplate.update(sql) } }
I faced the same problem working with Kotlin but the null instance was a JpaRepository. When I added the @Transactional
annotation to a method inside a service, I got a message saying Methods annotated with '@Transactional' must be overridable
so I went ahead and marked both, the class and the method as open
. Easy, right?! Well, not quite.
Although this compiles, I got the required repository as null at execution time. I was able to solve the problem in two ways:
open
:open class FooService(private val barRepository: BarRepository) { open fun aMethod(): Bar { ... } @Transactional open fun aTransactionalMethod(): Bar { ... } }
This works but having all the methods in a class marked with open
might look a bit odd, so I tried something else.
interface IFooService { fun aMethod(): Bar fun aTransactionalMethod(): Bar } open class FooService(private val barRepository: BarRepository) : IFooService { override fun aMethod(): Bar { ... } @Transactional override fun aTransactionalMethod(): Bar { ... } }
This way you can still use the annotation since all the methods will be overridable and you won't need to use open
everywhere.
Hope this helps =)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With