Description
When I try to annotate the unit-returning suspend function with @Update
annotation
@Repository
interface PersonRepository : CoroutineCrudRepository<Person, String> {
@Update("{ \$inc: { age: 1 } }")
suspend fun findAndIncrementAgeByName(name: String)
}
I get an exception
Caused by: java.lang.IllegalStateException: Update method may be void or return a numeric value (the number of updated documents). Offending Method: PersonRepository.findAndIncrementAgeByName
at org.springframework.data.mongodb.repository.query.MongoQueryMethod.verify(MongoQueryMethod.java:497) ~[spring-data-mongodb-4.3.3.jar:4.3.3]
at org.springframework.data.mongodb.repository.query.ReactiveMongoQueryMethod.verify(ReactiveMongoQueryMethod.java:164) ~[spring-data-mongodb-4.3.3.jar:4.3.3]
at org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactory$MongoQueryLookupStrategy.resolveQuery(ReactiveMongoRepositoryFactory.java:184) ~[spring-data-mongodb-4.3.3.jar:4.3.3]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:115) ~[spring-data-commons-3.3.3.jar:3.3.3]
... 42 common frames omitted
It seems to be related to the behavior of Kotlin's compiler. After the code compilation suspending functions return java.lang.Object
and thus the function is not treated as a void-returning one on the Spring Data MongoDB level. When I pause the program execution with the debugger, it shows that the resultType
is class kotlin.Unit
. When I delete the suspend
keyword from the findAndIncrementAgeByName
method, it just shows void
as a resultType
.
I've prepared a minimal example to make it easy for you to reproduce this issue quickly. You can find the project here: https://github.com/breader124/spring-data-mongodb-issues-kotlin/tree/suspend-fun-annotated-with-update