Consider the following repository interface declaration:
interface KotlinUserRepository : Repository<User, String> {
fun findById(username: String): User
fun search(username: String) = findById(username)
}
I'm declaring a default interface method search(…)
that defaults to invoking findById(…)
.
Starting my application fails with:
org.springframework.data.mapping.PropertyReferenceException: No property Search found for type User!
How can I use Kotlin default methods with Spring Data repository interfaces and prevent PropertyReferenceException
?
Kotlin 1.1/1.2 compiles default methods to abstract interface methods in the first place. It's not possible to use Kotlin's default methods in Spring Data repository interfaces.
Kotlin allows default interface methods with a Java runtime version 1.6. JVM-level default interface methods were introduced with Java 1.8. This causes Kotlin to use a different approach to compile default interface methods than Java does.
The code from KotlinUserRepository
compiles to:
interface KotlinUserRepository extends Repository {
User findById(String username);
User search(String username);
@Metadata(…)
public static final class DefaultImpls {
public static User search(KotlinUserRepository $this, String username) {
Intrinsics.checkParameterIsNotNull(username, "username");
return $this.findById(username);
}
}
}
The method search(…)
compiles to an abstract interface method. The implementation bit compiles to a class DefaultImpls
which reflects the default method signature. A class wanting to implement KotlinUserRepository
is required to implement search(…)
. Using the interface in a pure Kotlin environment will let the Kotlin compiler create the implementation bits.
Spring Data repositories work with proxies underneath. Every method on a repository must be either:
In this case, search(…)
is not implemented by any custom code according to how you'd implement a Java interface. Spring Data attempts to derive a query and considers search(…)
as property of the User
domain class. Lookup fails and throws PropertyReferenceException
.
This is a known limitation.