aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2014-01-23 23:10:21 +0200
committerVaadin Code Review <review@vaadin.com>2014-02-04 10:41:29 +0000
commitc54c5e26d82cf22ff182904323fb4f215b03a438 (patch)
tree23b83e48548bcb7352f1b95df330689fe503ff7c
parenteca905f8d6b527d7af41416eb96cf4d328167047 (diff)
downloadvaadin-framework-c54c5e26d82cf22ff182904323fb4f215b03a438.tar.gz
vaadin-framework-c54c5e26d82cf22ff182904323fb4f215b03a438.zip
Separate heartbeat functionality from ApplicationConnection
* Correctly cancels the timer if the interval is updated * Listens to ApplicationStoppedEvents and disables the heartbeat (#13249) Change-Id: I5f4f778583954a1dd22ffeb39ef3b8fa07b85a1c
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java66
-rw-r--r--client/src/com/vaadin/client/communication/Heartbeat.java171
2 files changed, 182 insertions, 55 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 8a3841b173..c4814d7e66 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -65,9 +65,11 @@ import com.google.gwt.user.client.Window.ClosingHandler;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ApplicationConfiguration.ErrorMessage;
+import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
import com.vaadin.client.ResourceLoader.ResourceLoadEvent;
import com.vaadin.client.ResourceLoader.ResourceLoadListener;
import com.vaadin.client.communication.HasJavaScriptConnectorHelper;
+import com.vaadin.client.communication.Heartbeat;
import com.vaadin.client.communication.JavaScriptMethodInvocation;
import com.vaadin.client.communication.JsonDecoder;
import com.vaadin.client.communication.JsonEncoder;
@@ -427,6 +429,8 @@ public class ApplicationConnection {
private VLoadingIndicator loadingIndicator;
+ private Heartbeat heartbeat = GWT.create(Heartbeat.class);
+
public static class MultiStepDuration extends Duration {
private int previousStep = elapsedMillis();
@@ -489,7 +493,7 @@ public class ApplicationConnection {
getLoadingIndicator().show();
- scheduleHeartbeat();
+ heartbeat.init(this);
Window.addWindowClosingHandler(new ClosingHandler() {
@Override
@@ -3310,20 +3314,11 @@ public class ApplicationConnection {
* interval elapses if the interval is a positive number. Otherwise, does
* nothing.
*
- * @see #sendHeartbeat()
- * @see ApplicationConfiguration#getHeartbeatInterval()
+ * @deprecated as of 7.2, use {@link Heartbeat#schedule()} instead
*/
+ @Deprecated
protected void scheduleHeartbeat() {
- final int interval = getConfiguration().getHeartbeatInterval();
- if (interval > 0) {
- VConsole.log("Scheduling heartbeat in " + interval + " seconds");
- new Timer() {
- @Override
- public void run() {
- sendHeartbeat();
- }
- }.schedule(interval * 1000);
- }
+ heartbeat.schedule();
}
/**
@@ -3332,51 +3327,12 @@ public class ApplicationConnection {
* Heartbeat requests are used to inform the server that the client-side is
* still alive. If the client page is closed or the connection lost, the
* server will eventually close the inactive UI.
- * <p>
- * <b>TODO</b>: Improved error handling, like in doUidlRequest().
*
- * @see #scheduleHeartbeat()
+ * @deprecated as of 7.2, use {@link Heartbeat#send()} instead
*/
+ @Deprecated
protected void sendHeartbeat() {
- final String uri = addGetParameters(
- translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX
- + ApplicationConstants.HEARTBEAT_PATH + '/'),
- UIConstants.UI_ID_PARAMETER + "="
- + getConfiguration().getUIId());
-
- final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri);
-
- final RequestCallback callback = new RequestCallback() {
-
- @Override
- public void onResponseReceived(Request request, Response response) {
- int status = response.getStatusCode();
- if (status == Response.SC_OK) {
- // TODO Permit retry in some error situations
- VConsole.log("Heartbeat response OK");
- scheduleHeartbeat();
- } else if (status == Response.SC_GONE) {
- showSessionExpiredError(null);
- } else {
- VConsole.error("Failed sending heartbeat to server. Error code: "
- + status);
- }
- }
-
- @Override
- public void onError(Request request, Throwable exception) {
- VConsole.error("Exception sending heartbeat: " + exception);
- }
- };
-
- rb.setCallback(callback);
-
- try {
- VConsole.log("Sending heartbeat request...");
- rb.send();
- } catch (RequestException re) {
- callback.onError(null, re);
- }
+ heartbeat.send();
}
/**
diff --git a/client/src/com/vaadin/client/communication/Heartbeat.java b/client/src/com/vaadin/client/communication/Heartbeat.java
new file mode 100644
index 0000000000..46c8d62c71
--- /dev/null
+++ b/client/src/com/vaadin/client/communication/Heartbeat.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.communication;
+
+import java.util.logging.Logger;
+
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
+import com.google.gwt.http.client.RequestCallback;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.http.client.Response;
+import com.google.gwt.user.client.Timer;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
+import com.vaadin.shared.ApplicationConstants;
+import com.vaadin.shared.ui.ui.UIConstants;
+
+/**
+ * Handles sending of heartbeats to the server and reacting to the response
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public class Heartbeat {
+
+ private int interval = -1;
+ private Timer timer = new Timer() {
+ @Override
+ public void run() {
+ send();
+ }
+ };
+
+ private ApplicationConnection connection;
+
+ private static Logger getLogger() {
+ return Logger.getLogger(Heartbeat.class.getName());
+ }
+
+ /**
+ * Initializes the heartbeat for the given application connection
+ *
+ * @param applicationConnection
+ * the connection
+ */
+ public void init(ApplicationConnection applicationConnection) {
+ interval = applicationConnection.getConfiguration()
+ .getHeartbeatInterval();
+ setInterval(interval);
+ schedule();
+
+ applicationConnection.addHandler(
+ ApplicationConnection.ApplicationStoppedEvent.TYPE,
+ new ApplicationConnection.ApplicationStoppedHandler() {
+
+ @Override
+ public void onApplicationStopped(
+ ApplicationStoppedEvent event) {
+ setInterval(-1);
+ schedule();
+ }
+ });
+
+ }
+
+ /**
+ * Sends a heartbeat to the server
+ */
+ public void send() {
+ final String uri = ApplicationConnection.addGetParameters(
+ getConnection().translateVaadinUri(
+ ApplicationConstants.APP_PROTOCOL_PREFIX
+ + ApplicationConstants.HEARTBEAT_PATH + '/'),
+ UIConstants.UI_ID_PARAMETER + "="
+ + getConnection().getConfiguration().getUIId());
+
+ final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST, uri);
+
+ final RequestCallback callback = new RequestCallback() {
+
+ @Override
+ public void onResponseReceived(Request request, Response response) {
+ int status = response.getStatusCode();
+ if (status == Response.SC_OK) {
+ // TODO Permit retry in some error situations
+ getLogger().fine("Heartbeat response OK");
+ schedule();
+ } else if (status == Response.SC_GONE) {
+ // FIXME This should really do something else like send an
+ // event
+ getConnection().showSessionExpiredError(null);
+ } else {
+ getLogger().warning(
+ "Failed sending heartbeat to server. Error code: "
+ + status);
+ }
+ }
+
+ @Override
+ public void onError(Request request, Throwable exception) {
+ getLogger().severe("Exception sending heartbeat: " + exception);
+ }
+ };
+
+ rb.setCallback(callback);
+
+ try {
+ getLogger().fine("Sending heartbeat request...");
+ rb.send();
+ } catch (RequestException re) {
+ callback.onError(null, re);
+ }
+
+ }
+
+ /**
+ * @return the interval at which heartbeat requests are sent
+ */
+ public int getInterval() {
+ return interval;
+ }
+
+ /**
+ * sets the interval at which heartbeat requests are sent
+ *
+ * @param interval
+ * the new interval
+ */
+ public void setInterval(int interval) {
+ this.interval = interval;
+ }
+
+ /**
+ * Updates the schedule of the heartbeat to match the set interval. A
+ * negative interval disables the heartbeat.
+ */
+ public void schedule() {
+ if (getInterval() > 0) {
+ getLogger()
+ .fine("Scheduling heartbeat in " + interval + " seconds");
+ timer.schedule(interval * 1000);
+ } else {
+ if (timer != null) {
+ getLogger().fine("Disabling heartbeat");
+ timer.cancel();
+ }
+ }
+
+ }
+
+ /**
+ * @return the application connection
+ */
+ protected ApplicationConnection getConnection() {
+ return connection;
+ }
+
+}