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.0KB

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