]> source.dussan.org Git - vaadin-framework.git/commitdiff
Stop polling if Communication Error #12362
authorJohn Ahlroos <john@vaadin.com>
Mon, 28 Oct 2013 14:41:24 +0000 (16:41 +0200)
committerVaadin Code Review <review@vaadin.com>
Wed, 30 Oct 2013 07:37:48 +0000 (07:37 +0000)
This change adds a new ApplicationStopped event which is triggered
whenever the ApplicationConnection marks the application as stopped.
This event is listened by the UIConnector and will terminate any polling
that might be currently done.

Change-Id: I5e698fba7a94f530f69a9f6f554eea896c370824

client/src/com/vaadin/client/ApplicationConnection.java
client/src/com/vaadin/client/ui/ui/UIConnector.java

index 4314602bc2932eecbcd2beee36124158876159bc..f95cec4fbc6363d2c325d6833446f6a5f037450e 100644 (file)
@@ -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;
         }
 
@@ -359,6 +361,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.
      */
@@ -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());
+    }
+
 }
index 46b5f63180526912d24be2406bb982f7d50fb649..8813d7060921b8a110c00584c45c1993d894b677 100644 (file)
@@ -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();