Yaroslav
Yaroslav

Reputation: 87

Jooq reactive fetching using r2dbc driver

My query looks like (using JOOQ v 3.15):

    override fun getCredentialsById(id: Long): Mono<UserCredentialsModel> {
    return Mono.from {
        dsl.select(
                USER_CREDENTIALS.ID,
                USER_CREDENTIALS.EMAIL,
                USER_CREDENTIALS.PHONE,
                USER_CREDENTIALS.LOGIN,
                USER_CREDENTIALS.PASSWORD)
            .from(USER_CREDENTIALS)
            .where(USER_CREDENTIALS.ID.eq(id))
            .and(USER_CREDENTIALS.IS_ACTIVE.eq(true))
            .fetchInto(UserCredentialsModel::class.java)
    }
}

JOOQ config:

@Bean
fun createContext(): DSLContext {
    return DSL.using(connection)
}

where connection is io.r2dbc.spi.ConnectionFactory

and I`m getting an exception:

org.jooq.exception.DetachedException: Attempt to execute a blocking method (e.g. Query.execute() or ResultQuery.fetch()) when only an R2BDC ConnectionFactory was configured

How should I then fetch my query result into Kotlin data class (or Java JOOQ`s POJO) in reactive style?

Upvotes: 2

Views: 2956

Answers (3)

Steinhof
Steinhof

Reputation: 21

You can try .toMono().subscribe()

dsl.select(
            USER_CREDENTIALS.ID,
            USER_CREDENTIALS.EMAIL,
            USER_CREDENTIALS.PHONE,
            USER_CREDENTIALS.LOGIN,
            USER_CREDENTIALS.PASSWORD)
        .from(USER_CREDENTIALS)
        .where(USER_CREDENTIALS.ID.eq(id))
        .and(USER_CREDENTIALS.IS_ACTIVE.eq(true))
        .fetchInto(UserCredentialsModel::class.java)
        .toMono().subscribe()

Upvotes: 0

Lukas Eder
Lukas Eder

Reputation: 221145

When using jOOQ reactively, you should never call any blocking methods, such as ResultQuery.fetchOneInto(Class). That method is just a convenience method for ResultQuery.fetchOne() and then Record.into(Class). Nothing keeps you from calling Record.into(Class) yourself, neither in the blocking world, nor in the non-blocking world.

So, use your usual reactor library methods to map stream contents:

mono.map { r -> r.into(UserCredentialsModel::class.java) }

Or, in a complete example:

return Mono.from {
    dsl.select(
            USER_CREDENTIALS.ID,
            USER_CREDENTIALS.EMAIL,
            USER_CREDENTIALS.PHONE,
            USER_CREDENTIALS.LOGIN,
            USER_CREDENTIALS.PASSWORD)
        .from(USER_CREDENTIALS)
        .where(USER_CREDENTIALS.ID.eq(id))
        .and(USER_CREDENTIALS.IS_ACTIVE.eq(true))
} .map { r -> r.into(UserCredentialsModel::class.java) }

Upvotes: 3

Simon Martinelli
Simon Martinelli

Reputation: 36223

Without testing I would say it should be

return Mono.from(
    dsl.select(
            USER_CREDENTIALS.ID,
            USER_CREDENTIALS.EMAIL,
            USER_CREDENTIALS.PHONE,
            USER_CREDENTIALS.LOGIN,
            USER_CREDENTIALS.PASSWORD)
        .from(USER_CREDENTIALS)
        .where(USER_CREDENTIALS.ID.eq(id))
        .and(USER_CREDENTIALS.IS_ACTIVE.eq(true)));

Upvotes: 1

Related Questions