From 2ea19f347b9c6aaa920c09b10747b644af4c2c45 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Wed, 17 Jul 2013 15:15:21 +0300 Subject: [PATCH] Make VaadinService.closeInactiveUIs set UI threadlocals (#12186) Also update javadocs for methods called without UI threadlocals Also make sure pending access tasks are run for a UI being closed Change-Id: Ia600207b2d25fc195ee4254da371d420152bf100 --- .../src/com/vaadin/server/VaadinService.java | 17 +++++---- server/src/com/vaadin/ui/UI.java | 36 +++++++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index 1be5bd5c99..f603fbd1e9 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -1136,13 +1136,18 @@ public abstract class VaadinService implements Serializable { * @since 7.0.0 */ private void closeInactiveUIs(VaadinSession session) { - String sessionId = session.getSession().getId(); - for (UI ui : session.getUIs()) { + final String sessionId = session.getSession().getId(); + for (final UI ui : session.getUIs()) { if (!isUIActive(ui) && !ui.isClosing()) { - getLogger().log(Level.FINE, - "Closing inactive UI #{0} in session {1}", - new Object[] { ui.getUIId(), sessionId }); - ui.close(); + ui.accessSynchronously(new Runnable() { + @Override + public void run() { + getLogger().log(Level.FINE, + "Closing inactive UI #{0} in session {1}", + new Object[] { ui.getUIId(), sessionId }); + ui.close(); + } + }); } } } diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 403bb31f63..0746431302 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -438,8 +438,12 @@ public abstract class UI extends AbstractSingleComponentContainer implements * the server that originates from this UI. * {@link VaadinService#findUI(VaadinRequest)} uses this id to find the * route to which the request belongs. + *

+ * This method is not intended to be overridden. If it is overridden, care + * should be taken since this method might be called in situations where + * {@link UI#getCurrent()} does not return this UI. * - * @return + * @return the id of this UI */ public int getUIId() { return uiId; @@ -1014,9 +1018,12 @@ public abstract class UI extends AbstractSingleComponentContainer implements /** * Returns the timestamp of the last received heartbeat for this UI. + *

+ * This method is not intended to be overridden. If it is overridden, care + * should be taken since this method might be called in situations where + * {@link UI#getCurrent()} does not return this UI. * - * @see #heartbeat() - * @see VaadinSession#cleanupInactiveUIs() + * @see VaadinService#closeInactiveUIs(VaadinSession) * * @return The time the last heartbeat request occurred, in milliseconds * since the epoch. @@ -1029,6 +1036,10 @@ public abstract class UI extends AbstractSingleComponentContainer implements * Sets the last heartbeat request timestamp for this UI. Called by the * framework whenever the application receives a valid heartbeat request for * this UI. + *

+ * This method is not intended to be overridden. If it is overridden, care + * should be taken since this method might be called in situations where + * {@link UI#getCurrent()} does not return this UI. * * @param lastHeartbeat * The time the last heartbeat request occurred, in milliseconds @@ -1072,6 +1083,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements if (getPushConnection() != null) { // Push the Rpc to the client. The connection will be closed when // the UI is detached and cleaned up. + + // Can't use UI.push() directly since it checks for a valid session + if (session != null) { + session.getService().runPendingAccessTasks(session); + } getPushConnection().push(); } @@ -1079,6 +1095,10 @@ public abstract class UI extends AbstractSingleComponentContainer implements /** * Returns whether this UI is marked as closed and is to be detached. + *

+ * This method is not intended to be overridden. If it is overridden, care + * should be taken since this method might be called in situations where + * {@link UI#getCurrent()} does not return this UI. * * @see #close() * @@ -1344,6 +1364,13 @@ public abstract class UI extends AbstractSingleComponentContainer implements * Returns the internal push connection object used by this UI. This method * should only be called by the framework. If the returned PushConnection is * not null, it is guaranteed to have {@code isConnected() == true}. + *

+ * This method is not intended to be overridden. If it is overridden, care + * should be taken since this method might be called in situations where + * {@link UI#getCurrent()} does not return this UI. + * + * @return the push connection used by this UI, null if there + * is no active push connection. */ public PushConnection getPushConnection() { assert (pushConnection == null || pushConnection.isConnected()); @@ -1354,6 +1381,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements * Sets the internal push connection object used by this UI. This method * should only be called by the framework. If {@pushConnection} is not null, * its {@code isConnected()} must be true. + * + * @param pushConnection + * the push connection to use for this UI */ public void setPushConnection(PushConnection pushConnection) { // If pushMode is disabled then there should never be a pushConnection -- 2.39.5