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.

ReconnectingCommunicationProblemHandler.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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 com.google.gwt.core.shared.GWT;
  18. import com.google.gwt.http.client.Request;
  19. import com.google.gwt.http.client.Response;
  20. import com.google.gwt.user.client.Timer;
  21. import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
  22. import elemental.json.JsonObject;
  23. //FIXME This is just a test and should be merged with DCPH
  24. public class ReconnectingCommunicationProblemHandler extends
  25. DefaultCommunicationProblemHandler {
  26. private enum Type {
  27. HEARTBEAT, MESSAGE
  28. }
  29. ReconnectDialog reconnectDialog = GWT.create(ReconnectDialog.class);
  30. int reconnectAttempt = 0;
  31. private Type reconnectionCause = null;
  32. @Override
  33. public void xhrException(CommunicationProblemEvent event) {
  34. getLogger().warning("xhrException");
  35. handleTemporaryError(Type.MESSAGE, event.getPayload());
  36. }
  37. @Override
  38. public boolean heartbeatException(Request request, Throwable exception) {
  39. handleTemporaryError(Type.HEARTBEAT, null);
  40. return true;
  41. }
  42. @Override
  43. public boolean heartbeatInvalidStatusCode(Request request, Response response) {
  44. if (response.getStatusCode() == Response.SC_GONE) {
  45. // Session expired
  46. resolveTemporaryError(Type.HEARTBEAT, false);
  47. return super.heartbeatInvalidStatusCode(request, response);
  48. }
  49. handleTemporaryError(Type.HEARTBEAT, null);
  50. return true;
  51. }
  52. @Override
  53. public void heartbeatOk() {
  54. resolveTemporaryError(Type.HEARTBEAT, true);
  55. }
  56. private void handleTemporaryError(Type type, final JsonObject payload) {
  57. getLogger().warning("handleTemporaryError(" + type + ")");
  58. reconnectAttempt++;
  59. reconnectionCause = type;
  60. if (!reconnectDialog.isAttached()) {
  61. // FIXME
  62. reconnectDialog.setStyleName("active", true);
  63. reconnectDialog.setOwner(getConnection().getUIConnector()
  64. .getWidget());
  65. reconnectDialog.setPopupPositionAndShow(new PositionCallback() {
  66. @Override
  67. public void setPosition(int offsetWidth, int offsetHeight) {
  68. // FIXME
  69. reconnectDialog.setPopupPosition(0, 0);
  70. }
  71. });
  72. }
  73. if (payload != null) {
  74. getConnection().getServerCommunicationHandler().endRequest();
  75. }
  76. if (reconnectAttempt >= getMaxReconnectAttempts()) {
  77. // FIXME Remove
  78. reconnectDialog.setText("Server connection lost. Gave up after "
  79. + reconnectAttempt + " attempts.");
  80. // FIXME
  81. reconnectDialog.setStyleName("active", false);
  82. getConnection().setApplicationRunning(false);
  83. } else {
  84. reconnectDialog
  85. .setText("Server connection lost, trying to reconnect... Attempt "
  86. + reconnectAttempt);
  87. // Here and not in timer to avoid TB for getting in between
  88. if (payload != null) {
  89. // FIXME: Not like this
  90. getConnection().getServerCommunicationHandler().startRequest();
  91. }
  92. // Reconnect
  93. new Timer() {
  94. @Override
  95. public void run() {
  96. if (payload != null) {
  97. getLogger().info(
  98. "Re-sending last message to the server...");
  99. getConnection().getServerCommunicationHandler().send(
  100. payload);
  101. } else {
  102. // Use heartbeat
  103. getLogger().info(
  104. "Trying to re-establish server connection...");
  105. getConnection().getHeartbeat().send();
  106. }
  107. }
  108. }.schedule(getReconnectInterval());
  109. }
  110. }
  111. /**
  112. * @since
  113. * @return
  114. */
  115. private int getMaxReconnectAttempts() {
  116. // FIXME Parameter
  117. return 15;
  118. }
  119. /**
  120. * @since
  121. * @return
  122. */
  123. private int getReconnectInterval() {
  124. // FIXME Parameter
  125. return 5000;
  126. }
  127. @Override
  128. public void xhrInvalidContent(CommunicationProblemEvent event) {
  129. getLogger().warning("xhrInvalidContent");
  130. super.xhrInvalidContent(event);
  131. };
  132. @Override
  133. public void xhrInvalidStatusCode(CommunicationProblemEvent event) {
  134. getLogger().info(
  135. "Server returned " + event.getResponse().getStatusCode()
  136. + " for xhr request");
  137. getLogger().warning("xhrInvalidStatusCode");
  138. handleTemporaryError(Type.MESSAGE, event.getPayload());
  139. }
  140. @Override
  141. public void xhrOk() {
  142. getLogger().warning("xhrOk");
  143. resolveTemporaryError(Type.MESSAGE, true);
  144. }
  145. private void resolveTemporaryError(Type type, boolean success) {
  146. getLogger().warning("resolveTemporaryError(" + type + ")");
  147. if (reconnectionCause == null) {
  148. // Not trying to reconnect
  149. return;
  150. }
  151. if (reconnectionCause == Type.MESSAGE && type == Type.HEARTBEAT) {
  152. // If a heartbeat goes through while we are trying to re-send an
  153. // XHR, we wait for the XHR to go through to avoid removing the
  154. // reconnect dialog and then possible showing it again
  155. return;
  156. }
  157. reconnectionCause = null;
  158. if (reconnectDialog.isAttached()) {
  159. reconnectDialog.hide();
  160. }
  161. if (success && reconnectAttempt != 0) {
  162. getLogger().info("Re-established connection to server");
  163. reconnectAttempt = 0;
  164. }
  165. }
  166. @Override
  167. public void pushOk(PushConnection pushConnection) {
  168. super.pushOk(pushConnection);
  169. resolveTemporaryError(Type.MESSAGE, true);
  170. }
  171. @Override
  172. public void pushNotConnected(JsonObject payload) {
  173. super.pushNotConnected(payload);
  174. handleTemporaryError(Type.MESSAGE, payload);
  175. }
  176. }