IDEMPIERE-1550 Zk: Problem with multiple browser tab

This commit is contained in:
Heng Sin Low 2014-03-07 19:35:07 -05:00
parent 8786638e1e
commit 9dd3098138
9 changed files with 71 additions and 50 deletions

View File

@ -103,8 +103,6 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
public static final String EXECUTION_CARRYOVER_SESSION_KEY = "execution.carryover"; 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 final String CLIENT_INFO = "client.info";
private static boolean eventThreadEnabled = false; private static boolean eventThreadEnabled = false;
@ -246,7 +244,6 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
IDesktop appDesktop = createDesktop(); IDesktop appDesktop = createDesktop();
appDesktop.setClientInfo(clientInfo); appDesktop.setClientInfo(clientInfo);
appDesktop.createPart(this.getPage()); appDesktop.createPart(this.getPage());
ctx.put(ZK_DESKTOP_SESSION_KEY, new WeakReference<Desktop>(this.getPage().getDesktop()));
this.getPage().getDesktop().setAttribute(APPLICATION_DESKTOP_KEY, new WeakReference<IDesktop>(appDesktop)); this.getPage().getDesktop().setAttribute(APPLICATION_DESKTOP_KEY, new WeakReference<IDesktop>(appDesktop));
//track browser tab per session //track browser tab per session

View File

@ -34,7 +34,6 @@ import java.util.logging.Level;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import org.adempiere.webui.AdempiereWebUI;
import org.adempiere.webui.component.Window; import org.adempiere.webui.component.Window;
import org.adempiere.webui.desktop.IDesktop; import org.adempiere.webui.desktop.IDesktop;
import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.session.SessionManager;
@ -741,8 +740,7 @@ public final class AEnv
if (inUIThread) { if (inUIThread) {
return Executions.getCurrent().getDesktop(); return Executions.getCurrent().getDesktop();
} else { } else {
@SuppressWarnings("unchecked") WeakReference<Desktop> ref = DesktopRunnable.getThreadLocalDesktop();
WeakReference<Desktop> ref = (WeakReference<Desktop>) Env.getCtx().get(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY);
return ref != null ? ref.get() : null; return ref != null ? ref.get() : null;
} }
} }

View File

@ -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<Desktop> desktopWeakRef;
private static ThreadLocal<WeakReference<Desktop>> threadLocalDesktop = new ThreadLocal<WeakReference<Desktop>>() {
protected WeakReference<Desktop> initialValue()
{
return null;
}
};
public DesktopRunnable(Runnable runnable, Desktop desktop) {
this.runnable = runnable;
this.desktopWeakRef = new WeakReference<Desktop>(desktop);
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
threadLocalDesktop.set(desktopWeakRef);
runnable.run();
} finally {
threadLocalDesktop.remove();
}
}
/* package */static WeakReference<Desktop> getThreadLocalDesktop() {
return threadLocalDesktop.get();
}
}

View File

@ -6,7 +6,6 @@ import static org.compiere.model.SystemIDs.PROCESS_M_INOUT_GENERATE;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.lang.ref.WeakReference;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -20,8 +19,6 @@ import java.util.logging.Level;
import org.adempiere.util.Callback; import org.adempiere.util.Callback;
import org.adempiere.util.ContextRunnable; import org.adempiere.util.ContextRunnable;
import org.adempiere.util.IProcessUI; import org.adempiere.util.IProcessUI;
import org.adempiere.util.ServerContext;
import org.adempiere.webui.AdempiereWebUI;
import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Button;
import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.ConfirmPanel;
@ -347,15 +344,8 @@ public class ProcessDialog extends Window implements EventListener<Event>, IProc
} }
public void runProcess() { 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>(desktop));
}
processDialogRunnable = new ProcessDialogRunnable(); processDialogRunnable = new ProcessDialogRunnable();
future = Adempiere.getThreadPoolExecutor().submit(processDialogRunnable); future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(processDialogRunnable, getDesktop()));
} }
private void onComplete() { private void onComplete() {

View File

@ -17,7 +17,6 @@
package org.adempiere.webui.apps; package org.adempiere.webui.apps;
import java.io.File; import java.io.File;
import java.lang.ref.WeakReference;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -30,8 +29,6 @@ import java.util.logging.Level;
import org.adempiere.util.Callback; import org.adempiere.util.Callback;
import org.adempiere.util.ContextRunnable; import org.adempiere.util.ContextRunnable;
import org.adempiere.util.IProcessUI; import org.adempiere.util.IProcessUI;
import org.adempiere.util.ServerContext;
import org.adempiere.webui.AdempiereWebUI;
import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.Button; import org.adempiere.webui.component.Button;
import org.adempiere.webui.component.ConfirmPanel; import org.adempiere.webui.component.ConfirmPanel;
@ -50,7 +47,6 @@ import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
import org.zkoss.zk.au.out.AuEcho; import org.zkoss.zk.au.out.AuEcho;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
@ -379,15 +375,8 @@ public class ProcessModalDialog extends Window implements EventListener<Event>,
* internal use, don't call this directly * internal use, don't call this directly
*/ */
public void runProcess() { 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>(desktop));
}
processDialogRunnable = new ProcessDialogRunnable(); processDialogRunnable = new ProcessDialogRunnable();
future = Adempiere.getThreadPoolExecutor().submit(processDialogRunnable); future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(processDialogRunnable, getDesktop()));
} }
private void hideBusyDialog() { private void hideBusyDialog() {

View File

@ -14,6 +14,7 @@
package org.adempiere.webui.desktop; package org.adempiere.webui.desktop;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.AdempiereWebUI;
@ -26,6 +27,7 @@ import org.compiere.model.MMenu;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.zkoss.zk.ui.Executions; 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.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Window.Mode; import org.zkoss.zul.Window.Mode;
@ -39,13 +41,10 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop
private transient ClientInfo clientInfo; private transient ClientInfo clientInfo;
private List<Object> windows = null;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final CLogger logger = CLogger.getCLogger(AbstractDesktop.class); private static final CLogger logger = CLogger.getCLogger(AbstractDesktop.class);
public AbstractDesktop() { public AbstractDesktop() {
windows = new ArrayList<Object>();
} }
/** /**
@ -112,6 +111,7 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop
* @param win * @param win
*/ */
public int registerWindow(Object win) { public int registerWindow(Object win) {
List<Object> windows = getWindows();
int retValue = windows.size(); int retValue = windows.size();
windows.add(win); windows.add(win);
return retValue; return retValue;
@ -121,6 +121,7 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop
* @param WindowNo * @param WindowNo
*/ */
public void unregisterWindow(int WindowNo) { public void unregisterWindow(int WindowNo) {
List<Object> windows = getWindows();
if (WindowNo < windows.size()) if (WindowNo < windows.size())
windows.set(WindowNo, null); windows.set(WindowNo, null);
Env.clearWinContext(WindowNo); Env.clearWinContext(WindowNo);
@ -132,6 +133,7 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop
* @return Object * @return Object
*/ */
public Object findWindow(int WindowNo) { public Object findWindow(int WindowNo) {
List<Object> windows = getWindows();
if (WindowNo < windows.size()) if (WindowNo < windows.size())
return windows.get(WindowNo); return windows.get(WindowNo);
else else
@ -297,7 +299,14 @@ public abstract class AbstractDesktop extends AbstractUIPart implements IDesktop
} }
protected List<Object> getWindows(){ protected List<Object> getWindows(){
return windows; Session session = getComponent().getDesktop().getSession();
@SuppressWarnings("unchecked")
List<Object> list = (List<Object>) session.getAttribute("windows.list");
if (list == null) {
list = new ArrayList<Object>();
session.setAttribute("windows.list", list);
}
return Collections.synchronizedList(list);
} }
} }

View File

@ -30,6 +30,7 @@ import org.adempiere.util.ServerContext;
import org.adempiere.webui.adwindow.ADWindow; import org.adempiere.webui.adwindow.ADWindow;
import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.apps.BusyDialog; import org.adempiere.webui.apps.BusyDialog;
import org.adempiere.webui.apps.DesktopRunnable;
import org.adempiere.webui.apps.ProcessDialog; import org.adempiere.webui.apps.ProcessDialog;
import org.adempiere.webui.apps.WReport; import org.adempiere.webui.apps.WReport;
import org.adempiere.webui.component.Tab; 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(); ToolBar toolbar = new ToolBar();
windowContainer.getComponent().appendChild(toolbar); windowContainer.getComponent().appendChild(toolbar);

View File

@ -17,7 +17,6 @@
package org.adempiere.webui.session; package org.adempiere.webui.session;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -133,8 +132,6 @@ public class SessionContextListener implements ExecutionInit,
//set locale //set locale
Locales.setThreadLocal(Env.getLanguage(ServerContext.getCurrentInstance()).getLocale()); Locales.setThreadLocal(Env.getLanguage(ServerContext.getCurrentInstance()).getLocale());
} }
Properties ctx = ServerContext.getCurrentInstance();
ctx.put(AdempiereWebUI.ZK_DESKTOP_SESSION_KEY, new WeakReference<Desktop>(exec.getDesktop()));
} }
} }

View File

@ -21,7 +21,6 @@ import static org.compiere.model.SystemIDs.WINDOW_PRINTFORMAT;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.StringWriter; import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -36,11 +35,10 @@ import javax.servlet.http.HttpServletRequest;
import org.adempiere.exceptions.DBException; import org.adempiere.exceptions.DBException;
import org.adempiere.pdf.Document; import org.adempiere.pdf.Document;
import org.adempiere.util.ContextRunnable; import org.adempiere.util.ContextRunnable;
import org.adempiere.util.ServerContext;
import org.adempiere.webui.AdempiereWebUI;
import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.apps.BusyDialog; import org.adempiere.webui.apps.BusyDialog;
import org.adempiere.webui.apps.DesktopRunnable;
import org.adempiere.webui.apps.WReport; import org.adempiere.webui.apps.WReport;
import org.adempiere.webui.apps.form.WReportCustomization; import org.adempiere.webui.apps.form.WReportCustomization;
import org.adempiere.webui.component.Checkbox; import org.adempiere.webui.component.Checkbox;
@ -461,21 +459,14 @@ public class ZkReportViewer extends Window implements EventListener<Event>, ITab
} }
private void renderReport() { 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>(desktop));
}
media = null; media = null;
Listitem selected = previewType.getSelectedItem(); Listitem selected = previewType.getSelectedItem();
if (selected == null || "PDF".equals(selected.getValue())) { 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())) { } 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())) { } else if ("XLS".equals(previewType.getSelectedItem().getValue())) {
future = Adempiere.getThreadPoolExecutor().submit(new XLSRendererRunnable(this)); future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new XLSRendererRunnable(this),getDesktop()));
} }
} }