[ REQUEST FOR FEEDBACK ] jOOQ / Kotlin users: What utilities would you like to see in a future jOOQ?

320 views
Skip to first unread message

Lukas Eder

unread,
Jul 17, 2019, 10:49:25 AM7/17/19
to jOOQ User Group
Dear jOOQ / Kotlin users

We already know how cool the jOOQ / Kotlin out of the box experience is, thanks to a lot of great language features, and 1-2 Kotlin specific API enhancements in jOOQ:

We're currently thinking of adding additional utilities, similar to the jOOQ-scala modules, where we offer additional, Scala specific API through implicits. In Kotlin, extension functions, or even infix functions, could be quite useful. There's a pending feature request for this:

One example I've just noticed today while writing unit tests is the ability of mapping into Kotlin classes more idiomatically, e.g.

query.fetchInto(KotlinClass::class)

Rather than

query.fetchInto(KotlinClass::class.java)

This could be achieved very easily via:

fun <E: Any, R: Record> ResultQuery<R>.fetchInto(klass: KClass<E>): MutableList<E> {
    return this.into(klass.java)
}

What other utilities would you like jOOQ to offer out of the box for an improved jOOQ / Kotlin experience?

Cheers,
Lukas

Marshall Pierce

unread,
Jul 24, 2019, 9:48:36 AM7/24/19
to jooq...@googlegroups.com

> On Jul 17, 2019, at 7:49 AM, Lukas Eder <lukas...@gmail.com> wrote:
> <snip>
> What other utilities would you like jOOQ to offer out of the box for an improved jOOQ / Kotlin experience?

Honestly, it’s pretty good as it is… I haven’t felt much friction using Kotlin + jOOQ for the last year.

A couple small things nonetheless:

- It’d be neat if the generated record types could have their various members explicitly marked as nullable so that they’re `?` types rather than `!` types. However, maybe that can be done by annotating them `@Nullable` — I forget if kotlin’s platform type integration takes that into account.
- fetchOne() (or its equivalent extension function) could return `R?` instead of `R!`

Lukas Eder

unread,
Jul 25, 2019, 4:00:56 AM7/25/19
to jOOQ User Group
Thanks for your reply, Marshall.

I did take the lack of other replies as a sign for "no news is good news" :) Great to hear that's true for you.

On Wed, Jul 24, 2019 at 3:48 PM Marshall Pierce <mars...@mpierce.org> wrote:
- It’d be neat if the generated record types could have their various members explicitly marked as nullable so that they’re `?` types rather than `!` types. However, maybe that can be done by annotating them `@Nullable` — I forget if kotlin’s platform type integration takes that into account.

That would indeed be a possibility to opt in to. A future code generator API will make adding custom annotations everywhere much easier. The current one isn't too easy to extend this way, although, it might be possible via overriding JavaGenerator::generateRecordGetter, prepending the annotation to the original implementation of the method.

A feature request for supporting this out of the box exists: https://github.com/jOOQ/jOOQ/issues/4748

With the code generator, the discussion on which of the many silly choices of @Nullable we should depend is irrelevant, because it's *your* choice, not the library maintainers' choice. (Unlike below). So, while this hasn't been a top priority, we'll definitely do this eventually.
 
- fetchOne() (or its equivalent extension function) could return `R?` instead of `R!`

That's the other discussion, which also has a feature request:

It is distinctly different from extending the code generator, because now, *we* have to add a dependency, and the sorry state of JSR 305 and related libraries prevented us from doing this so far. This is not a technical problem at all. It's obvious, which methods would need which annotation, and we might even be able to automate this in our API generation tools.

But to pick this dependency has proven to be a difficult question - none of the benefits so far outweighed the effort. I'm very happy to be proven wrong here, in case I have overlooked something.

Thanks,
Lukas 


 

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooq-user/968881B1-F851-4AD6-AF4D-E03F141EEEBB%40mpierce.org.

Marshall Pierce

unread,
Sep 30, 2019, 10:39:28 AM9/30/19
to jOOQ User Group
One more...

It'd make integration with Kotlin coroutines (OK, that's not just Kotlin the language...) easier/possible to have something like `transactionResult` that instead of taking a `TransactionCallable` and doing all the ManagedBlocker bits, took something whose `run()` (or equivalent) was a `suspend` function. In Kotlinese, that could be simply a function type: `suspend (Configuration) -> T`.

My current use case is that I'd like to be able to kick off some fire-and-forget async work inside a transaction, and for various reasons I'd prefer to have that be done via coroutines rather than `CompletableFuture` and friends (e.g. coroutine context carries over to child coroutines, unlike threadlocals, and other such things).

Lukas Eder

unread,
Oct 1, 2019, 2:47:38 AM10/1/19
to jOOQ User Group
Hi Marshall,

Thank you very much for your suggestion. Is that something you think would be easy to integrate in jOOQ without adding a dependency on Kotlin libraries? How does supporting that out of the box compare to an extension method (at least for now)? I would imagine that this could be implemented entirely outside of jOOQ, too...

Thanks,
Lukas

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.

Marshall Pierce

unread,
Oct 2, 2019, 9:22:34 AM10/2/19
to jOOQ User Group
There's little downside to having this exposed as an extension method (extension methods can only access public members but not an issue here), and I think that's really the only reasonable way to do it. Technically I could provide a TransactionalCallable with a runBlocking{} inside it, and that would compile, but also lose much of the benefits of using coroutines (won't carry over coroutine context, ties up a thread). Instead, I threw together a quick proof of concept of one way it could work: https://github.com/jOOQ/jOOQ/compare/master...marshallpierce:kotlin-suspend-txn-result?expand=1

This way does work and was "easy", but now there's essentially a duplicated copy of `transactionResult0`, which is pretty sad, and it's in `org.jooq.impl` to get access to DefaultTransactionContext and friends, creating a split package which will make JPMS upset.

If there was another way to implement the listener stuff before and exception stuff after that didn't involve package-private classes (and hopefully also avoiding copy-and-paste code...), then the extension function could be in a separate package, and indeed a separate project entirely. Or, if there isn't an option to use public types, could *gasp* actually use JPMS to expose the org.jooq.impl package to org.jooq.kotlin_stuff_goes_here. Mark Reinhold would be so happy.

On Tuesday, October 1, 2019 at 12:47:38 AM UTC-6, Lukas Eder wrote:
Hi Marshall,

Thank you very much for your suggestion. Is that something you think would be easy to integrate in jOOQ without adding a dependency on Kotlin libraries? How does supporting that out of the box compare to an extension method (at least for now)? I would imagine that this could be implemented entirely outside of jOOQ, too...

Thanks,
Lukas

On Mon, Sep 30, 2019 at 4:39 PM Marshall Pierce <mars...@mpierce.org> wrote:
One more...

It'd make integration with Kotlin coroutines (OK, that's not just Kotlin the language...) easier/possible to have something like `transactionResult` that instead of taking a `TransactionCallable` and doing all the ManagedBlocker bits, took something whose `run()` (or equivalent) was a `suspend` function. In Kotlinese, that could be simply a function type: `suspend (Configuration) -> T`.

My current use case is that I'd like to be able to kick off some fire-and-forget async work inside a transaction, and for various reasons I'd prefer to have that be done via coroutines rather than `CompletableFuture` and friends (e.g. coroutine context carries over to child coroutines, unlike threadlocals, and other such things).

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq...@googlegroups.com.

Lukas Eder

unread,
Oct 8, 2019, 6:01:24 AM10/8/19
to jOOQ User Group
On Wed, Oct 2, 2019 at 3:22 PM Marshall Pierce <mars...@mpierce.org> wrote:
There's little downside to having this exposed as an extension method (extension methods can only access public members but not an issue here), and I think that's really the only reasonable way to do it. Technically I could provide a TransactionalCallable with a runBlocking{} inside it, and that would compile, but also lose much of the benefits of using coroutines (won't carry over coroutine context, ties up a thread). Instead, I threw together a quick proof of concept of one way it could work: https://github.com/jOOQ/jOOQ/compare/master...marshallpierce:kotlin-suspend-txn-result?expand=1

This way does work and was "easy", but now there's essentially a duplicated copy of `transactionResult0`, which is pretty sad, and it's in `org.jooq.impl` to get access to DefaultTransactionContext and friends, creating a split package which will make JPMS upset.

If there was another way to implement the listener stuff before and exception stuff after that didn't involve package-private classes (and hopefully also avoiding copy-and-paste code...), then the extension function could be in a separate package, and indeed a separate project entirely.

Sure, I understand the drawback of copy pasting, but that could be a viable workaround for the time being. Thanks for documenting it.
 
Or, if there isn't an option to use public types, could *gasp* actually use JPMS to expose the org.jooq.impl package to org.jooq.kotlin_stuff_goes_here. Mark Reinhold would be so happy.

I'm not touching JPMS anytime soon during the next year. Making jOOQ a module provides almost zero value to the community right now (as JPMS adoption is still incredibly low), while causing tons of headaches for us, with IDEs and transitive dependencies still not being 100% ready for it.

Anyway, I wonder if we could simply include that Kotlin class in the jOOQ library directly, instead of putting it in a new module... If our mostly Java based integration tests don't fail because of some class loading issue, I don't see a problem adding some Kotlin classes to org.jooq.impl. I've created an issue for this:

Thanks,
Lukas 
Reply all
Reply to author
Forward
0 new messages