I’m using Vaadin 23 to test real-time UI updates with message distribution over JMS in a WildFly 26 (Jakarta EE 8) cluster. There is a Vaadin view that allows sending and receiving messages across the cluster. The view broacasts the messages using the broadcaster pattern. Besides broadcasting to local listeners, the broadcaster relies on CDI events and the jakartaee-clustered-cdi-events EJB module to send the events to other cluster nodes via JMS. Local broadcasts update the view as expected, but when a message arrives from another node over JMS, the Vaadin view reloads unexpectedly. Vaadin 23 completely fails to show the messages, while Vaadin 8 is able to show the messages after page reload (I also created a Vaadin 8 version of the application). See attached screencasts below that demonstrate this behavior.
Here’s how the Vaadin 23 application behaves. First two windows from left are two different user sessions on the same node, the rightmost window is on a different node. Broadcast between different users on the same node works, but completely fails between nodes.
Here’s how the Vaadin 8 application behaves. Here both windows are on different nodes. You can see messages moving between nodes successfully after page reload.
Finally, here’s the Vaadin 8 application debug log from browser console that has a couple of interesting lines. Notably:
Thu Jan 18 21:01:32 GMT+200 2024 com.vaadin.client.communication.XhrConnection
INFO: Received xhr message: for(;;);[{"changes":{},"resources":{},"locales":{},"meta":{"appError":{"caption":"Session Expired","url":null,"message":"Take note of any unsaved data, and <u>click here</u> or press ESC key to continue.","details":null}},"syncId":-1}] line 9 > injectedScript:1:245
Thu Jan 18 21:01:32 GMT+200 2024 com.vaadin.client.communication.MessageHandler
SEVERE: Response didn't contain a server id. Please verify that the server is up-to-date and that the response data has not been modified in transmission. line 9 > injectedScript:1:160
And here is the Vaadin 23 application debug log that doesn’t have much useful information, unlike in Vaadin 8. I’m missing the detailed log of Vaadin 8… message.txt (2.19 KB)
Nice report! For clarification, the listener function on the remote node is being called, right?
Thanks for the good words! Yes, the listener function on the remote node is called, see the attached detailed log.
Here’s a breakdown of the events in the log:
Message received and broadcasted on node 1.
AbstractBroadcaster on wildfly-node1 receives a “hello” message.
For some reason there are four MainView instances in four threads concurrently receiving this message on wildfly-node1?
Message is sent to the JMS topic on node 1.
JMSMessageSender on wildfly-node1 sends the “hello” message to the CLUSTER_CDI_EVENTS JMS topic.
Message received from the JMS topic on node 1.
JMSMessageReceiver on wildfly-node1 receives the message from the JMS topic
Message to self is detected, no further processing occurs on node 1.
Message received from the JMS topic on node 2.
JMSMessageReceiver on wildfly-node2 also receives the message from the JMS topic.
AbstractBroadcaster on wildfly-node2 logs the receipt of the message.
Again for some reason 3 MainView instances in seprate threads concurrently receive the message on wildfly-node2.
Views are reloaded.
AbstractBroadcaster on both nodes logs the registration of new MainView listeners. The registration is called from the onAttached() event handler. message.txt (3.45 KB)
I think what may be happening is that there is a CDI instance of your view in the CDI context, but it’s not a Vaadin UI-bound CDI instance
Considering that the code is copied from the standard CDI starter, wouldn’t this be a highly visible bug?
If that is the case, can you make the MainView @RequestScoped?
I tried (somewhat reluctantly) and deployment fails with error Caused by: org.jboss.weld.exceptions.DeploymentException: Normal scoped Vaadin components are not supported. 'org.test.MainView' should not belong to a normal scope. The error message is quite clear I think. I would rather not change the standard CDI example scopes unless there is a convincing rationale for this. But many thanks for the helpful suggestion !
The generic CDI event observer methods in AbstractBroadcaster were the culprit. Generic types are erased during runtime, so when using @Observes or @ObservesAsync with a generic type, the CDI container only saw the raw type, which led to the unintended behavior. Real glad it was a simple mistake after all. Seems obvious in hindsight, but all the symptoms were so confusing that I thought it was somehow related to Vaadin. Here’s the fix: https://github.com/mrts/test-jakartaee-clustered-cdi-events/commit/c11dd612945a06df87829455886a939591fb2bf0