quarkus: Qute Template Extension with multiple parameters: Resulting in endless wait without error

Describe the bug I’m trying to create a Qute template extension with multiple parameters as described here: https://quarkus.io/guides/qute-reference#method-parameters

When using a method with a single parameter all is working well, when I add a second parameter in the template extension method, it results in an endless loop in the browser.

I tried setting the default logger to DEBUG, but nothing gets logged (see log under “actual behavior”). I also tried to set a breakpoint in the method that gets called, but the error seems to be happening before the breakpoint is reached.

Expected behavior The template extension method is called, the result computed and displayed in my HTML template.

Actual behavior Website loads endlesly in browser. Logfile shows this:

2020-02-11 17:00:18,069 INFO  [io.quarkus] (main) Quarkus 1.2.0.Final started in 2.818s. Listening on: http://0.0.0.0:8080
2020-02-11 17:00:18,070 INFO  [io.quarkus] (main) Profile dev activated. Live Coding activated.
2020-02-11 17:00:18,070 INFO  [io.quarkus] (main) Installed features: [cdi, qute, resteasy, resteasy-jackson, resteasy-qute, spring-di, spring-web]
2020-02-11 17:00:30,242 DEBUG [io.net.uti.Recycler] (vert.x-eventloop-thread-1) -Dio.netty.recycler.maxCapacityPerThread: {}
2020-02-11 17:00:30,243 DEBUG [io.net.uti.Recycler] (vert.x-eventloop-thread-1) -Dio.netty.recycler.maxSharedCapacityFactor: {}
2020-02-11 17:00:30,243 DEBUG [io.net.uti.Recycler] (vert.x-eventloop-thread-1) -Dio.netty.recycler.linkCapacity: {}
2020-02-11 17:00:30,243 DEBUG [io.net.uti.Recycler] (vert.x-eventloop-thread-1) -Dio.netty.recycler.ratio: {}
2020-02-11 17:00:30,334 DEBUG [io.net.han.cod.com.ZlibCodecFactory] (vert.x-eventloop-thread-1) -Dio.netty.noJdkZlibDecoder: {}
2020-02-11 17:00:30,334 DEBUG [io.net.han.cod.com.ZlibCodecFactory] (vert.x-eventloop-thread-1) -Dio.netty.noJdkZlibEncoder: {}
2020-02-11 17:00:30,459 DEBUG [org.jbo.res.res.i18n] (executor-thread-1) RESTEASY002315: PathInfo: /
2020-02-11 17:00:31,172 DEBUG [io.qua.qut.run.EngineProducer] (executor-thread-1) Locate template for templates/feed
2020-02-11 17:00:31,175 DEBUG [io.qua.qut.run.EngineProducer] (executor-thread-1) Locate template for templates/feed.qute.html
2020-02-11 17:00:31,176 DEBUG [io.qua.qut.run.EngineProducer] (executor-thread-1) Locate template for templates/feed.qute.txt

<HERE WE HAVE AN ENDLESS WAIT, THEN IT SEEMS TO RESTART THE TASK?>

> Task :quarkusDev

<THEN RELOADING WEBSITE IN BROWSER>

2020-02-11 17:04:48,855 DEBUG [io.qua.resteasy] (vert.x-eventloop-thread-10) IO Exception : io.vertx.core.VertxException: Connection was closed

2020-02-11 17:04:48,892 DEBUG [org.jbo.res.res.i18n] (executor-thread-1) RESTEASY002315: PathInfo: /
2020-02-11 17:04:49,219 DEBUG [io.qua.qut.run.EngineProducer] (executor-thread-1) Locate template for templates/feed
2020-02-11 17:04:49,222 DEBUG [io.qua.qut.run.EngineProducer] (executor-thread-1) Locate template for templates/feed.qute.html
2020-02-11 17:04:49,224 DEBUG [io.qua.qut.run.EngineProducer] (executor-thread-1) Locate template for templates/feed.qute.txt

<AND ENDLESS WAIT AGAIN>

Not working code example

    // My @RestController method, where "downloadFolder" would be a simple String, and "feed" would be a @Component with several methods
    @GetMapping(value = "/", produces = MediaType.TEXT_HTML)
    public TemplateInstance showFeed() {
        return feed.data("feed", feedReader.readFeed())
                .data("downloadFolder", downloadFolder);
    }
@TemplateExtension
public class DownloadExistsUtil {
    public static boolean isAlreadyDownloaded(FeedItem feedItem, String downloadUrl, String downloadFolder) {
        return false;
    }
}
<table class="datagrid">
    {#for item in feed}
    <tr>
        <td>
            {#for url in item.urls}
                {#if item.isAlreadyDownloaded(url,downloadFolder) == false}
                    <p>
                        Bla
                    </p>
                {#else}
                    <p>
                        Blub
                    </p>
                {/if}
            {/for}
        </td>
    </tr>
    {/for}
</table>

Working example with just 1 parameter

    // No change from "not working example"
    // My @RestController method, where "downloadFolder" would be a simple String, and "feed" would be a @Component with several methods
    @GetMapping(value = "/", produces = MediaType.TEXT_HTML)
    public TemplateInstance showFeed() {
        return feed.data("feed", feedReader.readFeed())
                .data("downloadFolder", downloadFolder);
    }
@TemplateExtension
public class DownloadExistsUtil {
    public static boolean isAlreadyDownloaded(FeedItem feedItem, String downloadUrl) {
        return false;
    }
}
<table class="datagrid">
    {#for item in feed}
    <tr>
        <td>
            {#for url in item.urls}
                {#if item.isAlreadyDownloaded(url) == false}
                    <p>
                        Bla
                    </p>
                {#else}
                    <p>
                        Blub
                    </p>
                {/if}
            {/for}
        </td>
    </tr>
    {/for}
</table>

Configuration

  • Nothing

Environment (please complete the following information):

  • Output of uname -a or ver: Microsoft Windows [Version 10.0.18363.592]
  • Output of java -version:
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07)
OpenJDK 64-Bit Server VM GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07, mixed mode, sharing)
  • GraalVM version (if different from Java): same as java
  • Quarkus version or git rev: 1.2.0.Final

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18 (10 by maintainers)

Commits related to this issue

Most upvoted comments

So there are actually two problems.

(1) We have a bug in the “parent context resolution”. Basically, when evaluating an expression a parent context should be used if we fail to resolve an expression in the current context. Currently, we stop the resolution on the first level (in your case there is a nested loop -> 2 levels).

(2) The generated value resolver does not handle ClassCastException correctly.

I’m going to send a PR shortly. A workaround exists: use the data namespace, ie. item.isAlreadyDownloaded(url,data:downloadFolder).

I’ve also noticed that you’re using lombok in your app that does not seem to play well with quarkus development mode. TBH I’m not sure what’s the current “support status” of lombok in quarkus. But I would expect troubles.

@mithandir I think the easiest way to get this fixed would be for you to provide a small Maven project reproducing the issue. Thanks!

Yesterday Alpha2 wasn’t available on maven central. Will be home in about an hour, then I can start checking the issue on Alpha2.