quarkus
quarkus copied to clipboard
Support for Kotlin collections in type-safe Qute templates
Description
For the time being, I'm annotating my Kotlin data classes with @JvmRecord (as suggested in #38194). My template takes a list of items, so I've declared the data class with val items: Collection<DataClass> and added {@kotlin.collections.Collection<my.custom.DataClass> items} to the template file.
Further down, my template looks like this
{#for i in items}
{i.whatever
{/}
I would expect to see the whatever property for all items printed out, but instead, Quarkus shows an error message
io.quarkus.qute.TemplateException: Class [kotlin.collections.Collection] used in the parameter declaration in template [email/detail.html] on line 7 was not found in the application index. Make sure it is spelled correctly.
Implementation ideas
No response
/cc @geoand (kotlin), @mkouba (qute)
Forgot to mention, but I feel it might be relevant: if my template takes in a data class that holds a Kotlin Collection (i.e., something like data class MyItems(val items: Collection<Item>), I'm not seeing the error page, and iterating over the collection works just as you'd expect.
Could you pls provide a small reproducer app?
Could you pls provide a small reproducer app?
Yep, but not this week, maybe next week
Thanks for your patience, @mkouba. I tried to reproduce in a separate project, and it seems the issue may have been caused by the fact that my TemplateInstance subclass (a.k.a. the Kotlin Data Class with @JvmRecord on it) and the template file itself had type parameters.
In other words, I had this
@CheckedTemplate
@JvmRecord
data class DemoPage(
val items: Collection<DataClass>
): TemplateInstance
and this
{@kotlin.collections.Collection<my.custom.DataClass> items}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Quarkus issue #38440</title>
</head>
<body>
<ul>
{#for item in items}
<li>{item.whatever}</li>
{/}
</ul>
</body>
</html>
I guess you normally don't need to have both, right? Anyway, when I stripped the {@kotlin.collections.Collection<my.custom.DataClass> items} from the HTML file, it worked just fine.
I guess you normally don't need to have both, right?
Exactly. The template param declarations are extracted from the record params. However, items: Collection<DataClass> should be transfomed to {@kotlin.collections.Collection<my.custom.DataClass> items} unless there's some kotlin magic happening under the hood. Maybe if you look at the compiled DemoPage you'll see a different type for the items.
Anyway, when I stripped the {@kotlin.collections.Collection<my.custom.DataClass> items} from the HTML file, it worked just fine.
:+1:
Maybe if you look at the compiled
DemoPageyou'll see a different type for theitems.
I've inspected that class using the IntelliJ Kotlin bytecode viewer:
// access flags 0x12
// signature Ljava/util/Collection<Lit/mulders/quarkus/issue38440/DataClass;>;
// declaration: items extends java.util.Collection<it.mulders.quarkus.issue38440.DataClass>
private final Ljava/util/Collection; items
Interesting detail here is that although the Kotlin code does not import java.util.Collection. Thus, by definition, using Collection refers to kotlin.collections.Collection, right? But the bytecode seems to be different nevertheless...
Maybe if you look at the compiled
DemoPageyou'll see a different type for theitems.I've inspected that class using the IntelliJ Kotlin bytecode viewer:
// access flags 0x12 // signature Ljava/util/Collection<Lit/mulders/quarkus/issue38440/DataClass;>; // declaration: items extends java.util.Collection<it.mulders.quarkus.issue38440.DataClass> private final Ljava/util/Collection; itemsInteresting detail here is that although the Kotlin code does not import
java.util.Collection. Thus, by definition, usingCollectionrefers tokotlin.collections.Collection, right? But the bytecode seems to be different nevertheless...
Yeah, it seems that the kotlin Collection is transformed to a JDK Collection during compilation...