Minimal example of Push in Vaadin 7 app ("@Push")
I want to see the most minimal example of using the new Push technology in Vaadin 7, such as the new @Push
annotation.
I am having problems getting server-push to work in my app. I would like to try a simple example app before trying to fix my own app.
Solution 1:
Simplification Of Example In The Book Of Vaadin
The Book Of Vaadin includes a chapter on Push, including an example using Vaadin Charts.
Below is my code. While based on that Vaadin Charts example mentioned above, I simplified it by replacing the use of a Chart
object with a simple Label
object. The Label updates every second or so to tell you the current time.
For Example Use Only – Use an Executor in real-world project
Caveat: My example below is built for simplicity, not intended as production code. Sleeping a thread is a crude and awkward way to manage scheduled threaded work. Java provides the Executor
facility for this kind of work. In a real-world project I would use a ScheduledExecutorService rather than a single sleeping Thread
object to schedule our task (of telling time). Related tip: Never use a Timer
in a Servlet environment. For a fuller and more real-world example, see my Answer to a similar Question about Push with Vaadin.
I took other shortcuts in this example, such as: I place the Label
widget directly on the UI
whereas real-world work would use a Layout
to contain the Label
.
My Configuration
My code is using Vaadin 7.3.7 with Java 8 Update 25 in NetBeans 8.0.2 and Tomcat 8.0.15 on Mac OS X 10.8.5 (Mountain Lion).
Push technology is relatively new, especially the WebSocket variety. Be sure to use recent versions of your web server, such as recent updates to Tomcat 7 or 8.
How To Use This Example
This code is a single file, the MyUI.java
file. To use this code:
- Create a new default Vaadin app in your IDE of choice.
- Get that example running successfully, before modifying.
- Replace the contents of
MyUI
class with the code below.
@Push
Annotation
Beside the code in the middle, note how we added the @Push
annotation to the MyUI
class definition.
Example Code
package com.example.pushvaadinapp;
import com.vaadin.annotations.Push;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import javax.servlet.annotation.WebServlet;
/**
* © 2014 Basil Bourque. This source code may be used freely forever by anyone absolving me of any and all responsibility.
*
* +----------------------------+
* | NOT FOR PRODUCTION USE! |
* +----------------------------+
* Sleeping threads is an awkward way to manage scheduled background work.
* By the way, never use a 'Timer' in a Servlet environment.
* Use an Executor instead, probably a ScheduledExecutorService.
*/
@Push
@Theme ( "mytheme" )
@Widgetset ( "com.example.pushvaadinapp.MyAppWidgetset" )
public class MyUI extends UI
{
Label label = new Label( "Now : " );
@Override
protected void init ( VaadinRequest vaadinRequest )
{
// Put a widget on this UI. In real work we would use a Layout.
setContent( this.label );
// Start the data feed thread
new FeederThread().start();
}
@WebServlet ( urlPatterns = "/*" , name = "MyUIServlet" , asyncSupported = true )
@VaadinServletConfiguration ( ui = MyUI.class , productionMode = false )
public static class MyUIServlet extends VaadinServlet
{
}
public void tellTime ()
{
label.setValue( "Now : " + new java.util.Date() ); // If Java 8, use: Instant.now(). Or, in Joda-Time: DateTime.now().
}
class FeederThread extends Thread
{
int count = 0;
@Override
public void run ()
{
try {
// Update the data for a while
while ( count < 100 ) {
Thread.sleep( 1000 );
// Calling special 'access' method on UI object, for inter-thread communication.
access( new Runnable()
{
@Override
public void run ()
{
count ++;
tellTime();
}
} );
}
// Inform that we have stopped running
// Calling special 'access' method on UI object, for inter-thread communication.
access( new Runnable()
{
@Override
public void run ()
{
label.setValue( "Done." );
}
} );
} catch ( InterruptedException e ) {
e.printStackTrace();
}
}
}
}
Solution 2:
Here is a simple but full Vaadin 8 example that demonstrates how to use server push and Java EE messaging APIs to send messages between different UIs using the Broadcaster pattern described in Vaadin docs. If you are not interested in messaging or broadcasting to other users, then look at ReceiveMessageUI only.
In principle it all boils down to the following:
- Annotate the Vaadin UI with
@Push
to enable server push (by default over a WebSocket connection) -
Wrap UI updates with
access()
when accessing it from other threads, sending updates happens automatically by default:getUI().access(() -> layout.addComponent(new Label("Hello!")));
Use the Broadcaster pattern to publish messages to other users and to subscribe to their messages.