diff options
author | Marc Englund <marc.englund@itmill.com> | 2009-01-23 09:48:33 +0000 |
---|---|---|
committer | Marc Englund <marc.englund@itmill.com> | 2009-01-23 09:48:33 +0000 |
commit | c60ca65f8f941fe3d80317747f5dc4f41c0e70d6 (patch) | |
tree | 441a360960bf623c8940341909c0fd68e3b34d69 /src/com | |
parent | 58507aa78d79200fa9b858395daf280e00c5e86d (diff) | |
download | vaadin-framework-c60ca65f8f941fe3d80317747f5dc4f41c0e70d6.tar.gz vaadin-framework-c60ca65f8f941fe3d80317747f5dc4f41c0e70d6.zip |
Added a communication error system-message that is written to the client when the initial page is rendered. If any UIDL request fails, the message is shown. Fixes [2485]
svn changeset:6624/svn branch:trunk
Diffstat (limited to 'src/com')
4 files changed, 155 insertions, 21 deletions
diff --git a/src/com/itmill/toolkit/Application.java b/src/com/itmill/toolkit/Application.java index fa4f5e9a9d..866a9ced51 100644 --- a/src/com/itmill/toolkit/Application.java +++ b/src/com/itmill/toolkit/Application.java @@ -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"; @@ -1245,6 +1250,36 @@ public abstract class Application implements URIHandler, Terminal.ErrorListener /** * @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 + */ public String getInternalErrorURL() { return internalErrorURL; } @@ -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> */ diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java index 3fe4015b9d..919ab0807c 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConfiguration.java @@ -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); diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index e9f4f1597b..d8dd3a5895 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -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; } diff --git a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java index d442b1ed17..471ef2877e 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java @@ -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) { |