BaseRepository in Hibernate Reactive - kotlin

How can I make baseRepository in hibernate reactive in kotlin?
I want to make a repository for all other repositories like JpaRepository.
How can I implement it?
My BaseRepository
interface BaseRepository<E, ID> {
suspend fun save(entity: E): E
suspend fun findByIdOrNull(id: ID): E?
}
My BaseRepositoryImpl
class BaseRepositoryImpl<E, ID>(
private val session: Mutiny.Session,
private val domainClass: Class<E>
) : BaseRepository<E, ID> {
override suspend fun save(entity: E): E {
session.persist(entity)
.await()
return entity
}
override suspend fun findByIdOrNull(id: ID): E? {
return session.find(domainClass, id)
.convert()
.with(toMono()).awaitSingleOrNull()
}
}
How can I use this baseRepository?

Related

kotlin interfaces, sealed classes and generic types usage (using child classes of generic types in interface functions)

I have this sealed class
sealed class S3FileUploaderRequest {
abstract val s3Configuration: S3Configuration
data class S3UploadRequest(
val uploadData: S3UploadData,
override val s3Configuration: S3Configuration
) : S3FileUploaderRequest()
data class S3DeleteRequest(
val path: String,
override val s3Configuration: S3Configuration
) : S3FileUploaderRequest()
data class S3MultiUploadRequest(
val multiUploadData: List<S3UploadData>,
override val s3Configuration: S3Configuration
) : S3FileUploaderRequest()
data class S3MultiDeleteRequest(
val paths: List<String>,
override val s3Configuration: S3Configuration
) : S3FileUploaderRequest()
}
And this interface:
interface FileUploader<T, S> {
suspend fun multiUploadFile(request: T): S
suspend fun multiDeleteFile(request: T): List<S>
suspend fun uploadFile(request: T): S
suspend fun deleteFile(request: T): S
}
I would like to use the child classes of data class S3FileUploaderRequest es entry parameter of interface functions, somethig like this:
interface FileUploader<T, S> {
suspend fun multiUploadFile(request: out T): out S
suspend fun multiDeleteFile(request: out T): List<S>
suspend fun uploadFile(request: out T): out S
suspend fun deleteFile(request: out T): out S
}
Is possible to do this? I feel like kotlin should be able to do this but don't find the proper syntax for it.
Update:
I would like to implement the interface this way:
#Singleton
class S3FileUploader() : FileUploader<S3FileUploaderRequest, S3FileUploaderResponse> {
override suspend fun uploadFile(request: S3UploadRequest): S3UploadResponse {
//DO STUFF
}
override suspend fun deleteFile(request: S3DeleteRequest): S3DeleteResponse {
//DO STUFF
}
override suspend fun multiUploadFile(request: S3MultiUploadRequest): S3MultiUploadResponse {
//DO STUFF
}
override suspend fun multiDeleteFile(request: S3MultiDeleteRequest): List<S3DeleteResponse> {
//DO STUFF
}
}

Mocking Kotlin receivers

I was wondering - what is the best way to mock Kotlin's receivers? In more concrete terms, let's say I defined the following interfaces:
interface TransactionalRepository {
fun <T> withTransaction(TransactionalOperations.() -> T)
}
interface TransactionalOperations {
fun <T: Entity> save(entity: T)
fun <T: Entity> load(id: UUID): T
}
Assuming I have some business logic using an implementation of TransactionalRepository like this:
fun decrementCounter(counterId: UUID) {
repository.transaction {
val entity: Counter = load(counterId)
entity.decrement()
save(entity)
}
}
What is the best way to mock out the interactions between TransactionalRepository and TransactionalOperations?

How to use actors while retaining the ability to do structured concurrency in Kotlin?

I have a class which uses an actor to ensure thread safety of shared mutable state. I made a small wrapper around this actor to make it easy to use:
interface Ref<T : Any> {
fun get(): T
fun transform(transformer: (T) -> T): Job
}
Here get uses runBlocking to block until it fetches the actual value of T:
override fun get(): T = runBlocking {
val deferred = CompletableDeferred<T>()
launch {
actor.send(RefOperation.Get(deferred))
}
deferred.await()
}
and transform does something similar without runBlocking and just returns a Job:
override fun transform(transformer: (T) -> T): Job {
val job = Job()
launch {
actor.send(RefOperation.Transform(transformer, job))
}
return job
}
This is fine until a transform call leads to another one:
ref.transform {
...
ref.transform {
}
}
Here I have 2 Jobs but there is no way to combine them to a single Job on which I can call join() if I want to wait for their completion.
The solution for this would be structured concurrency but then I don't know how to create my actor anymore since it is defined as an extension on CoroutineScope.
How can I keep using an actor while retaining the ability to use structured concurrency?
Note that I've created Ref because my project is multiplatform and for targets other than the JVM I use alternative implementations.
actor processes items in the same order as they were added, and does it sequentially in a single coroutine. It means that inner transform will be processed AFTER completion of outer transform, and you can't change it while you are using actor (in actor we can't launch more coroutines, because we confine our state to a single thread, otherwise recurrent processing order would be possible). Trying to join the job of inner transform in body of outer transform (if we mark transform as suspended function) will just cause deadlock.
Are you OK with such behaviour? If not, don't use either actors or nested transforms. If yes, please provide some use cases where creating a nested transform that will be processed after outer transform makes any sense.
As for joining all the jobs, I've got some code. In main we have outer transform that creates an inner transform. Outer one returns 2, inner one returns 8, but inner one starts after completion of outer one, so the result is 8. But as you wanted, transformJob.join() in main waits for inner job too.
private sealed class RefOperation<T>
private class Get<T : Any>(val deferred: CompletableDeferred<T>) : RefOperation<T>()
private class Transform<T : Any>(val transformer: TransformStub<T>.(T) -> T, val stub: TransformStub<T>, val job: CompletableJob) : RefOperation<T>()
interface Ref<T : Any> {
fun get(): T
fun transform(transformer: TransformStub<T>.(T) -> T): Job
}
interface TransformStub<T : Any> {
fun transform(transformer: TransformStub<T>.(T) -> T): Job
}
private class TransformStubImpl<T : Any>(
val actor: SendChannel<RefOperation<T>>,
val scope: CoroutineScope
) : TransformStub<T> {
override fun transform(transformer: TransformStub<T>.(T) -> T): Job {
return scope.launch {
val childJob: CompletableJob = Job()
val childStub = TransformStubImpl(actor, this)
actor.send(Transform(transformer, childStub, childJob))
childJob.join()
}
}
}
class RefImpl<T : Any>(initialValue: T) : Ref<T> {
private val actorJob = Job()
private val actorScope = CoroutineScope(actorJob)
private val actor = actorScope.actor<RefOperation<T>> {
var value: T = initialValue
for (msg in channel) {
when (msg) {
is Get -> {
println("Get! $value")
msg.deferred.complete(value)
}
is Transform -> {
with(msg) {
val newValue = stub.transformer(value)
println("Transform! $value -> $newValue")
value = newValue
job.complete()
}
}
}
}
}
override fun get(): T = runBlocking {
val deferred = CompletableDeferred<T>()
actor.send(Get(deferred))
deferred.await()
}
override fun transform(transformer: TransformStub<T>.(T) -> T): Job {
val stub = TransformStubImpl(actor, GlobalScope)
return stub.transform(transformer)
}
}
fun main() = runBlocking<Unit> {
val ref: Ref<Int> = RefImpl(0)
val transformJob = ref.transform {
transform { 8 }
2
}
transformJob.join()
ref.get()
}

How to inherit MutableList in Kotlin?

I am trying to inherit MutableList, and add my own function to it. For example:
class CompositeJob : MutableList<Job> {
fun cancelAllJobs() {
for (job in this) {
job.cancel()
}
}
}
But I got the following error:
Class 'CompositeJob' is not abstract and does not implement abstract member
public abstract val size: Int defined in kotlin.collections.MutableList
How can I inherit MutableList, so I can use its original methods like add() and isEmpty(), and add my own one?
Thanks.
One option other answers don't mention is delegation:
class CompositeJob : MutableList<Job> by mutableListOf() {
fun cancelAllJobs() {
for (job in this) {
job.cancel()
}
}
}
is basically equivalent to
class CompositeJob : MutableList<Job> {
private val impl: MutableList<Job> = mutableListOf()
override fun size() = impl.size()
override fun add(x: Job) { impl.add(x) }
// etc for all other MutableList methods
fun cancelAllJobs() {
for (job in this) {
job.cancel()
}
}
}
MutableList is an interface - it doesn't implement any of its methods, just declares them. If you want to implement MutableList from scratch, you'll have to implement all 20 of its methods plus the size property, as your error already told you.
You can, however, subclass actual implementations of this interface, for example ArrayList or LinkedList:
class CompositeJob : ArrayList<Job>() {
fun cancelAllJobs() {
for (job in this) {
job.cancel()
}
}
}
Edit: If you're just looking to group coroutine Job instances, you should use a parent Job, a SupervisorJob, and CoroutineScope at this point, instead of collecting jobs like this manually.
Implementation of all the members is not the only way to achieve what you need.
An easier way is create an extension function like this:
fun MutableList<Job>.cancelAllJobs() {
this.forEach { it.cancel() }
}
Now you can call myList.cancelAllJobs() for every MutableList<Job> object.
As I have tested you need to make CompositeJob an abstract as error also suggest. After that, you can able to override add() and isEmpty() from MutableList
So your code looks like as below:
abstract class CompositeJob : MutableList<Job> {
override fun add(element:Job): Boolean
{
}
override fun isEmpty(): Boolean
{
}
}
If you want to avoid inheritance, or if the concrete class methods are marked final, then you can use composition and redirect all method calls which are not overridden. Here's a template:
class MyMutableList<T> : MutableList<T> {
private val list = mutableListOf<T>()
override val size get() = list.size
// MutableList<T>
override fun add(element: T): Boolean = list.add(element)
override fun add(index: Int, element: T) = list.add(index, element)
override fun addAll(elements: Collection<T>): Boolean = list.addAll(elements)
override fun addAll(index: Int, elements: Collection<T>): Boolean = list.addAll(index, elements)
override fun clear() = list.clear()
override fun remove(element: T): Boolean = list.remove(element)
override fun removeAll(elements: Collection<T>): Boolean = list.removeAll(elements)
override fun removeAt(index: Int): T = list.removeAt(index)
override fun retainAll(elements: Collection<T>): Boolean = list.retainAll(elements)
override fun set(index: Int, element: T): T = list.set(index, element)
// List<T>
override fun contains(element: T): Boolean = list.contains(element)
override fun containsAll(elements: Collection<T>): Boolean = list.containsAll(elements)
override fun get(index: Int): T = list.get(index)
override fun indexOf(element: T): Int = list.indexOf(element)
override fun isEmpty(): Boolean = list.isEmpty()
override fun iterator(): MutableIterator<T> = list.iterator()
override fun lastIndexOf(element: T): Int = list.lastIndexOf(element)
override fun listIterator(): MutableListIterator<T> = list.listIterator()
override fun listIterator(index: Int): MutableListIterator<T> = list.listIterator(index)
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> =
list.subList(fromIndex, toIndex)
}
...of course, this might add an additional layer of indirection, possibly affecting list performance with a slight overhead.

Invoking methods on interfaces with generics

The following is a very simple illustration of what I'm trying to do:
interface Event {
fun value(): Int
}
class Event1: Event {
override fun value() = 1
}
class Event2: Event {
override fun value() = 2
}
interface EventConsumer<T> where T: Event {
fun consume(event: T)
}
class Event1Consumer: EventConsumer<Event1> {
override fun consume(event: Event1) {
println(event.value())
}
}
class Event2Consumer: EventConsumer<Event2> {
override fun consume(event: Event2) {
println(event.value())
}
}
class EventManager {
private val consumers: Map<KClass<*>, EventConsumer<*>> = mapOf(
Event1::class to Event1Consumer(),
Event2::class to Event2Consumer()
)
fun consume(event: Event) {
val consumer = consumers[event::class]
consumer?.consume(event)
}
}
The final method call (consumer.consume()) is giving me a compiler error
Out-projected type 'EventConsumer<*>?' prohibits the use of 'public
abstract fun consume(event: T): Unit defined in EventConsumer'
I know that Kotlin is a lot more strict about generics than Java which is probably why it doesn't work, but how would I implement something like this properly?
Since you are building the consumers map, it would be safe to make an unchecked cast to the correct generic EventConsumer type:
fun <T: Event> consume(event: T) {
val consumer = consumers[event::class] as? EventConsumer<T>
consumer?.consume(event)
}