From 99cead1540e137b4e79cceb4b6dfeb207f5a6b7d Mon Sep 17 00:00:00 2001 From: hengsin Date: Thu, 2 Apr 2020 09:58:01 +0800 Subject: [PATCH] IDEMPIERE-4228 Align ServerPush implementation with Executions.schedule JavaDoc --- .../zk/atmosphere/AtmosphereServerPush.java | 41 +++++++++++-------- .../org/adempiere/webui/AdempiereWebUI.java | 27 ++++++++++++ .../webui/desktop/DefaultDesktop.java | 34 ++------------- .../webui/editor/WTableDirEditor.java | 14 ++----- .../ui/zk/websocket/WebSocketServerPush.java | 26 ++++++------ 5 files changed, 72 insertions(+), 70 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/fi/jawsy/jawwa/zk/atmosphere/AtmosphereServerPush.java b/org.adempiere.ui.zk/WEB-INF/src/fi/jawsy/jawwa/zk/atmosphere/AtmosphereServerPush.java index 71afc6ef92..d2cf3a125b 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/fi/jawsy/jawwa/zk/atmosphere/AtmosphereServerPush.java +++ b/org.adempiere.ui.zk/WEB-INF/src/fi/jawsy/jawwa/zk/atmosphere/AtmosphereServerPush.java @@ -29,6 +29,7 @@ import org.atmosphere.cpr.AtmosphereResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zkoss.lang.Library; +import org.zkoss.zk.au.out.AuEcho; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.DesktopUnavailableException; @@ -62,6 +63,7 @@ public class AtmosphereServerPush implements ServerPush { private ExecutionCarryOver _carryOver; private final Object _mutex = new Object(); private List> schedules = new ArrayList<>(); + private long lastPiggyBack = 0; public AtmosphereServerPush() { String timeoutString = Library.getProperty("fi.jawsy.jawwa.zk.atmosphere.timeout"); @@ -162,6 +164,7 @@ public class AtmosphereServerPush implements ServerPush { @SuppressWarnings("unchecked") @Override public void onPiggyback() { + lastPiggyBack = System.currentTimeMillis(); Schedule[] pendings = null; synchronized (schedules) { if (!schedules.isEmpty()) { @@ -171,6 +174,7 @@ public class AtmosphereServerPush implements ServerPush { } if (pendings != null && pendings.length > 0) { for(Schedule p : pendings) { + //schedule and execute in desktop's onPiggyBack listener p.scheduler.schedule(p.task, p.event); } } @@ -180,53 +184,54 @@ public class AtmosphereServerPush implements ServerPush { @Override public void schedule(EventListener task, T event, Scheduler scheduler) { + if (Executions.getCurrent() == null) { - //save for schedule at on piggyback event - synchronized (schedules) { - schedules.add(new Schedule(task, event, scheduler)); - } - boolean ok = false; + //schedule and execute in desktop's onPiggyBack listener + scheduler.schedule(task, event); + boolean ok = false; try { ok = commitResponse(); } catch (IOException e) { log.error(e.getMessage(), e); } if (!ok) { + long l = lastPiggyBack; for(int i = 0; i < 3 && !ok; i++) { try { Thread.sleep(100); } catch (InterruptedException e1) {} - if (schedules.size() > 0) { + if (l == lastPiggyBack) { try { ok = commitResponse(); } catch (IOException e) { log.error(e.getMessage(), e); } - } else { - ok = true; - } + } else { + ok = true; + } } if (!ok) { Desktop d = desktop.get(); log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : "")); if (d != null) { - Integer count = (Integer) d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); - if (count != null) - count = Integer.valueOf(count.intValue()+1); - else - count = Integer.valueOf(1); - d.setAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES, count); + AdempiereWebUI.increaseScheduleFailures(d); } } } } else { - //in event listener thread, can schedule immediately - scheduler.schedule(task, event); + // in event listener thread, use echo to execute async + synchronized (schedules) { + schedules.add(new Schedule(task, event, scheduler)); + } + if (Executions.getCurrent().getAttribute("AtmosphereServerPush.Echo") == null) { + Executions.getCurrent().setAttribute("AtmosphereServerPush.Echo", Boolean.TRUE); + Clients.response(new AuEcho()); + } } } - @Override + @Override public void start(Desktop desktop) { Desktop oldDesktop = this.desktop.getAndSet(desktop); if (oldDesktop != null) { 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 a841868c40..a99ad6b54f 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 @@ -594,4 +594,31 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb } return uploadSetting.toString(); } + + /** + * Increase server push schedule failures count + * @param d + */ + public static void increaseScheduleFailures(Desktop d) { + Integer count = (Integer) d.getAttribute(SERVERPUSH_SCHEDULE_FAILURES); + if (count != null) + count = Integer.valueOf(count.intValue()+1); + else + count = Integer.valueOf(1); + d.setAttribute(SERVERPUSH_SCHEDULE_FAILURES, count); + } + + /** + * + * @param d + * @return server push schedule failures count + */ + public static int getScheduleFailures(Desktop d) { + int failures = 0; + Object attr = d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); + if (attr != null && attr instanceof Integer) + failures = ((Integer)attr).intValue(); + + return failures; + } } 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 a060514ec1..2a4ecc4f7f 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 @@ -31,13 +31,11 @@ import org.adempiere.base.event.EventManager; import org.adempiere.base.event.IEventManager; import org.adempiere.base.event.IEventTopics; import org.adempiere.model.MBroadcastMessage; -import org.adempiere.util.ServerContext; import org.adempiere.webui.ClientInfo; import org.adempiere.webui.LayoutUtils; 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; @@ -54,15 +52,11 @@ import org.adempiere.webui.panel.BroadcastMessageWindow; import org.adempiere.webui.panel.HeaderPanel; import org.adempiere.webui.panel.HelpController; import org.adempiere.webui.panel.TimeoutPanel; -import org.adempiere.webui.session.SessionContextListener; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ThemeManager; -import org.adempiere.webui.util.IServerPushCallback; -import org.adempiere.webui.util.ServerPushTemplate; import org.adempiere.webui.util.UserPreference; import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.FDialog; -import org.compiere.Adempiere; import org.compiere.model.GridField; import org.compiere.model.GridTab; import org.compiere.model.I_AD_Preference; @@ -382,30 +376,10 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria layout.getDesktop().enableServerPush(true); } - Runnable runnable = new Runnable() { - public void run() { - try { - Thread.sleep(100); - } catch (InterruptedException e) {} - - IServerPushCallback callback = new IServerPushCallback() { - public void updateUI() { - Properties ctx = (Properties)layout.getDesktop().getSession().getAttribute(SessionContextListener.SESSION_CTX); - try { - ServerContext.setCurrentInstance(ctx); - renderHomeTab(); - automaticOpen(ctx); - } finally { - ServerContext.dispose(); - } - } - }; - ServerPushTemplate template = new ServerPushTemplate(layout.getDesktop()); - template.executeAsync(callback); - } - }; - - Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(runnable,layout.getDesktop())); + Executions.schedule(layout.getDesktop(), event -> { + renderHomeTab(); + automaticOpen(Env.getCtx()); + }, new Event("onRenderHomeTab")); ToolBar toolbar = windowContainer.getToobar(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java index 021bcca920..01bbf2c427 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/WTableDirEditor.java @@ -918,11 +918,8 @@ ContextMenuListener, IZoomableEditor } private void refreshLookupList() { - int failures = 0; Desktop desktop = editor.getComponent().getDesktop(); - Object attr = desktop.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); - if (attr != null && attr instanceof Integer) - failures = ((Integer)attr).intValue(); + int failures = AdempiereWebUI.getScheduleFailures(desktop); Executions.schedule(desktop, new EventListener() { @Override public void onEvent(Event event) { @@ -932,12 +929,9 @@ ContextMenuListener, IZoomableEditor } catch (Exception e) {} } }, new Event("onResetLookupList")); - attr = desktop.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); - if (attr != null && attr instanceof Integer) { - int f = ((Integer)attr).intValue(); - if (f > failures) { - ((ITableDirEditor)editor.getComponent()).cleanup(); - } + int f = AdempiereWebUI.getScheduleFailures(desktop); + if (f > failures) { + ((ITableDirEditor)editor.getComponent()).cleanup(); } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/idempiere/ui/zk/websocket/WebSocketServerPush.java b/org.adempiere.ui.zk/WEB-INF/src/org/idempiere/ui/zk/websocket/WebSocketServerPush.java index 049eeda286..0fb6822939 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/idempiere/ui/zk/websocket/WebSocketServerPush.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/idempiere/ui/zk/websocket/WebSocketServerPush.java @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.adempiere.webui.AdempiereWebUI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.zkoss.zk.au.out.AuEcho; import org.zkoss.zk.au.out.AuScript; import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.DesktopUnavailableException; @@ -177,6 +178,7 @@ public class WebSocketServerPush implements ServerPush { } if (pendings != null && pendings.length > 0) { for(Schedule p : pendings) { + //schedule and execute in desktop's onPiggyBack listener p.scheduler.schedule(p.task, p.event); } } @@ -199,25 +201,25 @@ public class WebSocketServerPush implements ServerPush { public void schedule(EventListener task, T event, Scheduler scheduler) { if (Executions.getCurrent() == null) { - //save for schedule at on piggyback event - synchronized (schedules) { - schedules.add(new Schedule(task, event, scheduler)); - } + //schedule and execute in desktop's onPiggyBack listener + scheduler.schedule(task, event); boolean ok = echo(); if (!ok) { Desktop d = desktop.get(); + log.warn("Failed to resume long polling resource" + (d != null ? " for desktop " + d.getId() : "")); if (d != null) { - Integer count = (Integer) d.getAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES); - if (count != null) - count = Integer.valueOf(count.intValue()+1); - else - count = Integer.valueOf(1); - d.setAttribute(AdempiereWebUI.SERVERPUSH_SCHEDULE_FAILURES, count); + AdempiereWebUI.increaseScheduleFailures(d); } } } else { - //in event listener thread, can schedule immediately - scheduler.schedule(task, event); + // in event listener thread, use echo to execute async + synchronized (schedules) { + schedules.add(new Schedule(task, event, scheduler)); + } + if (Executions.getCurrent().getAttribute("AtmosphereServerPush.Echo") == null) { + Executions.getCurrent().setAttribute("AtmosphereServerPush.Echo", Boolean.TRUE); + Clients.response(new AuEcho()); + } } }