简体   繁体   中英

How to write parametric/generic functions in kotlin

I'm trying to find a workaround to make a Spring Reactive Webclient work with JDBC . Here is were I got the idea from: https://gitorko.github.io/2019/04/02/Spring-Webflux-Reactive-JDBC/ .

I'm writing a service that calls the jdbc repository interface and instead of returning the type of my domain object MyClass returns a Mono<MyClass> like this:

//other specific imports here
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
import reactor.core.scheduler.Scheduler
import reactor.core.scheduler.Schedulers
import java.util.concurrent.Callable

@Service
class MyClassService(val repo: MyClassRepository, val jdbcScheduler: Scheduler){

    fun save(obj: MyClass?): Mono<MyClass?>? {
       return asyncCallable { repo.save(obj) }
    }

    protected fun <S> asyncCallable(callable: Callable<S>?): Mono<S>? {
        return Mono.fromCallable(callable).subscribeOn(Schedulers.parallel()).publishOn(jdbcScheduler)
    }
}

//this is a jdbc repository
interface MyClassRepository : CrudRepository<MyClass, UUID> {}

Now the problem is that calling asyncCallable { repo.save(obj) } returns the compile error inferred type is MyClass? but TypeVariable(S) was expected inferred type is MyClass? but TypeVariable(S) was expected and Mono.fromCallable(callable).subscribeOn(Schedulers.parallel()).publishOn(jdbcScheduler) returns the compile error inferred type is Callable<S>? but Callable<out TypeVariable(T)!> was expected inferred type is Callable<S>? but Callable<out TypeVariable(T)!> was expected . I understand by reading about kotlin generics that this has to do with the variance. If I'm not wrong the function asyncCallable is invariant on the generic type S and in this case covariance is required?

I think the syntax you need is asyncCallable(Callable { repo.save(obj) }) .

Complete example:

@Service
class MyClassService(val repo: MyClassRepository, val jdbcScheduler: Scheduler){

    fun save(obj: MyClass): Mono<MyClass?>? {
        return asyncCallable(Callable { repo.save(obj) })
    }

    protected fun <S> asyncCallable(callable: Callable<S>): Mono<S>? {
        return Mono.fromCallable(callable).subscribeOn(Schedulers.parallel()).publishOn(jdbcScheduler)
    }
}

I'd also remove the ? s, but I left them to keep it as close to your code as possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM