Closed koenpunt closed 1 year ago
Coroutine repositories are built on top of reactive repositories by adapting Coroutine infrastructure to Reactive return types. There's no concrete implementation for CoroutineCrudRepository
because the invocation proxy for Coroutine repositories uses SimpleReactive…Repository
implementations.
We do not natively support coroutine extensions because of the mentioned adapter mechanism. If you want to extend a Coroutine repository you need to provide an extension to a SimpleReactive…Repository
using the reactive Java mechanisms.
Coroutine repositories are built on top of reactive repositories by adapting Coroutine infrastructure to Reactive return types. There's no concrete implementation for CoroutineCrudRepository because the invocation proxy for Coroutine repositories uses SimpleReactive…Repository implementations.
This was clear to me, also from the linked issue.
We do not natively support coroutine extensions because of the mentioned adapter mechanism. If you want to extend a Coroutine repository you need to provide an extension to a SimpleReactive…Repository using the reactive Java mechanisms.
How can such a repository be exposed with suspend fun's? Because the interface has to be defined with reactive types. Or isn't that possible? That would be fairly disappointing..
suspend
is a Kotlin feature that the Spring Data adopts to if such a method is invoked.
Because the interface has to be defined with reactive types
Exactly. Check out how SimpleReactiveMongoRepository
maps to the Coroutine repository declaration. If you want to expose a suspend
method, then the implementation uses Mono<…>
as return type. For Flow
, you would return Flow
.
Let me know whether that helps.
If you want to expose a
suspend
method, then the implementation usesMono<…>
as return type. ForFlow
, you would returnFlow
.
I tried this, but how should I import/implement this interface?
What I'm trying to accomplish is having a custom "base repository" for entities that have to support soft deletion.
So ProductRepository
-> SoftDeleteRepository
-> ???Repository
.
If ???Repository
would be an interface with methods defined like SimpleReactiveMongoRepository, then how can a implementation importing the ProductRepository
invoke suspend fun's on it?
You're right. Fragments are discovered by naming pattern and expected to implement an interface. I am afraid that this is going to prevent your approach to discover fragments out of the box. You could post-process the actual bean definition (RepositoryFactoryBeanSupport.setRepositoryFragments(…)
) to include repository fragments (RepositoryFragment.implemented(…)
) for that purpose.
For base repositories, you can specify a subclass of Simple…Repository
via @Enable…Repositories(repositoryBaseClass = …)
.
Spring Data introspects all repository fragments (base repository, default custom implementation, implemented fragments and configuration-contributed ones such as Querydsl) to find a method to invoke.
Let me know how this goes.
Thank you for these details.
So if I understand correctly; I have to create a SoftDeleteRepository
implementation defining reactive methods, inheriting from Simple...Repository
.
Additionally I would define a SoftDeleteCoroutineRepository
interface that defines the same methods, but with a coroutine signature, and then by defining repository fragments I should be able to glue the two together?
and then by defining repository fragments I should be able to glue the two together?
If you specify SoftDeleteRepository
as repositoryBaseClass
, then this should be sufficient.
I'm trying to implement a
SoftDeleteRepository
abstraction, but since there's no concrete implementation of theCoroutineCrudRepository
(or any coroutine repository for that matter), how am I supposed to achieve this?Contrived example of what I'm working with;
The problem; when for example performing the
findById
method it never reaches the custom implementation.Related: https://github.com/spring-projects/spring-data-commons/issues/2379