You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UsingServerInitiatedEvents.asciidoc 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. ---
  2. title: Using Server Initiated Events
  3. order: 30
  4. layout: page
  5. ---
  6. [[using-server-initiated-events]]
  7. Using server-initiated events
  8. -----------------------------
  9. The traditional way of communicating with the server is always client
  10. initiated. Whenever the user interacts with the application so a server
  11. visit is needed, the browser connects to the server, sends a request and
  12. waits for the response. The response is handled when received by the
  13. browser and the UI is updated accordingly. For basic applications this
  14. is all that is needed but there are also many cases when you want the
  15. server to be able to initiate events: updating the progress of a long
  16. running application, notifying you of changes in the back end, providing
  17. interaction between users and so on.
  18. Starting from Vaadin 7.1 you have a couple of ways you can implement
  19. server initiated events without requiring any external add-ons: polling
  20. and push. Polling is based on the client actively polling the server,
  21. asking “are there any news for me?” whereas push is based on keeping a
  22. connection constantly open to the server, allowing the server to,
  23. whenever it likes, send something to the client. Which you want to use
  24. is dependent on your use case. If you have events which occur seldom but
  25. you want to deliver them immediately to the user, then push might serve
  26. you better. If you want to avoid constant server connections and only
  27. need to check now and then if something has happened, polling may work
  28. out well for you. For any use case you should consider the two options
  29. and which one will better suit your needs.
  30. An important part to consider when using server initiated events is
  31. locking. Vaadin is built around the fact that only one thread can access
  32. any VaadinSession instance at any time. This is to prevent
  33. inconsistencies from occuring and needs to be taken into account when
  34. using background threads to update a UI (which lives inside a
  35. VaadinSession). To do proper locking when you are updating the UI you
  36. use the UI.access method:
  37. [source,java]
  38. ....
  39. theUI.access(new Runnable() {
  40. @Override
  41. public void run() {
  42. theUI.setContent(new Label("This is the real content"));
  43. }
  44. });
  45. ....
  46. The access method ensure your update is safe to do (you have exclusive
  47. access to the `VaadinSession`), it ensures that threadlocals work also
  48. inside the `run()`` method (e.g. `UI.getCurrent()``) and finally it deals with
  49. some typical deadlock situations. To be able to do all this it does not
  50. guarantee that the `Runnable` is executed immediately - on the contrary
  51. it will be run as soon as it is safe to run it without causing deadlocks
  52. by locking multiple `VaadinSessions` at once.
  53. A typical use case is the one-shot background operation which does some
  54. heavy lifting, updates the `UI` based on the result (which is then
  55. fetched by the browser by polling or pushed to the browser) and then
  56. goes away. This can be implemented as a `Runnable`, e.g.
  57. [source,java]
  58. ....
  59. class AntCounter implements Runnable {
  60. @Override
  61. public void run() {
  62. // Do some heavy work
  63. final int result = calculateNumberOfAntsInTheWorld();
  64. // Wrap UI updates in access to properly deal with locking
  65. theUI.access(new Runnable() {
  66. @Override
  67. public void run() {
  68. theUI.setContent(new Label("The result is " + result));
  69. }
  70. });
  71. }
  72. }
  73. ....
  74. The Runnable is typically run in a background thread using e.g. an
  75. `ExecutorService`.
  76. The other typical case is a long running background task which checks
  77. for some event and, in case that events happens, alerts the user. The
  78. event can originate from another user, from a change in the database or
  79. from somewhere else. Similarly to before, this can be implemented as a
  80. `Runnable`:
  81. [source,java]
  82. ....
  83. class AntTracker implements Runnable {
  84. @Override
  85. public void run() {
  86. // Do some initial work
  87. int antPopulation = calculateNumberOfAntsInTheWorld();
  88. while (true) {
  89. // Loop forever and ever
  90. final int antPopulationNow = calculateNumberOfAntsInTheWorld();
  91. if (antPopulationNow != antPopulation) {
  92. antPopulation = antPopulationNow;
  93. // Wrap UI updates in access to properly deal with locking
  94. theUI.access(new Runnable() {
  95. @Override
  96. public void run() {
  97. new Notification("Ant population is now "
  98. + antPopulationNow, Type.TRAY_NOTIFICATION)
  99. .show(theUI.getPage());
  100. }
  101. });
  102. }
  103. // Wait for a while before calculating again
  104. try {
  105. Thread.sleep(5000);
  106. } catch (InterruptedException e) {
  107. return;
  108. }
  109. }
  110. }
  111. private int calculateNumberOfAntsInTheWorld() {
  112. return (int) (new Date().getTime()/1500);
  113. }
  114. }
  115. ....
  116. The same thing can of course be implemented without the `while(true)`` loop
  117. by using for instance a `ScheduledExecutorService` instead to make the
  118. executor service handle the iteration and interval (e.g. `Executors.newScheduledThreadPool(1).scheduleAtFixedRate(...)`).
  119. For more information on how to enable push or polling in your
  120. application, see link:EnablingServerPush.asciidoc[Enabling server push] or link:UsingPolling.asciidoc[Using polling].