]> source.dussan.org Git - vaadin-framework.git/commitdiff
Migrate UsingServerInitiatedEvents pr9959/r3
authorErik Lumme <erik@vaadin.com>
Mon, 11 Sep 2017 12:06:32 +0000 (15:06 +0300)
committerErik Lumme <erik@vaadin.com>
Mon, 11 Sep 2017 12:06:32 +0000 (15:06 +0300)
documentation/articles/UsingServerInitiatedEvents.asciidoc [new file with mode: 0644]
documentation/articles/contents.asciidoc

diff --git a/documentation/articles/UsingServerInitiatedEvents.asciidoc b/documentation/articles/UsingServerInitiatedEvents.asciidoc
new file mode 100644 (file)
index 0000000..26221e9
--- /dev/null
@@ -0,0 +1,130 @@
+[[using-server-initiated-events]]
+Using server-initiated events
+-----------------------------
+
+The traditional way of communicating with the server is always client
+initiated. Whenever the user interacts with the application so a server
+visit is needed, the browser connects to the server, sends a request and
+waits for the response. The response is handled when received by the
+browser and the UI is updated accordingly. For basic applications this
+is all that is needed but there are also many cases when you want the
+server to be able to initiate events: updating the progress of a long
+running application, notifying you of changes in the back end, providing
+interaction between users and so on.
+
+Starting from Vaadin 7.1 you have a couple of ways you can implement
+server initiated events without requiring any external add-ons: polling
+and push. Polling is based on the client actively polling the server,
+asking “are there any news for me?” whereas push is based on keeping a
+connection constantly open to the server, allowing the server to,
+whenever it likes, send something to the client. Which you want to use
+is dependent on your use case. If you have events which occur seldom but
+you want to deliver them immediately to the user, then push might serve
+you better. If you want to avoid constant server connections and only
+need to check now and then if something has happened, polling may work
+out well for you. For any use case you should consider the two options
+and which one will better suit your needs.
+
+An important part to consider when using server initiated events is
+locking. Vaadin is built around the fact that only one thread can access
+any VaadinSession instance at any time. This is to prevent
+inconsistencies from occuring and needs to be taken into account when
+using background threads to update a UI (which lives inside a
+VaadinSession). To do proper locking when you are updating the UI you
+use the UI.access method:
+
+[source,java]
+....
+theUI.access(new Runnable() {
+  @Override
+  public void run() {
+    theUI.setContent(new Label("This is the real content"));
+  }
+});
+....
+
+The access method ensure your update is safe to do (you have exclusive
+access to the `VaadinSession`), it ensures that threadlocals work also
+inside the `run()`` method (e.g. `UI.getCurrent()``) and finally it deals with
+some typical deadlock situations. To be able to do all this it does not
+guarantee that the `Runnable` is executed immediately - on the contrary
+it will be run as soon as it is safe to run it without causing deadlocks
+by locking multiple `VaadinSessions` at once.
+
+A typical use case is the one-shot background operation which does some
+heavy lifting, updates the `UI` based on the result (which is then
+fetched by the browser by polling or pushed to the browser) and then
+goes away. This can be implemented as a `Runnable`, e.g.
+
+[source,java]
+....
+class AntCounter implements Runnable {
+  @Override
+  public void run() {
+    // Do some heavy work
+    final int result = calculateNumberOfAntsInTheWorld();
+
+    // Wrap UI updates in access to properly deal with locking
+    theUI.access(new Runnable() {
+      @Override
+      public void run() {
+        theUI.setContent(new Label("The result is " + result));
+      }
+    });
+  }
+}
+....
+
+The Runnable is typically run in a background thread using e.g. an
+`ExecutorService`.
+
+The other typical case is a long running background task which checks
+for some event and, in case that events happens, alerts the user. The
+event can originate from another user, from a change in the database or
+from somewhere else. Similarly to before, this can be implemented as a
+`Runnable`:
+
+[source,java]
+....
+class AntTracker implements Runnable {
+  @Override
+  public void run() {
+    // Do some initial work
+    int antPopulation = calculateNumberOfAntsInTheWorld();
+
+    while (true) {
+      // Loop forever and ever
+      final int antPopulationNow = calculateNumberOfAntsInTheWorld();
+      if (antPopulationNow != antPopulation) {
+        antPopulation = antPopulationNow;
+        // Wrap UI updates in access to properly deal with locking
+        theUI.access(new Runnable() {
+          @Override
+          public void run() {
+            new Notification("Ant population is now "
+              + antPopulationNow, Type.TRAY_NOTIFICATION)
+              .show(theUI.getPage());
+          }
+        });
+      }
+      // Wait for a while before calculating again
+      try {
+        Thread.sleep(5000);
+      } catch (InterruptedException e) {
+        return;
+      }
+    }
+  }
+
+  private int calculateNumberOfAntsInTheWorld() {
+    return (int) (new Date().getTime()/1500);
+  }
+}
+....
+
+The same thing can of course be implemented without the `while(true)`` loop
+by using for instance a `ScheduledExecutorService` instead to make the
+executor service handle the iteration and interval (e.g. `Executors.newScheduledThreadPool(1).scheduleAtFixedRate(...)`).
+
+For more information on how to enable push or polling in your
+application, see link:EnablingServerPush.asciidoc[Enabling server push] or link:UsingPolling.asciidoc[Using polling].
index d2e77bad8311513f2730eb5f35eb65d847a2d281..462e6df4fcfe8ead2878772ccecb16ce579b3cb4 100644 (file)
@@ -36,3 +36,4 @@ are great, too.
 - link:AccessingWebPageAndBrowserInformation.asciidoc[Accessing web page and browser information]
 - link:GeneratingDynamicResourcesBasedOnURIOrParameters.asciidoc[Generating dynamic resources based on URI or parameters]
 - link:OptimizingTheWidgetSet.asciidoc[Optimizing the widget set]
+- link:UsingServerInitiatedEvents.asciidoc[Using server-initiated events]