aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java89
-rw-r--r--client/src/com/vaadin/client/ui/ui/UIConnector.java25
2 files changed, 105 insertions, 9 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 4314602bc2..f95cec4fbc 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Logger;
import com.google.gwt.aria.client.LiveValue;
import com.google.gwt.aria.client.RelevantValue;
@@ -63,6 +64,7 @@ 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;
@@ -294,7 +296,7 @@ public class ApplicationConnection {
}
@Override
- public com.google.gwt.event.shared.GwtEvent.Type<CommunicationHandler> getAssociatedType() {
+ public Type<CommunicationHandler> getAssociatedType() {
return TYPE;
}
@@ -314,7 +316,7 @@ public class ApplicationConnection {
}
@Override
- public com.google.gwt.event.shared.GwtEvent.Type<CommunicationHandler> getAssociatedType() {
+ public Type<CommunicationHandler> getAssociatedType() {
return TYPE;
}
@@ -349,7 +351,7 @@ public class ApplicationConnection {
public static Type<CommunicationHandler> TYPE = new Type<CommunicationHandler>();
@Override
- public com.google.gwt.event.shared.GwtEvent.Type<CommunicationHandler> getAssociatedType() {
+ public Type<CommunicationHandler> getAssociatedType() {
return TYPE;
}
@@ -360,6 +362,34 @@ public class ApplicationConnection {
}
/**
+ * Event triggered when a application is stopped by calling
+ * {@link ApplicationConnection#setApplicationRunning(false)}.
+ *
+ * To listen for the event add a {@link ApplicationStoppedHandler} by
+ * invoking
+ * {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)}
+ * to the {@link ApplicationConnection}
+ *
+ * @since 7.1.8
+ * @author Vaadin Ltd
+ */
+ public static class ApplicationStoppedEvent extends
+ GwtEvent<ApplicationStoppedHandler> {
+
+ public static Type<ApplicationStoppedHandler> TYPE = new Type<ApplicationStoppedHandler>();
+
+ @Override
+ public Type<ApplicationStoppedHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(ApplicationStoppedHandler listener) {
+ listener.onApplicationStopped(this);
+ }
+ }
+
+ /**
* Allows custom handling of communication errors.
*/
public interface CommunicationErrorHandler {
@@ -377,6 +407,27 @@ public class ApplicationConnection {
public boolean onError(String details, int statusCode);
}
+ /**
+ * A listener for listening to application stopped events. The listener can
+ * be added to a {@link ApplicationConnection} by invoking
+ * {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)}
+ *
+ * @since 7.1.8
+ * @author Vaadin Ltd
+ */
+ public interface ApplicationStoppedHandler extends EventHandler {
+
+ /**
+ * Triggered when the {@link ApplicationConnection} marks a previously
+ * running application as stopped by invoking
+ * {@link ApplicationConnection#setApplicationRunning(false)}
+ *
+ * @param event
+ * the event triggered by the {@link ApplicationConnection}
+ */
+ void onApplicationStopped(ApplicationStoppedEvent event);
+ }
+
private CommunicationErrorHandler communicationErrorDelegate = null;
private VLoadingIndicator loadingIndicator;
@@ -751,6 +802,10 @@ public class ApplicationConnection {
showCommunicationError(details, statusCode);
}
endRequest();
+
+ // Consider application not running any more and prevent all
+ // future requests
+ setApplicationRunning(false);
}
@Override
@@ -882,10 +937,10 @@ public class ApplicationConnection {
VConsole.log("JSON parsing took "
+ (new Date().getTime() - start.getTime()) + "ms");
- if (applicationRunning) {
+ if (isApplicationRunning()) {
handleReceivedJSONMessage(start, jsonText, json);
} else {
- applicationRunning = true;
+ setApplicationRunning(true);
handleWhenCSSLoaded(jsonText, json);
}
}
@@ -1121,7 +1176,7 @@ public class ApplicationConnection {
retryCanceledActiveRequest = false;
webkitMaybeIgnoringRequests = false;
- if (applicationRunning) {
+ if (isApplicationRunning()) {
checkForPendingVariableBursts();
runPostRequestHooks(configuration.getRootPanelId());
}
@@ -1456,7 +1511,7 @@ public class ApplicationConnection {
error.getString("message"),
error.getString("url"));
- applicationRunning = false;
+ setApplicationRunning(false);
}
Profiler.leave("Error handling");
}
@@ -2379,6 +2434,12 @@ public class ApplicationConnection {
*/
public void addMethodInvocationToQueue(MethodInvocation invocation,
boolean delayed, boolean lastOnly) {
+ if (!isApplicationRunning()) {
+ getLogger()
+ .warning(
+ "Trying to invoke method on not yet started or stopped application");
+ return;
+ }
String tag;
if (lastOnly) {
tag = invocation.getLastOnlyTag();
@@ -2437,7 +2498,7 @@ public class ApplicationConnection {
private boolean deferedSendPending = false;
private void doSendPendingVariableChanges() {
- if (applicationRunning) {
+ if (isApplicationRunning()) {
if (hasActiveRequest() || (push != null && !push.isActive())) {
// skip empty queues if there are pending bursts to be sent
if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) {
@@ -2449,6 +2510,11 @@ public class ApplicationConnection {
} else {
buildAndSendVariableBurst(pendingInvocations);
}
+ } else {
+ getLogger()
+ .warning(
+ "Trying to send variable changes from not yet started or stopped application");
+ return;
}
}
@@ -3384,6 +3450,9 @@ public class ApplicationConnection {
}
public void setApplicationRunning(boolean running) {
+ if (applicationRunning && !running) {
+ eventBus.fireEvent(new ApplicationStoppedEvent());
+ }
applicationRunning = running;
}
@@ -3486,4 +3555,8 @@ public class ApplicationConnection {
}
}
+ private static Logger getLogger() {
+ return Logger.getLogger(ApplicationConnection.class.getName());
+ }
+
}
diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java
index 46b5f63180..8813d70609 100644
--- a/client/src/com/vaadin/client/ui/ui/UIConnector.java
+++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java
@@ -45,6 +45,7 @@ import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
@@ -320,7 +321,8 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
.getPaintableAttribute("focused", getConnection());
if (paintable == null) {
- // Do not try to focus invisible components which not present in UIDL
+ // Do not try to focus invisible components which not
+ // present in UIDL
return;
}
@@ -467,6 +469,21 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
// side-effects from focusing (scrollIntoView).
getWidget().getElement().focus();
}
+
+ applicationConnection.addHandler(
+ ApplicationConnection.ApplicationStoppedEvent.TYPE,
+ new ApplicationConnection.ApplicationStoppedHandler() {
+
+ @Override
+ public void onApplicationStopped(
+ ApplicationStoppedEvent event) {
+ // Stop any polling
+ if (pollTimer != null) {
+ pollTimer.cancel();
+ pollTimer = null;
+ }
+ }
+ });
}
private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
@@ -686,6 +703,12 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
pollTimer = new Timer() {
@Override
public void run() {
+ if (getState().pollInterval < 0) {
+ // Polling has been cancelled server side
+ pollTimer.cancel();
+ pollTimer = null;
+ return;
+ }
getRpcProxy(UIServerRpc.class).poll();
// Send changes even though poll is @Delayed
getConnection().sendPendingVariableChanges();