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 8d5397bc3d..b157d311a2 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 @@ -103,8 +103,6 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb public static final String EXECUTION_CARRYOVER_SESSION_KEY = "execution.carryover"; - public static final String ZK_DESKTOP_SESSION_KEY = "zk.desktop"; - private static final String CLIENT_INFO = "client.info"; private static boolean eventThreadEnabled = false; @@ -246,7 +244,6 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb 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 diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java index 8426495d63..e412de4a9e 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AEnv.java @@ -34,7 +34,6 @@ import java.util.logging.Level; import javax.servlet.ServletRequest; -import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.component.Window; import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.session.SessionManager; @@ -741,8 +740,7 @@ public final class AEnv if (inUIThread) { return Executions.getCurrent().getDesktop(); } else { - @SuppressWarnings("unchecked") - WeakReference ref = (WeakReference) Env.getCtx().get(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY); + WeakReference ref = DesktopRunnable.getThreadLocalDesktop(); return ref != null ? ref.get() : null; } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/DesktopRunnable.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/DesktopRunnable.java new file mode 100644 index 0000000000..ca1a1a9bf5 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/DesktopRunnable.java @@ -0,0 +1,49 @@ +/** + * + */ +package org.adempiere.webui.apps; + +import java.lang.ref.WeakReference; + +import org.zkoss.zk.ui.Desktop; + +/** + * If your background task need access to desktop, wrap your runnable with this, i.e new DesktopRunnable(yourRunnable, desktop). + * You can then use AEnv.getDesktop() in your runnable to get access to desktop. + * @author hengsin + * + */ +public class DesktopRunnable implements Runnable { + + private Runnable runnable; + private WeakReference desktopWeakRef; + + private static ThreadLocal> threadLocalDesktop = new ThreadLocal>() { + protected WeakReference initialValue() + { + return null; + } + }; + + public DesktopRunnable(Runnable runnable, Desktop desktop) { + this.runnable = runnable; + this.desktopWeakRef = new WeakReference(desktop); + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + threadLocalDesktop.set(desktopWeakRef); + runnable.run(); + } finally { + threadLocalDesktop.remove(); + } + } + + /* package */static WeakReference getThreadLocalDesktop() { + return threadLocalDesktop.get(); + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java index 88c1acb32e..4adf037559 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessDialog.java @@ -6,7 +6,6 @@ import static org.compiere.model.SystemIDs.PROCESS_M_INOUT_GENERATE; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.lang.ref.WeakReference; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -20,8 +19,6 @@ import java.util.logging.Level; import org.adempiere.util.Callback; import org.adempiere.util.ContextRunnable; import org.adempiere.util.IProcessUI; -import org.adempiere.util.ServerContext; -import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.component.Button; import org.adempiere.webui.component.ConfirmPanel; @@ -347,15 +344,8 @@ public class ProcessDialog extends Window implements EventListener, IProc } public void runProcess() { - //prepare context for background thread - Properties context = ServerContext.getCurrentInstance(); - if (context.get(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY) == null) { - Desktop desktop = this.getDesktop(); - context.put(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY, new WeakReference(desktop)); - } - processDialogRunnable = new ProcessDialogRunnable(); - future = Adempiere.getThreadPoolExecutor().submit(processDialogRunnable); + future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(processDialogRunnable, getDesktop())); } private void onComplete() { diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java index 91d671edc1..ddd329e5ba 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/ProcessModalDialog.java @@ -17,7 +17,6 @@ package org.adempiere.webui.apps; import java.io.File; -import java.lang.ref.WeakReference; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -30,8 +29,6 @@ import java.util.logging.Level; import org.adempiere.util.Callback; import org.adempiere.util.ContextRunnable; import org.adempiere.util.IProcessUI; -import org.adempiere.util.ServerContext; -import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.component.Button; import org.adempiere.webui.component.ConfirmPanel; @@ -50,7 +47,6 @@ import org.compiere.util.Env; import org.compiere.util.Msg; import org.zkoss.zk.au.out.AuEcho; import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; @@ -379,15 +375,8 @@ public class ProcessModalDialog extends Window implements EventListener, * internal use, don't call this directly */ public void runProcess() { - //prepare context for background thread - Properties context = ServerContext.getCurrentInstance(); - if (context.get(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY) == null) { - Desktop desktop = this.getDesktop(); - context.put(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY, new WeakReference(desktop)); - } - processDialogRunnable = new ProcessDialogRunnable(); - future = Adempiere.getThreadPoolExecutor().submit(processDialogRunnable); + future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(processDialogRunnable, getDesktop())); } private void hideBusyDialog() { diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java index 85e656ffef..38ed19fc41 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/AbstractDesktop.java @@ -14,6 +14,7 @@ package org.adempiere.webui.desktop; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.adempiere.webui.AdempiereWebUI; @@ -26,6 +27,7 @@ import org.compiere.model.MMenu; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.zkoss.zk.ui.Executions; +import org.zkoss.zk.ui.Session; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zul.Window.Mode; @@ -39,13 +41,10 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop private transient ClientInfo clientInfo; - private List windows = null; - @SuppressWarnings("unused") private static final CLogger logger = CLogger.getCLogger(AbstractDesktop.class); public AbstractDesktop() { - windows = new ArrayList(); } /** @@ -112,6 +111,7 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop * @param win */ public int registerWindow(Object win) { + List windows = getWindows(); int retValue = windows.size(); windows.add(win); return retValue; @@ -121,6 +121,7 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop * @param WindowNo */ public void unregisterWindow(int WindowNo) { + List windows = getWindows(); if (WindowNo < windows.size()) windows.set(WindowNo, null); Env.clearWinContext(WindowNo); @@ -132,6 +133,7 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop * @return Object */ public Object findWindow(int WindowNo) { + List windows = getWindows(); if (WindowNo < windows.size()) return windows.get(WindowNo); else @@ -297,7 +299,14 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop } protected List getWindows(){ - return windows; + Session session = getComponent().getDesktop().getSession(); + @SuppressWarnings("unchecked") + List list = (List) session.getAttribute("windows.list"); + if (list == null) { + list = new ArrayList(); + session.setAttribute("windows.list", list); + } + return Collections.synchronizedList(list); } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java index 7dcc696803..9582947ff8 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DefaultDesktop.java @@ -30,6 +30,7 @@ import org.adempiere.util.ServerContext; import org.adempiere.webui.adwindow.ADWindow; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.BusyDialog; +import org.adempiere.webui.apps.DesktopRunnable; import org.adempiere.webui.apps.ProcessDialog; import org.adempiere.webui.apps.WReport; import org.adempiere.webui.component.Tab; @@ -265,7 +266,7 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria } }; - Adempiere.getThreadPoolExecutor().submit(runnable); + Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(runnable,layout.getDesktop())); ToolBar toolbar = new ToolBar(); windowContainer.getComponent().appendChild(toolbar); 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 b329771882..2a2ca7728c 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,7 +17,6 @@ package org.adempiere.webui.session; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -133,8 +132,6 @@ 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())); } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java index dafb409eed..45325e462e 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/ZkReportViewer.java @@ -21,7 +21,6 @@ import static org.compiere.model.SystemIDs.WINDOW_PRINTFORMAT; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.StringWriter; -import java.lang.ref.WeakReference; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -36,11 +35,10 @@ import javax.servlet.http.HttpServletRequest; import org.adempiere.exceptions.DBException; import org.adempiere.pdf.Document; import org.adempiere.util.ContextRunnable; -import org.adempiere.util.ServerContext; -import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.BusyDialog; +import org.adempiere.webui.apps.DesktopRunnable; import org.adempiere.webui.apps.WReport; import org.adempiere.webui.apps.form.WReportCustomization; import org.adempiere.webui.component.Checkbox; @@ -461,21 +459,14 @@ public class ZkReportViewer extends Window implements EventListener, ITab } private void renderReport() { - //prepare context for background thread - Properties context = ServerContext.getCurrentInstance(); - if (context.get(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY) == null) { - Desktop desktop = this.getDesktop(); - context.put(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY, new WeakReference(desktop)); - } - media = null; Listitem selected = previewType.getSelectedItem(); if (selected == null || "PDF".equals(selected.getValue())) { - future = Adempiere.getThreadPoolExecutor().submit(new PDFRendererRunnable(this)); + future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new PDFRendererRunnable(this),getDesktop())); } else if ("HTML".equals(previewType.getSelectedItem().getValue())) { - future = Adempiere.getThreadPoolExecutor().submit(new HTMLRendererRunnable(this)); + future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new HTMLRendererRunnable(this),getDesktop())); } else if ("XLS".equals(previewType.getSelectedItem().getValue())) { - future = Adempiere.getThreadPoolExecutor().submit(new XLSRendererRunnable(this)); + future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new XLSRendererRunnable(this),getDesktop())); } }