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.

Heartbeat.java 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * Copyright 2000-2014 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client.communication;
  17. import java.util.logging.Logger;
  18. import com.google.gwt.http.client.Request;
  19. import com.google.gwt.http.client.RequestBuilder;
  20. import com.google.gwt.http.client.RequestCallback;
  21. import com.google.gwt.http.client.RequestException;
  22. import com.google.gwt.http.client.Response;
  23. import com.google.gwt.user.client.Timer;
  24. import com.vaadin.client.ApplicationConnection;
  25. import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
  26. import com.vaadin.client.ApplicationConnection.ConnectionStatusEvent;
  27. import com.vaadin.shared.ApplicationConstants;
  28. import com.vaadin.shared.ui.ui.UIConstants;
  29. /**
  30. * Handles sending of heartbeats to the server and reacting to the response
  31. *
  32. * @since 7.2
  33. * @author Vaadin Ltd
  34. */
  35. public class Heartbeat {
  36. private Timer timer = new Timer() {
  37. @Override
  38. public void run() {
  39. send();
  40. }
  41. };
  42. private ApplicationConnection connection;
  43. private String uri;
  44. private int interval = -1;
  45. private static Logger getLogger() {
  46. return Logger.getLogger(Heartbeat.class.getName());
  47. }
  48. /**
  49. * Initializes the heartbeat for the given application connection
  50. *
  51. * @param connection
  52. * the connection
  53. */
  54. public void init(ApplicationConnection applicationConnection) {
  55. connection = applicationConnection;
  56. setInterval(connection.getConfiguration().getHeartbeatInterval());
  57. uri = ApplicationConnection.addGetParameters(connection
  58. .translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX
  59. + ApplicationConstants.HEARTBEAT_PATH + '/'),
  60. UIConstants.UI_ID_PARAMETER + "="
  61. + connection.getConfiguration().getUIId());
  62. connection.addHandler(
  63. ApplicationConnection.ApplicationStoppedEvent.TYPE,
  64. new ApplicationConnection.ApplicationStoppedHandler() {
  65. @Override
  66. public void onApplicationStopped(
  67. ApplicationStoppedEvent event) {
  68. setInterval(-1);
  69. }
  70. });
  71. }
  72. /**
  73. * Sends a heartbeat to the server
  74. */
  75. public void send() {
  76. timer.cancel();
  77. final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri);
  78. final RequestCallback callback = new RequestCallback() {
  79. @Override
  80. public void onResponseReceived(Request request, Response response) {
  81. int status = response.getStatusCode();
  82. // Notify network observers about response status
  83. connection.fireEvent(new ConnectionStatusEvent(status));
  84. if (status == Response.SC_OK) {
  85. getLogger().fine("Heartbeat response OK");
  86. } else if (status == 0) {
  87. getLogger().warning(
  88. "Failed sending heartbeat, server is unreachable, retrying in "
  89. + interval + "secs.");
  90. } else if (status >= 500) {
  91. getLogger().warning(
  92. "Failed sending heartbeat, see server logs, retrying in "
  93. + interval + "secs.");
  94. } else if (status == Response.SC_GONE) {
  95. connection.showSessionExpiredError(null);
  96. // If session is expired break the loop
  97. return;
  98. } else {
  99. getLogger().warning(
  100. "Failed sending heartbeat to server. Error code: "
  101. + status);
  102. }
  103. // Don't break the loop
  104. schedule();
  105. }
  106. @Override
  107. public void onError(Request request, Throwable exception) {
  108. getLogger().severe(
  109. "Exception sending heartbeat: "
  110. + exception.getMessage());
  111. // Notify network observers about response status
  112. connection.fireEvent(new ConnectionStatusEvent(0));
  113. // Don't break the loop
  114. schedule();
  115. }
  116. };
  117. rb.setCallback(callback);
  118. try {
  119. getLogger().fine("Sending heartbeat request...");
  120. rb.send();
  121. } catch (RequestException re) {
  122. callback.onError(null, re);
  123. }
  124. }
  125. /**
  126. * @return the interval at which heartbeat requests are sent
  127. */
  128. public int getInterval() {
  129. return interval;
  130. }
  131. /**
  132. * Updates the schedule of the heartbeat to match the set interval. A
  133. * negative interval disables the heartbeat.
  134. */
  135. public void schedule() {
  136. if (interval > 0) {
  137. getLogger()
  138. .fine("Scheduling heartbeat in " + interval + " seconds");
  139. timer.schedule(interval * 1000);
  140. } else {
  141. getLogger().fine("Disabling heartbeat");
  142. timer.cancel();
  143. }
  144. }
  145. /**
  146. * @return the application connection
  147. */
  148. @Deprecated
  149. protected ApplicationConnection getConnection() {
  150. return connection;
  151. }
  152. /**
  153. * Changes the heartbeatInterval in runtime and applies it.
  154. *
  155. * @param heartbeatInterval
  156. * new interval in seconds.
  157. */
  158. public void setInterval(int heartbeatInterval) {
  159. getLogger().info(
  160. "Setting hearbeat interval to " + heartbeatInterval + "sec.");
  161. interval = heartbeatInterval;
  162. schedule();
  163. }
  164. }