From 84b78846fca4a68d11231f00d9d3eff22d7a78f0 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Tue, 19 Nov 2013 18:40:46 +0800 Subject: [PATCH 1/3] 1003502 Exception when using multiple browser tab. IDEMPIERE-1550 --- .../org/adempiere/webui/AdempiereWebUI.java | 142 ++++-------------- .../webui/session/SessionContextListener.java | 77 +++++++++- .../webui/session/SessionManager.java | 34 +---- 3 files changed, 106 insertions(+), 147 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java index 3fd0ecc6e8..02578ce7a2 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java @@ -18,8 +18,6 @@ package org.adempiere.webui; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -53,23 +51,15 @@ import org.zkforge.keylistener.Keylistener; import org.zkoss.web.Attributes; import org.zkoss.web.servlet.Servlets; import org.zkoss.zk.au.out.AuScript; -import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.Session; -import org.zkoss.zk.ui.UiException; import org.zkoss.zk.ui.event.ClientInfoEvent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; -import org.zkoss.zk.ui.impl.ExecutionCarryOver; import org.zkoss.zk.ui.sys.DesktopCache; -import org.zkoss.zk.ui.sys.DesktopCtrl; -import org.zkoss.zk.ui.sys.ExecutionCtrl; -import org.zkoss.zk.ui.sys.ExecutionsCtrl; import org.zkoss.zk.ui.sys.SessionCtrl; -import org.zkoss.zk.ui.sys.Visualizer; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Window; @@ -100,8 +90,6 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb private WLogin loginDesktop; - private IDesktop appDesktop; - private ClientInfo clientInfo = new ClientInfo(); private String langSession; @@ -239,107 +227,15 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb keyListener.setCtrlKeys("@a@c@d@e@f@h@n@o@p@r@s@t@z@x@#left@#right@#up@#down@#home@#end#enter^u@u"); keyListener.setAutoBlur(false); - @SuppressWarnings("unchecked") - WeakReference desktopRef = (WeakReference) currSess.getAttribute(APPLICATION_DESKTOP_KEY); - IDesktop d = desktopRef != null ? desktopRef.get() : null; - if (d != null && d instanceof IDesktop) - { - @SuppressWarnings("unchecked") - WeakReference ecoRef = (WeakReference) currSess.getAttribute(EXECUTION_CARRYOVER_SESSION_KEY);; - ExecutionCarryOver eco = ecoRef != null ? ecoRef.get() : null; - if (eco != null) { - //try restore - try { - appDesktop = (IDesktop) d; - - ExecutionCarryOver current = new ExecutionCarryOver(this.getPage().getDesktop()); - ExecutionCtrl ctrl = ExecutionsCtrl.getCurrentCtrl(); - Visualizer vi = ctrl.getVisualizer(); - eco.carryOver(); - Collection rootComponents = new ArrayList(); - try { - ctrl = ExecutionsCtrl.getCurrentCtrl(); - ((DesktopCtrl)Executions.getCurrent().getDesktop()).setVisualizer(vi); - - //detach root component from old page - Page page = appDesktop.getComponent().getPage(); - if (page.getDesktop() != null) { - Collection collection = page.getRoots(); - for(Component comp : collection) { - try { - comp.detach(); - if (!(comp instanceof Keylistener) && !(comp instanceof AdempiereWebUI)) { - rootComponents.add(comp); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - appDesktop.getComponent().detach(); - - DesktopCache desktopCache = ((SessionCtrl)currSess).getDesktopCache(); - if (desktopCache != null) - desktopCache.removeDesktop(Executions.getCurrent().getDesktop()); - } else { - appDesktop = null; - } - } catch (Exception e) { - e.printStackTrace(); - appDesktop = null; - } finally { - eco.cleanup(); - current.carryOver(); - } - - if (appDesktop != null) { - //re-attach root components - for (Component component : rootComponents) { - try { - component.setPage(this.getPage()); - } catch (UiException e) { - // e.printStackTrace(); - // an exception is thrown here when refreshing the page, it seems is harmless to catch and ignore it - // i.e.: org.zkoss.zk.ui.UiException: Not unique in the ID space of [Page z_kg_0]: zk_comp_2 - } - } - appDesktop.setPage(this.getPage()); - Clients.response(new AuScript("$('.slimScroll .z-anchorlayout-body').slimScroll({height: '100%',railVisible: true, alwaysVisible: false});")); - currSess.setAttribute(EXECUTION_CARRYOVER_SESSION_KEY, new WeakReference(current)); - } - - currSess.setAttribute(ZK_DESKTOP_SESSION_KEY, new WeakReference(this.getPage().getDesktop())); - ctx.put(ZK_DESKTOP_SESSION_KEY, new WeakReference(this.getPage().getDesktop())); - ClientInfo sessionClientInfo = (ClientInfo) currSess.getAttribute(CLIENT_INFO); - if (sessionClientInfo != null) { - clientInfo = sessionClientInfo; - } - } catch (Throwable t) { - //restore fail - t.printStackTrace(); - appDesktop = null; - Collection roots = this.getPage().getRoots(); - for(Component comp : roots) { - if (!(comp instanceof Keylistener) && !(comp instanceof AdempiereWebUI)) { - comp.detach(); - } - } - } - - } - } - - if (appDesktop == null) - { - //create new desktop - createDesktop(); - appDesktop.setClientInfo(clientInfo); - appDesktop.createPart(this.getPage()); - currSess.setAttribute(APPLICATION_DESKTOP_KEY, new WeakReference(appDesktop)); - ExecutionCarryOver eco = new ExecutionCarryOver(this.getPage().getDesktop()); - currSess.setAttribute(EXECUTION_CARRYOVER_SESSION_KEY, new WeakReference(eco)); - currSess.setAttribute(ZK_DESKTOP_SESSION_KEY, new WeakReference(this.getPage().getDesktop())); - ctx.put(ZK_DESKTOP_SESSION_KEY, new WeakReference(this.getPage().getDesktop())); - } + //create new desktop + IDesktop appDesktop = createDesktop(); + appDesktop.setClientInfo(clientInfo); + appDesktop.createPart(this.getPage()); + ctx.put(ZK_DESKTOP_SESSION_KEY, new WeakReference(this.getPage().getDesktop())); + this.getPage().getDesktop().setAttribute(APPLICATION_DESKTOP_KEY, new WeakReference(appDesktop)); + + //track browser tab per session + SessionContextListener.addDesktopId(mSession.getAD_Session_ID(), getPage().getDesktop().getId()); //ensure server push is on if (!this.getPage().getDesktop().isServerPushEnabled()) @@ -377,9 +273,9 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb return keyListener; } - private void createDesktop() + private IDesktop createDesktop() { - appDesktop = null; + IDesktop appDesktop = null; String className = MSysConfig.getValue(MSysConfig.ZK_DESKTOP_CLASS); if ( className != null && className.trim().length() > 0) { @@ -396,6 +292,8 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb //fallback to default if (appDesktop == null) appDesktop = new DefaultDesktop(); + + return appDesktop; } /* (non-Javadoc) @@ -434,6 +332,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb } //stop background thread + IDesktop appDesktop = getAppDeskop(); if (appDesktop != null) appDesktop.logout(); @@ -454,6 +353,18 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb */ public IDesktop getAppDeskop() { + Desktop desktop = Executions.getCurrent() != null ? Executions.getCurrent().getDesktop() : null; + IDesktop appDesktop = null; + if (desktop != null) + { + @SuppressWarnings("unchecked") + WeakReference ref = (WeakReference) desktop.getAttribute(APPLICATION_DESKTOP_KEY); + if (ref != null) + { + appDesktop = ref.get(); + } + } + return appDesktop; } @@ -471,6 +382,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb clientInfo.desktopYOffset = c.getDesktopYOffset(); clientInfo.orientation = c.getOrientation(); clientInfo.timeZone = c.getTimeZone(); + IDesktop appDesktop = getAppDeskop(); if (appDesktop != null) appDesktop.setClientInfo(clientInfo); String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest()); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java index a733c4d078..920e10f7d5 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java @@ -17,6 +17,9 @@ package org.adempiere.webui.session; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Properties; @@ -24,6 +27,7 @@ import javax.servlet.http.HttpSession; import org.adempiere.util.ServerContext; import org.adempiere.util.ServerContextURLHandler; +import org.adempiere.webui.AdempiereWebUI; import org.compiere.model.MSession; import org.compiere.util.Env; import org.zkoss.util.Locales; @@ -37,8 +41,10 @@ import org.zkoss.zk.ui.event.EventThreadCleanup; import org.zkoss.zk.ui.event.EventThreadInit; import org.zkoss.zk.ui.event.EventThreadResume; import org.zkoss.zk.ui.event.EventThreadSuspend; +import org.zkoss.zk.ui.sys.DesktopCache; import org.zkoss.zk.ui.sys.DesktopCtrl; import org.zkoss.zk.ui.sys.ServerPush; +import org.zkoss.zk.ui.sys.SessionCtrl; import org.zkoss.zk.ui.util.DesktopCleanup; import org.zkoss.zk.ui.util.DesktopInit; import org.zkoss.zk.ui.util.ExecutionCleanup; @@ -120,6 +126,8 @@ public class SessionContextListener implements ExecutionInit, //set locale Locales.setThreadLocal(Env.getLanguage(ServerContext.getCurrentInstance()).getLocale()); } + Properties ctx = ServerContext.getCurrentInstance(); + ctx.put(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY, new WeakReference(exec.getDesktop())); } } @@ -336,10 +344,12 @@ public class SessionContextListener implements ExecutionInit, } int AD_Session_ID = Env.getContextAsInt(Env.getCtx(), "#AD_Session_ID"); if (AD_Session_ID > 0) { - String key = "ad_session."+AD_Session_ID+".desktop"; - String dtid = (String) Env.getCtx().get(key); - if (dtid != null) { - if (!dtid.equals(desktop.getId())) { + String key = getSessionDesktopListKey(AD_Session_ID); + @SuppressWarnings("unchecked") + List list = (List) Env.getCtx().get(key); + if (list != null) { + list.remove(desktop.getId()); + if (!isEmpty(list, desktop.getSession())) { return; } else { Env.getCtx().remove(key); @@ -356,6 +366,38 @@ public class SessionContextListener implements ExecutionInit, } } + private boolean isEmpty(List list, Session session) { + if (list.isEmpty()) + return true; + + if (session == null) + return false; + + DesktopCache desktopCache = ((SessionCtrl)session).getDesktopCache(); + if (desktopCache == null) + return false; + + int count = 0; + for(String dtid : list) { + Desktop desktop = desktopCache.getDesktopIfAny(dtid); + if (desktop == null) continue; + if (desktop.getFirstPage() == null) continue; + Collection roots = desktop.getFirstPage().getRoots(); + if (roots == null || roots.isEmpty()) continue; + boolean found = false; + for (Component root : roots) { + if (root instanceof AdempiereWebUI) { + found = true; + break; + } + } + if (!found) continue; + count++; + } + + return count == 0; + } + @Override public void init(Desktop desktop, Object request) throws Exception { if(Executions.getCurrent()==null) @@ -371,7 +413,32 @@ public class SessionContextListener implements ExecutionInit, mSession.setProcessed(false); mSession.saveEx(); } - Env.getCtx().put("ad_session."+mSession.getAD_Session_ID()+".desktop", desktop.getId()); + addDesktopId(mSession.getAD_Session_ID(), desktop.getId()); + } + } + + public static void addDesktopId(int AD_Session_ID, String dtid) + { + String key = getSessionDesktopListKey(AD_Session_ID); + @SuppressWarnings("unchecked") + List list = (List) Env.getCtx().get(key); + if (list == null) { + list = new ArrayList(); + Env.getCtx().put(key, list); + } + if (!list.contains(dtid)) + { + list.add(dtid); } } + + /** + * @param AD_Session_ID + * @return desktop list key + */ + public static String getSessionDesktopListKey(int AD_Session_ID) + { + String key = "ad_session."+AD_Session_ID+".desktop"; + return key; + } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionManager.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionManager.java index adccb34ef7..6d04638d2e 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionManager.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionManager.java @@ -20,15 +20,12 @@ package org.adempiere.webui.session; import java.lang.ref.WeakReference; import java.util.Properties; -import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.IWebClient; +import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.desktop.IDesktop; import org.compiere.model.MUser; import org.compiere.util.Env; import org.zkoss.zk.ui.Desktop; -import org.zkoss.zk.ui.Execution; -import org.zkoss.zk.ui.Executions; -import org.zkoss.zk.ui.Session; /** * @@ -51,28 +48,11 @@ public class SessionManager && !"".equals(adClientId) && !"".equals(adOrgId)); } - private static Session getSession() - { - Execution execution = Executions.getCurrent(); - Desktop desktop = null; - if (execution != null) - { - desktop = execution.getDesktop(); - } - else - { - @SuppressWarnings("unchecked") - WeakReference ref = (WeakReference) Env.getCtx().get(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY); - desktop = ref != null ? ref.get() : null; - } - return desktop != null ? desktop.getSession() : null; - } - public static void setSessionApplication(IWebClient app) { - Session session = getSession(); - if (session != null) - session.setAttribute(SESSION_APPLICATION, new WeakReference(app)); + Desktop desktop = AEnv.getDesktop(); + if (desktop != null) + desktop.setAttribute(SESSION_APPLICATION, new WeakReference(app)); } public static IDesktop getAppDesktop() @@ -83,12 +63,12 @@ public class SessionManager public static IWebClient getSessionApplication() { - Session session = getSession(); + Desktop desktop = AEnv.getDesktop(); IWebClient app = null; - if (session != null) + if (desktop != null) { @SuppressWarnings("unchecked") - WeakReference wref = (WeakReference) session.getAttribute(SESSION_APPLICATION); + WeakReference wref = (WeakReference) desktop.getAttribute(SESSION_APPLICATION); app = wref != null ? wref.get() : null; } return app; From 439e3e453a2020832a446ff9b5e9e11c4dee3078 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Tue, 19 Nov 2013 23:54:37 +0800 Subject: [PATCH 2/3] 1003454 Large reports slow, throwing errors. Reduce memory usage for generation of html output. --- .../src/org/compiere/print/ReportEngine.java | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/print/ReportEngine.java b/org.adempiere.base/src/org/compiere/print/ReportEngine.java index f132fe5b48..5b24b3d986 100644 --- a/org.adempiere.base/src/org/compiere/print/ReportEngine.java +++ b/org.adempiere.base/src/org/compiere/print/ReportEngine.java @@ -560,11 +560,35 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) if (cssPrefix != null) table.setClass(cssPrefix + "-table"); // + // + table.setNeedClosingTag(false); + PrintWriter w = new PrintWriter(writer); + if (onlyTable) + table.output(w); + else + { + XhtmlDocument doc = new XhtmlDocument(); + doc.getHtml().setNeedClosingTag(false); + doc.getBody().setNeedClosingTag(false); + doc.appendBody(table); + if (extension != null && extension.getStyleURL() != null) + { + link l = new link(extension.getStyleURL(), "stylesheet", "text/css"); + doc.appendHead(l); + } + if (extension != null && extension.getScriptURL() != null) + { + script jslink = new script(); + jslink.setLanguage("javascript"); + jslink.setSrc(extension.getScriptURL()); + doc.appendHead(jslink); + } + doc.output(w); + } // for all rows (-1 = header row) for (int row = -1; row < m_printData.getRowCount(); row++) { tr tr = new tr(); - table.addElement(tr); if (row != -1) { m_printData.setRowIndex(row); @@ -693,29 +717,15 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) } } // printed } // for all columns + tr.output(w); } // for all rows - // - PrintWriter w = new PrintWriter(writer); - if (onlyTable) - table.output(w); - else + w.println(); + w.println(""); + if (!onlyTable) { - XhtmlDocument doc = new XhtmlDocument(); - doc.appendBody(table); - if (extension != null && extension.getStyleURL() != null) - { - link l = new link(extension.getStyleURL(), "stylesheet", "text/css"); - doc.appendHead(l); - } - if (extension != null && extension.getScriptURL() != null) - { - script jslink = new script(); - jslink.setLanguage("javascript"); - jslink.setSrc(extension.getScriptURL()); - doc.appendHead(jslink); - } - doc.output(w); + w.println(""); + w.println(""); } w.flush(); w.close(); From cc30063c8482596c0f370a248066a6a3fc64ad05 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Wed, 20 Nov 2013 18:20:09 +0800 Subject: [PATCH 3/3] 1003481 Context Help Broken for Import File Loader window when accessed via Zoom Across. --- .../WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java index 4a9c46cb29..c19d8a0628 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/TabbedDesktop.java @@ -27,6 +27,7 @@ import org.adempiere.webui.component.Tabpanel; import org.adempiere.webui.component.Window; import org.adempiere.webui.factory.InfoManager; import org.adempiere.webui.panel.ADForm; +import org.adempiere.webui.panel.IHelpContext; import org.adempiere.webui.panel.InfoPanel; import org.adempiere.webui.part.WindowContainer; import org.adempiere.webui.window.FDialog; @@ -293,6 +294,8 @@ public abstract class TabbedDesktop extends AbstractDesktop { windowContainer.insertAfter(windowContainer.getSelectedTab(), tabPanel, title, true, true); else windowContainer.addWindow(tabPanel, title, true); + if (window instanceof IHelpContext) + Events.sendEvent(new Event(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT, window)); } /**