summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2012-08-22 13:59:26 +0300
committerJohannes Dahlström <johannesd@vaadin.com>2012-08-22 14:30:53 +0300
commit7a8fd7b5c0223ef6820b4e5cdbe1c05578b17d4a (patch)
tree1a575d46b1d6ab45a19892f11ed5808f3728dd48 /server
parent20b403146e96b7201583e9244bc90c5a1c2191f1 (diff)
downloadvaadin-framework-7a8fd7b5c0223ef6820b4e5cdbe1c05578b17d4a.tar.gz
vaadin-framework-7a8fd7b5c0223ef6820b4e5cdbe1c05578b17d4a.zip
Sending and receiving heartbeat requests (#9265)
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java15
-rw-r--r--server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java15
-rw-r--r--server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java38
-rw-r--r--server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java7
4 files changed, 71 insertions, 4 deletions
diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
index bd39504237..dea42b6b69 100644
--- a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ b/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
@@ -340,7 +340,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
}
protected enum RequestType {
- FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN, BROWSER_DETAILS, CONNECTOR_RESOURCE;
+ FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN, BROWSER_DETAILS, CONNECTOR_RESOURCE, HEARTBEAT;
}
protected RequestType getRequestType(WrappedPortletRequest wrappedRequest) {
@@ -361,6 +361,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
} else if (ServletPortletHelper
.isApplicationResourceRequest(wrappedRequest)) {
return RequestType.APPLICATION_RESOURCE;
+ } else if (ServletPortletHelper.isHeartbeatRequest(wrappedRequest)) {
+ return RequestType.HEARTBEAT;
} else if (isDummyRequest(resourceRequest)) {
return RequestType.DUMMY;
} else {
@@ -431,6 +433,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
Application application = null;
boolean transactionStarted = false;
boolean requestStarted = false;
+ boolean applicationRunning = false;
try {
// TODO What about PARAM_UNLOADBURST & redirectToApplication??
@@ -459,6 +462,10 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
applicationManager.serveConnectorResource(wrappedRequest,
wrappedResponse);
return;
+ } else if (requestType == RequestType.HEARTBEAT) {
+ applicationManager.handleHeartbeatRequest(wrappedRequest,
+ wrappedResponse, application);
+ return;
}
/* Update browser information from request */
@@ -477,6 +484,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
/* Start the newly created application */
startApplication(request, application, applicationContext);
+ applicationRunning = true;
/*
* Transaction starts. Call transaction listeners. Transaction
@@ -585,6 +593,11 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
handleServiceException(wrappedRequest, wrappedResponse,
application, e);
} finally {
+
+ if (applicationRunning) {
+ application.closeInactiveRoots();
+ }
+
// Notifies transaction end
try {
if (transactionStarted) {
diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index 062ba6cdf7..0fc8bc09a0 100644
--- a/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/server/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -248,6 +248,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
Application application = null;
boolean transactionStarted = false;
boolean requestStarted = false;
+ boolean applicationRunning = false;
try {
// If a duplicate "close application" URL is received for an
@@ -287,6 +288,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
if (requestType == RequestType.CONNECTOR_RESOURCE) {
applicationManager.serveConnectorResource(request, response);
return;
+ } else if (requestType == RequestType.HEARTBEAT) {
+ applicationManager.handleHeartbeatRequest(request, response,
+ application);
+ return;
}
/* Update browser information from the request */
@@ -304,6 +309,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
// Start the application if it's newly created
startApplication(request, application, webApplicationContext);
+ applicationRunning = true;
/*
* Transaction starts. Call transaction listeners. Transaction end
@@ -354,6 +360,11 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
} catch (final Throwable e) {
handleServiceException(request, response, application, e);
} finally {
+
+ if (applicationRunning) {
+ application.closeInactiveRoots();
+ }
+
// Notifies transaction end
try {
if (transactionStarted) {
@@ -1121,7 +1132,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
}
protected enum RequestType {
- FILE_UPLOAD, BROWSER_DETAILS, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE, CONNECTOR_RESOURCE;
+ FILE_UPLOAD, BROWSER_DETAILS, UIDL, OTHER, STATIC_FILE, APPLICATION_RESOURCE, CONNECTOR_RESOURCE, HEARTBEAT;
}
protected RequestType getRequestType(WrappedHttpServletRequest request) {
@@ -1137,6 +1148,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
return RequestType.STATIC_FILE;
} else if (ServletPortletHelper.isApplicationResourceRequest(request)) {
return RequestType.APPLICATION_RESOURCE;
+ } else if (ServletPortletHelper.isHeartbeatRequest(request)) {
+ return RequestType.HEARTBEAT;
}
return RequestType.OTHER;
diff --git a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index 00e65382cd..3099903454 100644
--- a/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/server/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -87,6 +87,7 @@ import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.VariableOwner;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedResponse;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.server.BootstrapHandler.BootstrapContext;
import com.vaadin.terminal.gwt.server.ComponentSizeValidator.InvalidLayout;
import com.vaadin.terminal.gwt.server.RpcManager.RpcInvocationException;
@@ -102,7 +103,7 @@ import com.vaadin.ui.Window;
* This is a common base class for the server-side implementations of the
* communication system between the client code (compiled with GWT into
* JavaScript) and the server side components. Its client side counterpart is
- * {@link ApplicationConstants}.
+ * {@link ApplicationConnection}.
*
* TODO Document better!
*/
@@ -577,6 +578,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
return;
}
+ // Keep the root alive
+ root.heartbeat();
+
// Change all variables based on request parameters
if (!handleVariables(request, response, callback, application, root)) {
@@ -2634,6 +2638,38 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
+ /**
+ * Handles a heartbeat request. Heartbeat requests are periodically sent by
+ * the client-side to inform the server that the root sending the heartbeat
+ * is still alive (the browser window is open, the connection is up) even
+ * when there are no UIDL requests for a prolonged period of time. Roots
+ * that do not receive either heartbeat or UIDL requests are eventually
+ * removed from the application and garbage collected.
+ *
+ * @param request
+ * @param response
+ * @param application
+ * @throws IOException
+ */
+ public void handleHeartbeatRequest(WrappedRequest request,
+ WrappedResponse response, Application application)
+ throws IOException {
+ Root root = null;
+ try {
+ int rootId = Integer.parseInt(request
+ .getParameter(ApplicationConstants.ROOT_ID_PARAMETER));
+ root = application.getRootById(rootId);
+ } catch (NumberFormatException nfe) {
+ // null-check below handles this as well
+ }
+ if (root != null) {
+ root.heartbeat();
+ } else {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
+ "Root not found");
+ }
+ }
+
public StreamVariable getStreamVariable(String connectorId,
String variableName) {
Map<String, StreamVariable> map = pidToNameToStreamVariable
diff --git a/server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java b/server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java
index 200f9a9103..6911101920 100644
--- a/server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java
+++ b/server/src/com/vaadin/terminal/gwt/server/ServletPortletHelper.java
@@ -9,7 +9,7 @@ import com.vaadin.terminal.WrappedRequest;
import com.vaadin.ui.Root;
/*
- * Copyright 2011 Vaadin Ltd.
+ * Copyright 2011 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -129,4 +129,9 @@ class ServletPortletHelper implements Serializable {
return hasPathPrefix(request, ApplicationConstants.APP_REQUEST_PATH);
}
+ public static boolean isHeartbeatRequest(WrappedRequest request) {
+ return hasPathPrefix(request,
+ ApplicationConstants.HEARTBEAT_REQUEST_PATH);
+ }
+
}