diff options
-rw-r--r-- | client/src/com/vaadin/client/ApplicationConnection.java | 89 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/ui/UIConnector.java | 25 |
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(); |