]> source.dussan.org Git - vaadin-framework.git/commitdiff
Added a communication error system-message that is written to the client when the...
authorMarc Englund <marc.englund@itmill.com>
Fri, 23 Jan 2009 09:48:33 +0000 (09:48 +0000)
committerMarc Englund <marc.englund@itmill.com>
Fri, 23 Jan 2009 09:48:33 +0000 (09:48 +0000)
svn changeset:6624/svn branch:trunk

src/com/itmill/toolkit/Application.java
src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java
src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java

index fa4f5e9a9d4c68119a6a650d25b5088b97bbad68..866a9ced51a19d0b3ad19c4b209414391acbefe1 100644 (file)
@@ -1195,6 +1195,11 @@ public abstract class Application implements URIHandler, Terminal.ErrorListener
         protected String sessionExpiredCaption = "Session Expired";
         protected String sessionExpiredMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
 
+        protected String communicationErrorURL = null;
+        protected boolean communicationErrorNotificationEnabled = true;
+        protected String communicationErrorCaption = "Communication problem";
+        protected String communicationErrorMessage = "Take note of any unsaved data, and <u>click here</u> to continue.";
+
         protected String internalErrorURL = null;
         protected boolean internalErrorNotificationEnabled = true;
         protected String internalErrorCaption = "Internal Error";
@@ -1242,6 +1247,36 @@ public abstract class Application implements URIHandler, Terminal.ErrorListener
                     : null);
         }
 
+        /**
+         * @return the URL to load on null for restart
+         */
+        public String getCommunicationErrorURL() {
+            return communicationErrorURL;
+        }
+
+        /**
+         * @return true = notification enabled, false = notification disabled
+         */
+        public boolean isCommunicationErrorNotificationEnabled() {
+            return communicationErrorNotificationEnabled;
+        }
+
+        /**
+         * @return the notification caption, or null for no caption
+         */
+        public String getCommunicationErrorCaption() {
+            return (communicationErrorNotificationEnabled ? communicationErrorCaption
+                    : null);
+        }
+
+        /**
+         * @return the notification message, or null for no message
+         */
+        public String getCommunicationErrorMessage() {
+            return (communicationErrorNotificationEnabled ? communicationErrorMessage
+                    : null);
+        }
+
         /**
          * @return the URL to load on null for restart
          */
@@ -1313,26 +1348,26 @@ public abstract class Application implements URIHandler, Terminal.ErrorListener
      * </p>
      * <p>
      * The default behavior is to show a notification, and restart the
-     * application the the user clicks the message. <br/>
-     * Instead of restarting the application, you can set a specific URL that
-     * the user is taken to.<br/>
-     * Setting both caption and message to null will restart the application (or
-     * go to the specified URL) without displaying a notification.
-     * set*NotificationEnabled(false) will achieve the same thing.
+     * application the the user clicks the message. <br/> Instead of restarting
+     * the application, you can set a specific URL that the user is taken
+     * to.<br/> Setting both caption and message to null will restart the
+     * application (or go to the specified URL) without displaying a
+     * notification. set*NotificationEnabled(false) will achieve the same thing.
      * </p>
      * <p>
      * The situations are:
      * <li>Session expired: the user session has expired, usually due to
      * inactivity.</li>
+     * <li>Communication error: the client failed to contact the server, or the
+     * server returned and invalid response.</li>
      * <li>Internal error: unhandled critical server error (e.g out of memory,
      * database crash)
      * <li>Out of sync: the client is not in sync with the server. E.g the user
-     * opens two windows showing the same application, and makes changes in one
-     * of the windows - the other window is no longer in sync, and (for
-     * instance) pressing a button that is no longer present in the UI will
-     * cause a out-of-sync -situation. You might want to disable the
-     * notification if silently ignoring a action (e.g button press) is not a
-     * problem in your application.
+     * opens two windows showing the same application, but the application does
+     * not support this and uses the same Window instance. When the user makes
+     * changes in one of the windows - the other window is no longer in sync,
+     * and (for instance) pressing a button that is no longer present in the UI
+     * will cause a out-of-sync -situation.
      * </p>
      */
 
index 3fe4015b9d561de93e8f47e5d46b6fe3875aacbc..919ab0807c0149d6db348f21515fae1e81ef39b9 100644 (file)
@@ -14,6 +14,9 @@ public class ApplicationConfiguration {
     private String appUri;
     private JavaScriptObject versionInfo;
     private String windowName;
+    private String communicationErrorCaption;
+    private String communicationErrorMessage;
+    private String communicationErrorUrl;
 
     private static ArrayList<ApplicationConnection> unstartedApplications = new ArrayList<ApplicationConnection>();
     private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>();
@@ -50,6 +53,18 @@ public class ApplicationConfiguration {
         return versionInfo;
     }
 
+    public String getCommunicationErrorCaption() {
+        return communicationErrorCaption;
+    }
+
+    public String getCommunicationErrorMessage() {
+        return communicationErrorMessage;
+    }
+
+    public String getCommunicationErrorUrl() {
+        return communicationErrorUrl;
+    }
+
     private native void loadFromDOM()
     /*-{
 
@@ -69,6 +84,11 @@ public class ApplicationConfiguration {
             if(jsobj.versionInfo) {
                 this.@com.itmill.toolkit.terminal.gwt.client.ApplicationConfiguration::versionInfo = jsobj.versionInfo;
             }
+            if(jsobj.comErrMsg) {
+                this.@com.itmill.toolkit.terminal.gwt.client.ApplicationConfiguration::communicationErrorCaption = jsobj.comErrMsg.caption;
+                this.@com.itmill.toolkit.terminal.gwt.client.ApplicationConfiguration::communicationErrorMessage = jsobj.comErrMsg.message;
+                this.@com.itmill.toolkit.terminal.gwt.client.ApplicationConfiguration::communicationErrorUrl = jsobj.comErrMsg.url;
+            }
         
         } else {
             $wnd.alert("Toolkit app failed to initialize: " + this.id);
index e9f4f1597b8707fab097024a6499e4a32dcb1d82..d8dd3a589569f5dc96dbd2fe5dfec0014edacfe5 100755 (executable)
@@ -328,12 +328,13 @@ public class ApplicationConnection {
         if (!forceSync) {
             final RequestBuilder rb = new RequestBuilder(RequestBuilder.POST,
                     uri);
+            // TODO enable timeout
+            // rb.setTimeoutMillis(timeoutMillis);
             rb.setHeader("Content-Type", "text/plain;charset=utf-8");
             try {
                 rb.sendRequest(requestData, new RequestCallback() {
                     public void onError(Request request, Throwable exception) {
-                        // TODO Better reporting to user
-                        console.error("Got error");
+                        showCommunicationError(exception.getMessage());
                         endRequest();
                         if (!applicationRunning) {
                             // start failed, let's try to start the next app
@@ -343,6 +344,16 @@ public class ApplicationConnection {
 
                     public void onResponseReceived(Request request,
                             Response response) {
+                        console.log("Server visit took "
+                                + String.valueOf((new Date()).getTime()
+                                        - requestStartTime.getTime()) + "ms");
+
+                        switch (response.getStatusCode()) {
+                        case 0:
+                            showCommunicationError("Invalid status code 0 (server down?)");
+                            return;
+                            // TODO could add more cases
+                        }
                         if ("init".equals(uidl_security_key)) {
                             // Read security key
                             String key = response
@@ -351,9 +362,6 @@ public class ApplicationConnection {
                                 uidl_security_key = key;
                             }
                         }
-                        console.log("Server visit took "
-                                + String.valueOf((new Date()).getTime()
-                                        - requestStartTime.getTime()) + "ms");
                         if (applicationRunning) {
                             handleReceivedJSONMessage(response);
                         } else {
@@ -405,6 +413,30 @@ public class ApplicationConnection {
         }
     }
 
+    /**
+     * Shows the communication error notification. The 'details' only go to the
+     * console for now.
+     * 
+     * @param details
+     *            Optional details for debugging.
+     */
+    private void showCommunicationError(String details) {
+        console.error("Communication error: " + details);
+        String html = "";
+        if (configuration.getCommunicationErrorCaption() != null) {
+            html += "<h1>" + configuration.getCommunicationErrorCaption()
+                    + "</h1>";
+        }
+        if (configuration.getCommunicationErrorMessage() != null) {
+            html += "<p>" + configuration.getCommunicationErrorMessage()
+                    + "</p>";
+        }
+        INotification n = new INotification(1000 * 60 * 45);
+        n.addEventListener(new NotificationRedirect(configuration
+                .getCommunicationErrorUrl()));
+        n.show(html, INotification.CENTERED_TOP, INotification.STYLE_SYSTEM);
+    }
+
     private native void syncSendForce(JavaScriptObject xmlHttpRequest,
             String uri, String requestData)
     /*-{
@@ -551,7 +583,7 @@ public class ApplicationConnection {
             json = JSONParser.parse(jsonText);
         } catch (final com.google.gwt.json.client.JSONException e) {
             endRequest();
-            console.log(e.getMessage() + " - Original JSON-text:");
+            showCommunicationError(e.getMessage() + " - Original JSON-text:");
             console.log(jsonText);
             return;
         }
index d442b1ed17226b1f204bf719129efa54be18a4c8..471ef2877e94ea0dd3bd051752ebc592b7359a2e 100644 (file)
@@ -784,7 +784,8 @@ public class ApplicationServlet extends HttpServlet {
      */
     private void writeAjaxPage(HttpServletRequest request,
             HttpServletResponse response, Window window, String themeName,
-            Application application) throws IOException, MalformedURLException {
+            Application application) throws IOException, MalformedURLException,
+            ServletException {
 
         // e.g portlets only want a html fragment
         boolean fragment = (request.getAttribute(REQUEST_FRAGMENT) != null);
@@ -885,6 +886,15 @@ public class ApplicationServlet extends HttpServlet {
         // but indicates that it should not be used in CSS and such:
         appId = appId + appId.hashCode();
 
+        // Get system messages
+        Application.SystemMessages systemMessages = null;
+        try {
+            systemMessages = getSystemMessages();
+        } catch (SystemMessageException e) {
+            // failing to get the system messages is always a problem
+            throw new ServletException("CommunicationError!", e);
+        }
+
         if (isGecko17(request)) {
             // special start page for gecko 1.7 versions. Firefox 1.0 is not
             // supported, but the hack is make it possible to use linux and
@@ -923,7 +933,25 @@ public class ApplicationServlet extends HttpServlet {
             page.write(VERSION);
             page.write("\",applicationVersion:\"");
             page.write(application.getVersion());
-            page.write("\"}");
+            page.write("\"},");
+            if (systemMessages != null) {
+                // Write the CommunicationError -message to client
+                String caption = systemMessages.getCommunicationErrorCaption();
+                if (caption != null) {
+                    caption = "\"" + caption + "\"";
+                }
+                String message = systemMessages.getCommunicationErrorMessage();
+                if (message != null) {
+                    message = "\"" + message + "\"";
+                }
+                String url = systemMessages.getCommunicationErrorURL();
+                if (url != null) {
+                    url = "\"" + url + "\"";
+                }
+                page.write("\"comErrMsg\": {" + "\"caption\":" + caption + ","
+                        + "\"message\" : " + message + "," + "\"url\" : " + url
+                        + "}");
+            }
             page.write("};\n//]]>\n</script>\n");
 
             if (themeName != null) {
@@ -978,7 +1006,26 @@ public class ApplicationServlet extends HttpServlet {
             page.write(VERSION);
             page.write("\",applicationVersion:\"");
             page.write(application.getVersion());
-            page.write("\"}");
+            page.write("\"},");
+            if (systemMessages != null) {
+                // Write the CommunicationError -message to client
+                String caption = systemMessages.getCommunicationErrorCaption();
+                if (caption != null) {
+                    caption = "\"" + caption + "\"";
+                }
+                String message = systemMessages.getCommunicationErrorMessage();
+                if (message != null) {
+                    message = "\"" + message + "\"";
+                }
+                String url = systemMessages.getCommunicationErrorURL();
+                if (url != null) {
+                    url = "\"" + url + "\"";
+                }
+
+                page.write("\"comErrMsg\": {" + "\"caption\":" + caption + ","
+                        + "\"message\" : " + message + "," + "\"url\" : " + url
+                        + "}");
+            }
             page.write("};\n//]]>\n</script>\n");
 
             if (themeName != null) {