From 2b24496d16c4ce464114cc01f6c713cb62d525d8 Mon Sep 17 00:00:00 2001 From: hengsin Date: Sun, 5 Feb 2023 18:21:48 +0800 Subject: [PATCH] IDEMPIERE-5557 Dashboard Rendering Threads do not hold language set after login (#1659) - add setup of thread local Locale to ContextRunnable --- .../org/adempiere/util/ContextRunnable.java | 29 ++++++++- .../webui/apps/AbstractProcessDialog.java | 4 +- .../webui/dashboard/DPDocumentStatus.java | 4 +- .../webui/dashboard/DashboardRunnable.java | 4 +- .../webui/desktop/DashboardController.java | 6 +- .../webui/util/ZkContextRunnable.java | 63 +++++++++++++++++++ .../webui/window/ZkReportViewer.java | 12 ++-- 7 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/ZkContextRunnable.java diff --git a/org.adempiere.base/src/org/adempiere/util/ContextRunnable.java b/org.adempiere.base/src/org/adempiere/util/ContextRunnable.java index 8fe3464fcc..86ccf8a720 100644 --- a/org.adempiere.base/src/org/adempiere/util/ContextRunnable.java +++ b/org.adempiere.base/src/org/adempiere/util/ContextRunnable.java @@ -17,13 +17,19 @@ import java.util.Properties; /** + * Base class to implement runnable that will execute code in session context * @author hengsin - * */ public abstract class ContextRunnable implements Runnable { + /** + * current session context + */ protected Properties context = null; + /** + * default constructor + */ public ContextRunnable() { this.context = ServerContext.getCurrentInstance(); } @@ -34,12 +40,29 @@ public abstract class ContextRunnable implements Runnable { @Override public void run() { try { - ServerContext.setCurrentInstance(context); + setup(); doRun(); } finally { - ServerContext.dispose(); + cleanup(); } } + /** + * setup thread context + */ + protected void setup() { + ServerContext.setCurrentInstance(context); + } + + /** + * clean up thread context + */ + protected void cleanup() { + ServerContext.dispose(); + } + + /** + * override to execute code in session context + */ protected abstract void doRun(); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java index 9bbb58bfea..22bcf69b1b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/AbstractProcessDialog.java @@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit; 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.LayoutUtils; @@ -50,6 +49,7 @@ import org.adempiere.webui.info.InfoWindow; import org.adempiere.webui.process.WProcessInfo; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.util.ZKUpdateUtil; +import org.adempiere.webui.util.ZkContextRunnable; import org.adempiere.webui.window.Dialog; import org.adempiere.webui.window.MultiFileDownloadDialog; import org.adempiere.webui.window.SimplePDFViewer; @@ -1142,7 +1142,7 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI return downloadFiles; } - private class ProcessDialogRunnable extends ContextRunnable + private class ProcessDialogRunnable extends ZkContextRunnable { private Trx m_trx; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPDocumentStatus.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPDocumentStatus.java index 33b826c958..21948a2002 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPDocumentStatus.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/dashboard/DPDocumentStatus.java @@ -29,12 +29,12 @@ package org.adempiere.webui.dashboard; -import org.adempiere.util.ContextRunnable; import org.adempiere.webui.apps.BusyDialog; import org.adempiere.webui.apps.graph.WDocumentStatusPanel; import org.adempiere.webui.component.ToolBarButton; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.ServerPushTemplate; +import org.adempiere.webui.util.ZkContextRunnable; import org.compiere.Adempiere; import org.compiere.util.Env; import org.compiere.util.Msg; @@ -102,7 +102,7 @@ public class DPDocumentStatus extends DashboardPanel implements EventListener { } } final Component zulComponent = zComponent; - ContextRunnable cr = new ContextRunnable() { + ZkContextRunnable cr = new ZkContextRunnable() { @Override protected void doRun() { try { @@ -594,7 +594,7 @@ public class DashboardController implements EventListener { } } final Component zulComponent = zComponent; - ContextRunnable cr = new ContextRunnable() { + ZkContextRunnable cr = new ZkContextRunnable() { @Override protected void doRun() { try { diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/ZkContextRunnable.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/ZkContextRunnable.java new file mode 100644 index 0000000000..bf0872d63b --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/ZkContextRunnable.java @@ -0,0 +1,63 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - hengsin * + **********************************************************************/ +package org.adempiere.webui.util; + +import java.util.Locale; + +import org.adempiere.util.ContextRunnable; +import org.zkoss.util.Locales; + +/** + * This class setup additional zk specific session context. + * Zk web UI code should use this instead of ContextRunnable. + * @author hengsin + */ +public abstract class ZkContextRunnable extends ContextRunnable { + + //session locale + private Locale locale = null; + //original locale for thread + private Locale old = null; + + /** + * default constructor + */ + public ZkContextRunnable() { + super(); + locale = Locales.getCurrent(); + } + + @Override + protected void setup() { + super.setup(); + old = Locales.setThreadLocal(locale); + } + + @Override + protected void cleanup() { + super.cleanup(); + Locales.setThreadLocal(old); + } +} 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 dd568f218f..3df546cc17 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 @@ -38,7 +38,6 @@ import org.adempiere.base.upload.IUploadService; import org.adempiere.exceptions.DBException; import org.adempiere.pdf.Document; import org.adempiere.util.Callback; -import org.adempiere.util.ContextRunnable; import org.adempiere.webui.ClientInfo; import org.adempiere.webui.Extensions; import org.adempiere.webui.LayoutUtils; @@ -71,6 +70,7 @@ import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.IServerPushCallback; import org.adempiere.webui.util.ServerPushTemplate; import org.adempiere.webui.util.ZKUpdateUtil; +import org.adempiere.webui.util.ZkContextRunnable; import org.compiere.model.GridField; import org.compiere.model.MArchive; import org.compiere.model.MAttachment; @@ -1797,7 +1797,7 @@ public class ZkReportViewer extends Window implements EventListener, ITab } } - static class PDFRendererRunnable extends ContextRunnable implements IServerPushCallback { + static class PDFRendererRunnable extends ZkContextRunnable implements IServerPushCallback { private ZkReportViewer viewer; @@ -1833,7 +1833,7 @@ public class ZkReportViewer extends Window implements EventListener, ITab } - static class HTMLRendererRunnable extends ContextRunnable implements IServerPushCallback { + static class HTMLRendererRunnable extends ZkContextRunnable implements IServerPushCallback { private ZkReportViewer viewer; public HTMLRendererRunnable(ZkReportViewer viewer) { @@ -1868,7 +1868,7 @@ public class ZkReportViewer extends Window implements EventListener, ITab } } - static class XLSRendererRunnable extends ContextRunnable implements IServerPushCallback { + static class XLSRendererRunnable extends ZkContextRunnable implements IServerPushCallback { private ZkReportViewer viewer; @@ -1904,7 +1904,7 @@ public class ZkReportViewer extends Window implements EventListener, ITab } - static class CSVRendererRunnable extends ContextRunnable implements IServerPushCallback { + static class CSVRendererRunnable extends ZkContextRunnable implements IServerPushCallback { private ZkReportViewer viewer; @@ -1938,7 +1938,7 @@ public class ZkReportViewer extends Window implements EventListener, ITab } - protected static class XLSXRendererRunnable extends ContextRunnable implements IServerPushCallback + protected static class XLSXRendererRunnable extends ZkContextRunnable implements IServerPushCallback { private ZkReportViewer viewer;