From 8d75aa84ee809710e10b74bdc8c282657a6a7128 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Wed, 31 Mar 2010 04:04:31 +0000 Subject: [PATCH] server push thread doesn't stop after browser refresh Link to SF Tracker: http://sourceforge.net/support/tracker.php?aid=2979748 --- .../org/adempiere/webui/AdempiereWebUI.java | 18 ++++-- .../webui/dashboard/DashboardRunnable.java | 64 ++++++++++++++++++- .../webui/desktop/DefaultDesktop.java | 10 +++ .../webui/desktop/NavBar2Desktop.java | 10 +++ .../webui/desktop/NavBarDesktop.java | 10 +++ .../webui/util/ServerPushTemplate.java | 17 +++-- 6 files changed, 114 insertions(+), 15 deletions(-) diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java b/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java index 69d4707f89..47da87b6b5 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java @@ -30,6 +30,7 @@ import org.adempiere.webui.component.ZoomCommand; import org.adempiere.webui.desktop.DefaultDesktop; import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.event.TokenEvent; +import org.adempiere.webui.session.SessionContextListener; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.BrowserToken; @@ -91,6 +92,10 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient private static final CLogger logger = CLogger.getCLogger(AdempiereWebUI.class); + public static final String EXECUTION_CARRYOVER_SESSION_KEY = "execution.carryover"; + + public static final String ZK_DESKTOP_SESSION_KEY = "zk.desktop"; + public AdempiereWebUI() { this.addEventListener(Events.ON_CLIENT_INFO, this); @@ -106,7 +111,8 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient Properties ctx = Env.getCtx(); langSession = Env.getContext(ctx, Env.LANGUAGE); SessionManager.setSessionApplication(this); - if (!SessionManager.isUserLoggedIn(ctx)) + Session session = Executions.getCurrent().getDesktop().getSession(); + if (session.getAttribute(SessionContextListener.SESSION_CTX) == null || !SessionManager.isUserLoggedIn(ctx)) { loginDesktop = new WLogin(this); loginDesktop.createPart(this.getPage()); @@ -186,7 +192,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient IDesktop d = (IDesktop) currSess.getAttribute("application.desktop"); if (d != null && d instanceof IDesktop) { - ExecutionCarryOver eco = (ExecutionCarryOver) currSess.getAttribute("execution.carryover"); + ExecutionCarryOver eco = (ExecutionCarryOver) currSess.getAttribute(EXECUTION_CARRYOVER_SESSION_KEY); if (eco != null) { //try restore try { @@ -229,8 +235,10 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient component.setPage(this.getPage()); } appDesktop.setPage(this.getPage()); - currSess.setAttribute("execution.carryover", current); + currSess.setAttribute(EXECUTION_CARRYOVER_SESSION_KEY, current); } + + currSess.setAttribute(ZK_DESKTOP_SESSION_KEY, this.getPage().getDesktop()); } catch (Throwable t) { //restore fail appDesktop = null; @@ -247,7 +255,8 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient appDesktop.createPart(this.getPage()); currSess.setAttribute("application.desktop", appDesktop); ExecutionCarryOver eco = new ExecutionCarryOver(this.getPage().getDesktop()); - currSess.setAttribute("execution.carryover", eco); + currSess.setAttribute(EXECUTION_CARRYOVER_SESSION_KEY, eco); + currSess.setAttribute(ZK_DESKTOP_SESSION_KEY, this.getPage().getDesktop()); } if ("Y".equalsIgnoreCase(Env.getContext(ctx, BrowserToken.REMEMBER_ME)) && MSystem.isZKRememberUserAllowed()) @@ -288,6 +297,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWebClient public void logout() { appDesktop.logout(); + Executions.getCurrent().getDesktop().getSession().getAttributes().clear(); MSession mSession = MSession.get(Env.getCtx(), false); if (mSession != null) { diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java index 5697981e30..64cecfb3f3 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/dashboard/DashboardRunnable.java @@ -18,7 +18,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Properties; +import java.util.logging.Level; +import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.session.ServerContext; import org.adempiere.webui.session.SessionContextListener; @@ -27,6 +29,7 @@ import org.compiere.model.MSysConfig; import org.compiere.util.CLogger; import org.zkoss.util.Locales; import org.zkoss.zk.ui.Desktop; +import org.zkoss.zk.ui.DesktopUnavailableException; /** * @@ -45,7 +48,6 @@ public class DashboardRunnable implements Runnable, Serializable private IDesktop appDesktop; private Locale locale; - @SuppressWarnings("unused") private static final CLogger logger = CLogger.getCLogger(DashboardRunnable.class); private final static String ZK_DASHBOARD_REFRESH_INTERVAL = "ZK_DASHBOARD_REFRESH_INTERVAL"; @@ -63,6 +65,12 @@ public class DashboardRunnable implements Runnable, Serializable locale = Locales.getCurrent(); } + public DashboardRunnable(DashboardRunnable tmp, Desktop desktop, + IDesktop appDesktop) { + this(desktop, appDesktop); + this.dashboardPanels = tmp.dashboardPanels; + } + public void run() { // default Update every one minutes @@ -76,13 +84,65 @@ public class DashboardRunnable implements Runnable, Serializable if (desktop.isAlive()) { Locales.setThreadLocal(locale); - refreshDashboard(); + try { + refreshDashboard(); + } catch (DesktopUnavailableException de) { + killSession(); + break; + } catch (Exception e) { + logger.log(Level.INFO, e.getLocalizedMessage(), (e.getCause() != null ? e.getCause() : e)); + break; + } } else { + killSession(); break; } } } + private void killSession() { + if (desktop.getSession() != null && desktop.getSession().getNativeSession() != null) + { + //differentiate between real destroy and refresh + try + { + Thread.sleep(90000); + } + catch (InterruptedException e) + { + try + { + desktop.getSession().getAttributes().clear(); + desktop.getSession().invalidate(); + } + catch (Exception e1) {} + return; + } + + try + { + Object sessionObj = desktop.getSession().getAttribute(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY); + if (sessionObj != null && sessionObj instanceof Desktop) + { + Desktop sessionDesktop = (Desktop) sessionObj; + + //don't destroy session if it have been attached to another desktop ( refresh will do that ) + if (sessionDesktop == desktop) + { + desktop.getSession().getAttributes().clear(); + desktop.getSession().invalidate(); + } + } + else + { + desktop.getSession().getAttributes().clear(); + desktop.getSession().invalidate(); + } + } + catch (Exception e1) {} + } + } + /** * Refresh dashboard content */ diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java index e0c4fd89ab..9ca7fba771 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java @@ -397,6 +397,16 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria if (this.page != page) { layout.setPage(page); this.page = page; + if (dashboardThread != null && dashboardThread.isAlive()) { + dashboardRunnable.stop(); + dashboardThread.interrupt(); + + DashboardRunnable tmp = dashboardRunnable; + dashboardRunnable = new DashboardRunnable(tmp, layout.getDesktop(), this); + dashboardThread = new Thread(dashboardRunnable, "UpdateInfo"); + dashboardThread.setDaemon(true); + dashboardThread.start(); + } } } diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBar2Desktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBar2Desktop.java index b8cc0a8ede..fc1c4e69ab 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBar2Desktop.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBar2Desktop.java @@ -419,6 +419,16 @@ public class NavBar2Desktop extends TabbedDesktop implements MenuListener, Seria layout.setPage(page); this.page = page; } + if (dashboardThread != null && dashboardThread.isAlive()) { + dashboardRunnable.stop(); + dashboardThread.interrupt(); + + DashboardRunnable tmp = dashboardRunnable; + dashboardRunnable = new DashboardRunnable(tmp, layout.getDesktop(), this); + dashboardThread = new Thread(dashboardRunnable, "UpdateInfo"); + dashboardThread.setDaemon(true); + dashboardThread.start(); + } } /** diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBarDesktop.java b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBarDesktop.java index 93c7bd307b..650f3f8af3 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBarDesktop.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/desktop/NavBarDesktop.java @@ -435,6 +435,16 @@ public class NavBarDesktop extends TabbedDesktop implements MenuListener, Serial layout.setPage(page); this.page = page; } + if (dashboardThread != null && dashboardThread.isAlive()) { + dashboardRunnable.stop(); + dashboardThread.interrupt(); + + DashboardRunnable tmp = dashboardRunnable; + dashboardRunnable = new DashboardRunnable(tmp, layout.getDesktop(), this); + dashboardThread = new Thread(dashboardRunnable, "UpdateInfo"); + dashboardThread.setDaemon(true); + dashboardThread.start(); + } } /** diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/util/ServerPushTemplate.java b/zkwebui/WEB-INF/src/org/adempiere/webui/util/ServerPushTemplate.java index 44807c725a..af63f3270a 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/util/ServerPushTemplate.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/util/ServerPushTemplate.java @@ -13,10 +13,9 @@ *****************************************************************************/ package org.adempiere.webui.util; -import java.util.logging.Level; - -import org.compiere.util.CLogger; +import org.adempiere.exceptions.AdempiereException; import org.zkoss.zk.ui.Desktop; +import org.zkoss.zk.ui.DesktopUnavailableException; import org.zkoss.zk.ui.Executions; /** @@ -29,8 +28,6 @@ public class ServerPushTemplate { private Desktop desktop; - private final static CLogger logger = CLogger.getCLogger(ServerPushTemplate.class); - /** * * @param desktop @@ -49,16 +46,18 @@ public class ServerPushTemplate { try { if (!inUIThread) { - //1 second timeout - if (Executions.activate(desktop, 1000)) { + //half second timeout + if (Executions.activate(desktop, 500)) { desktopActivated = true; } else { - return; + throw new DesktopUnavailableException("Timeout activating desktop."); } } callback.updateUI(); + } catch (DesktopUnavailableException de) { + throw de; } catch (Exception e) { - logger.log(Level.INFO, "Server push error="+e.getLocalizedMessage(), e); + throw new AdempiereException("Failed to update client in server push worker thread.", e); } finally { if (!inUIThread && desktopActivated) { Executions.deactivate(desktop);