Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vaadin + Quarkus @Push does not work - always DISABLED #164

Open
JasonTheDynamite opened this issue Jul 2, 2024 · 20 comments
Open

Vaadin + Quarkus @Push does not work - always DISABLED #164

JasonTheDynamite opened this issue Jul 2, 2024 · 20 comments

Comments

@JasonTheDynamite
Copy link

Describe the bug

I am getting this error on the frontend using vaadin with quarkus:
https://192.168.1.100/VAADIN/static/push/vaadinPush.js could not be loaded. Push will not work.
Looks like this:
image
Push does not work at all.

Logs show this:
io.package.website.configuration.VaadinAppShell' is not a CDI bean. Falling back to default instantiation.

Currently push works only when there is a user interaction with the frontend - for example a usern needs to click a button to force changes to the frontend.

#Gradle properties
quarkusPluginId=io.quarkus
quarkusPluginVersion=3.12.0
quarkusPlatformGroupId=io.quarkus.platform
quarkusPlatformArtifactId=quarkus-bom
quarkusPlatformVersion=3.12.0
vaadinVersion=24.4.4
vaadinPluginVersion=24.4.4
kotlinVersion=2.0.0

build.gradle:
`plugins {
id "java"
id "application"
id 'org.jetbrains.kotlin.jvm' version "${kotlinVersion}"
id 'org.jetbrains.kotlin.kapt' version "${kotlinVersion}"
id "org.jetbrains.kotlin.plugin.allopen" version "${kotlinVersion}"
id 'org.jetbrains.kotlin.plugin.jpa' version "${kotlinVersion}"
id 'com.github.gmazzo.buildconfig' version '5.3.5'
id "com.vaadin" version "${vaadinPluginVersion}"
id 'io.quarkus'
}

apply plugin: 'kotlin'

repositories {
mavenCentral()
maven {
url = uri("https://plugins.gradle.org/m2/")
}
maven {
url "https://maven.vaadin.com/vaadin-addons"
}
google()
gradlePluginPortal()
}

dependencies {
implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")

implementation "com.vaadin:vaadin-bom:${vaadinVersion}"
implementation "com.vaadin:vaadin-jandex:${vaadinVersion}"

// implementation "com.vaadin:vaadin-core:${vaadinVersion}"
implementation "com.vaadin:vaadin-quarkus-extension:${vaadinVersion}"

implementation "io.quarkus:quarkus-hibernate-orm"
implementation "io.quarkus:quarkus-jdbc-h2"
implementation "io.quarkus:quarkus-hibernate-validator"

implementation "io.quarkus:quarkus-kotlin"

implementation "io.quarkiverse.bucket4j:quarkus-bucket4j:1.0.3"
implementation "io.quarkus:quarkus-jdbc-postgresql"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "io.quarkus:quarkus-arc"
implementation "io.quarkus:quarkus-rest"
implementation "io.quarkus:quarkus-rest-jackson"

implementation("io.quarkus:quarkus-smallrye-jwt")
implementation("io.quarkus:quarkus-smallrye-jwt-build")
implementation "io.quarkus:quarkus-mutiny:3.11.2"
implementation "io.smallrye.reactive:mutiny-kotlin:2.6.0"
implementation("io.quarkus:quarkus-undertow")
implementation("io.quarkus:quarkus-websockets")

implementation "org.apache.tika:tika-core:2.9.2"
implementation("org.apache.commons:commons-text:1.11.0")
implementation("org.apache.syncope.common:syncope-common-lib:2.1.14")
implementation "org.apache.commons:commons-lang3:3.14.0"
implementation "commons-codec:commons-codec:1.17.0"
implementation "commons-io:commons-io:2.16.1"
implementation("com.google.guava:guava:33.2.1-jre")

implementation "net.java.dev.jna:jna:5.14.0"

runtimeOnly "com.h2database:h2:2.2.224"

implementation "org.bouncycastle:bcprov-jdk15to18:1.78"
implementation "org.bouncycastle:bcjmail-lts8on:2.73.6"


implementation "org.jboss.logmanager:jboss-logmanager:3.0.6.Final"

testImplementation "io.quarkus:quarkus-junit5"
testImplementation "io.rest-assured:rest-assured"
testImplementation "io.quarkus:quarkus-jdbc-postgresql"
testImplementation "io.quarkus:quarkus-jdbc-h2"
testImplementation "org.jboss.logmanager:jboss-logmanager:3.0.6.Final"

}

def props = new Properties()
props.load(new FileInputStream(new File("src/main/resources/application.properties")))

group 'io.package'
version '1.0.0-SNAPSHOT'

java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}

test {
systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager"
}
allOpen {
annotation("jakarta.ws.rs.Path")
annotation("jakarta.enterprise.context.ApplicationScoped")
annotation("jakarta.persistence.Entity")
annotation("io.quarkus.test.junit.QuarkusTest")
}

compileKotlin {
kotlinOptions.jvmTarget = JavaVersion.VERSION_21
kotlinOptions.javaParameters = true
kotlinOptions {
freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
freeCompilerArgs += "-opt-in=kotlinx.coroutines.ObsoleteCoroutinesApi"
freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
freeCompilerArgs += "-opt-in=kotlin.ExperimentalStdlibApi"
}
}

compileTestKotlin {
kotlinOptions.jvmTarget = JavaVersion.VERSION_21
kotlinOptions.javaParameters = true
kotlinOptions {
freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
freeCompilerArgs += "-opt-in=kotlinx.coroutines.ObsoleteCoroutinesApi"
freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
freeCompilerArgs += "-opt-in=kotlin.ExperimentalStdlibApi"
}
}

application {
mainClass.set("io.minifyimage.website.App")
}

jar {
zip64 = true
exclude 'META-INF/.RSA', 'META-INF/.SF', 'META-INF/*.DSA'
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
from {
configurations.runtimeClasspath.collect {
it.isDirectory() ? it : zipTree(it)
}
}

}
`

Expected behavior

Push should work.

Actual behavior

Push does not work which means that the website contents does not change.

How to Reproduce?

Steps:

  1. Create project with vaadin + quarkus using examples (gradle)
  2. Add class which extends: AppShellConfigurator with annotation: "@Push(PushMode.AUTOMATIC,transport = Transport.WEBSOCKET)" or just @Push
  3. Create class for website page with annotation @UIScoped
  4. Make a viewModel for the page with which repeats sending same update to the page every X seconds.

Output of uname -a or ver

Darwin MacBook-Air.local 23.5.0 Darwin Kernel Version 23.5.0: Wed May 1 20:14:59 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T8122 arm64

Output of java -version

OpenJDK Runtime Environment Zulu22.30+13-CA (build 22.0.1+8) OpenJDK 64-Bit Server VM Zulu22.30+13-CA (build 22.0.1+8, mixed mode, sharing)

Quarkus version or git rev

3.12.0

Build tool (ie. output of mvnw --version or gradlew --version)

8.7

Additional information

No response

Expected-behavior

Push should work.

Reproduction

Steps:

  1. Create project with vaadin + quarkus using examples (gradle)
  2. Add class which extends: AppShellConfigurator with annotation: "@Push(PushMode.AUTOMATIC,transport = Transport.WEBSOCKET)" or just @Push
    3/ Create class for website page with annotation @UIScoped
    4/ Make a viewModel for the page with which repeats sending same update to the page every X seconds.

System Info

Darwin MacBook-Air.local 23.5.0 Darwin Kernel Version 23.5.0: Wed May 1 20:14:59 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T8122 arm64

OpenJDK Runtime Environment Zulu22.30+13-CA (build 22.0.1+8) OpenJDK 64-Bit Server VM Zulu22.30+13-CA (build 22.0.1+8, mixed mode, sharing)

Quarkus version: 3.12.0

Gradle wrapper: 8.7

@JasonTheDynamite JasonTheDynamite added the bug Something isn't working label Jul 2, 2024
@ZheSun88 ZheSun88 transferred this issue from vaadin/platform Jul 2, 2024
@mcollovati mcollovati transferred this issue from vaadin/flow Jul 2, 2024
@mcollovati mcollovati removed the bug Something isn't working label Jul 2, 2024
@mcollovati
Copy link
Contributor

I tried a similar setup based on the Vaadin Quarkus maven starter and cannot reproduce, neither in dev nor in production mode.
Push script is loaded correctly and updates happen correctly without user interaction.

@JasonTheDynamite could you please share a full project that reproduces the issue as a GitHub project or attach a zip file to this issue?

Also, is the application behind some reverse-proxy that might block resources from being served to the client?

@JasonTheDynamite
Copy link
Author

@mcollovati
"Also, is the application behind some reverse-proxy that might block resources from being served to the client?" - no
Attaching full reprod. The "https://192.168.1.100/VAADIN/static/push/vaadinPush.js could not be loaded. Push will not work" does not show now but pushmode is still disabled.
push-issue_reprod.zip

@JasonTheDynamite
Copy link
Author

This "https://192.168.1.100/VAADIN/static/push/vaadinPush.js could not be loaded. Push will not work." is visible when I use the websiite with ssl (https). Without SSL this message is not being displayed. Push stil is DISABLED

@mcollovati
Copy link
Contributor

@JasonTheDynamite I tried your application. I am not familiar with kotlin and gradle, but here are a couple of notes

  1. I don't know much about couroutines in kotlin, but I assume UI changes are done in UI.access() block (In VaadinDispatcher you are using UI.accessSynchronously(), I think it could be UI.access() instead)
  2. According to the application logs, PUSH is enabled and working. PUSH annotation is applied per UI, so you should check the status on it, not on the VaadinSession (e.g. attachEvent!!.ui.pushConfiguration.pushMode instead of VaadinSession.getCurrent().configuration.pushMode);

In the logs below, you can see that push is in AUTOMATIC mode and two changes are sent to the client via PUSH, but then the block in viewModel?.getCounterValueList()?.collectLatest { } gets not invoked anymore.

2024-07-02 14:21:56,102 DEBUG [com.vaa.flo.ser.com.PushHandler] (vert.x-eventloop-thread-1) New push connection for resource 04c339a6-be20-4537-86b8-5c58bc4a77dd with transport WEBSOCKET
2024-07-02 14:21:56,137 ERROR [io.vaa.iss.pag.hom.HomePage] (executor-thread-1) pushMode -> DISABLED
2024-07-02 14:21:56,138 ERROR [io.vaa.iss.pag.hom.HomePage] (executor-thread-1) pushMode UI -> AUTOMATIC
2024-07-02 14:21:56,170 ERROR [io.vaa.iss.pag.hom.HomePage] (executor-thread-1) getCounterValueList / newestValue -> null
2024-07-02 14:21:56,171 ERROR [io.vaa.iss.pag.hom.HomePage] (executor-thread-1) getCounterValueList / counterSpan.text -> 
2024-07-02 14:21:56,179 DEBUG [com.vaa.flo.ser.com.UidlWriter] (executor-thread-1) * Creating response to client
2024-07-02 14:21:56,201 DEBUG [com.vaa.flo.ser.com.PushHandler] (vert.x-eventloop-thread-1) Received message from resource 04c339a6-be20-4537-86b8-5c58bc4a77dd
2024-07-02 14:21:56,204 DEBUG [com.vaa.flo.ser.com.UidlWriter] (vert.x-eventloop-thread-1) * Creating response to client
2024-07-02 14:21:57,157 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 0
2024-07-02 14:21:57,165 ERROR [io.vaa.iss.pag.hom.HomePage] (DefaultDispatcher-worker-1) getCounterValueList / newestValue -> 0
2024-07-02 14:21:57,165 ERROR [io.vaa.iss.pag.hom.HomePage] (DefaultDispatcher-worker-1) getCounterValueList / counterSpan.text -> 0
2024-07-02 14:21:57,166 DEBUG [com.vaa.flo.ser.com.UidlWriter] (DefaultDispatcher-worker-1) * Creating response to client
2024-07-02 14:21:58,167 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 1
2024-07-02 14:21:59,169 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 2
2024-07-02 14:22:00,170 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 3
2024-07-02 14:22:01,171 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 4
2024-07-02 14:22:02,172 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 5
2024-07-02 14:22:03,174 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 6
2024-07-02 14:22:04,175 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 7
2024-07-02 14:22:05,175 ERROR [io.vaa.iss.pag.hom.HomePageViewModel] (DefaultDispatcher-worker-1) counterValueList / repeat -> 8
...

Given that, it looks like to me that the problem is not PUSH, but the callback not being invoked on changes applied to getCounterValueList().
Also, clicking the "CLICK to receive all push UI changes" button has no effects. I cannot see any updates to the UI because there a no pending changes.

@mcollovati
Copy link
Contributor

Maybe @mvysny can provide some advice here

@JasonTheDynamite
Copy link
Author

@mcollovati ok I will look into it.
Then why there is this error message
image
when ssl is enabled ?

@mcollovati
Copy link
Contributor

Can you please provide the steps to run your application with SSL enabled?

@mcollovati
Copy link
Contributor

Ok, I managed to start the application with SSL. What I can see is that with SSL enabled, the push script is downloaded as a binary file instead of a JavaScript resource.
The culprit seems to be this setting quarkus.http.enable-compression=true in application.properties
If I remove it, the Vaadin PUSH script is downloaded correctly and there is no error message.

@JasonTheDynamite
Copy link
Author

@mcollovati ok so how to use compression if using it crashes push ?

@mcollovati
Copy link
Contributor

Push script is added with a standard <script> tag, so I don't know why it is not working with compression. Other javascript resources are working fine (e.g. index-xxxxx.js).
I wonder if it is something specific to Quarkus and SSL.

@JasonTheDynamite
Copy link
Author

@mcollovati so it seems I did found a bug 🙂

@mcollovati
Copy link
Contributor

I wonder if it is a problem of double compression. Flow already provides compressed version of several resources.
Maybe Quarkus does not detect that the resource is already compressed and it does an additional compression.
It can be tested by downloading vaadinPush.js

@JasonTheDynamite
Copy link
Author

It might be this way. I cant test this - javascript is something I am not familiar with

@mcollovati
Copy link
Contributor

I can confirm that the vaadinPush.js is compressed twice. It looks like a Quarkus issue

@JasonTheDynamite
Copy link
Author

Hmm so now I should be waiting for a fix ? 🙂
@mcollovati I am very grateful for your help with this 🙏

@JasonTheDynamite
Copy link
Author

@mcollovati so I checked everything and it seems that disabling compression helps bu still the UI is not getting updated 😢

@mcollovati
Copy link
Contributor

Unfortunately, I cannot help with Kotlin, but I tried to add the following to the HomePage.onAttach(...) method and I can see the UI updated every second

        val service = Executors.newScheduledThreadPool(1)
        val ui = attachEvent!!.ui
        service.scheduleAtFixedRate({
            ui.access {
                counterSpan.text = LocalTime.now().toString()
            }
        }, 1, 1 , TimeUnit.SECONDS)

@mcollovati
Copy link
Contributor

So, I suppose that there might be some issue in your code that prevents viewModel?.getCounterValueList()?collectLatest() callback being executed.

I hope @mvysny could take a look at your code and provide some suggestion.

@JasonTheDynamite
Copy link
Author

JasonTheDynamite commented Jul 3, 2024

@mvysny
I did mamy project using vaadin + spring boot and with this combination the same kotlin StateFlow with collect() or collectLatest() works. It does not work with vaadin + quarkus combination

@mvysny
Copy link
Member

mvysny commented Jul 3, 2024

@JasonTheDynamite regarding Kotlin Coroutines, it's very important to use the correct coroutine dispatcher which calls ui.access(). Please see https://github.com/mvysny/vaadin-coroutines-demo for an example.

@mshabarov mshabarov moved this from 🆕 Needs triage to 🔎 Investigation in Vaadin Flow bugs & maintenance (Vaadin 10+) Sep 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🔎 Investigation
Development

No branches or pull requests

4 participants