[ 2486831 ] Dashboard auto refresh performance issue
This commit is contained in:
parent
ac7b3839e6
commit
12c4c3ea4e
|
@ -19,6 +19,7 @@ import java.util.logging.Level;
|
|||
|
||||
import org.adempiere.webui.component.Button;
|
||||
import org.adempiere.webui.session.SessionManager;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
|
@ -42,6 +43,12 @@ public class DPActivities extends DashboardPanel implements EventListener {
|
|||
private static final CLogger logger = CLogger.getCLogger(DPActivities.class);
|
||||
|
||||
private Button btnNotice, btnRequest, btnWorkflow;
|
||||
|
||||
private int noOfNotice;
|
||||
|
||||
private int noOfRequest;
|
||||
|
||||
private int noOfWorkflow;
|
||||
|
||||
public DPActivities()
|
||||
{
|
||||
|
@ -162,18 +169,24 @@ public class DPActivities extends DashboardPanel implements EventListener {
|
|||
return count;
|
||||
}
|
||||
|
||||
public void refresh()
|
||||
@Override
|
||||
public void refresh(ServerPushTemplate template)
|
||||
{
|
||||
int noOfNotice = getNoticeCount();
|
||||
int noOfRequest = getRequestCount();
|
||||
int noOfWorkflow = getWorkflowCount();
|
||||
noOfNotice = getNoticeCount();
|
||||
noOfRequest = getRequestCount();
|
||||
noOfWorkflow = getWorkflowCount();
|
||||
|
||||
btnNotice.setLabel("Notice : " + noOfNotice);
|
||||
template.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
btnNotice.setLabel("Notice : " + noOfNotice);
|
||||
btnRequest.setLabel("Request : " + noOfRequest);
|
||||
btnWorkflow.setLabel("Workflow Activities : " + noOfWorkflow);
|
||||
}
|
||||
|
||||
public void onEvent(Event event)
|
||||
|
||||
public void onEvent(Event event)
|
||||
{
|
||||
Component comp = event.getTarget();
|
||||
String eventName = event.getName();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
package org.adempiere.webui.dashboard;
|
||||
|
||||
import org.adempiere.webui.component.Window;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
|
||||
/**
|
||||
* Custom dashboard item base class
|
||||
|
@ -27,12 +28,9 @@ public abstract class DashboardPanel extends Window implements IDashboardPanel {
|
|||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Desktop.UpdateInfoRunnable will call this method at a certain interval.
|
||||
* Subclass should overwrite this method to support server push.
|
||||
*/
|
||||
public void refresh() {
|
||||
|
||||
public void refresh(ServerPushTemplate template) {
|
||||
}
|
||||
|
||||
public void updateUI() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,21 +15,34 @@ package org.adempiere.webui.dashboard;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.webui.desktop.IDesktop;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.zkoss.zk.ui.Desktop;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class DashboardRunnable implements Runnable {
|
||||
private Desktop desktop;
|
||||
private boolean stop = false;
|
||||
private List<DashboardPanel> dashboardPanels;
|
||||
private IDesktop appDesktop;
|
||||
|
||||
private static final CLogger logger = CLogger.getCLogger(DashboardRunnable.class);
|
||||
@SuppressWarnings("unused")
|
||||
private static final CLogger logger = CLogger.getCLogger(DashboardRunnable.class);
|
||||
|
||||
private final static String ZK_DASHBOARD_REFRESH_INTERVAL = "ZK_DASHBOARD_REFRESH_INTERVAL";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param desktop zk desktop interface
|
||||
* @param appDesktop adempiere desktop interface
|
||||
*/
|
||||
public DashboardRunnable(Desktop desktop, IDesktop appDesktop) {
|
||||
this.desktop = desktop;
|
||||
this.appDesktop = appDesktop;
|
||||
|
@ -39,44 +52,43 @@ public class DashboardRunnable implements Runnable {
|
|||
|
||||
public void run()
|
||||
{
|
||||
// default Update every one minutes
|
||||
int interval = MSysConfig.getIntValue(ZK_DASHBOARD_REFRESH_INTERVAL, 60000);
|
||||
while(!stop) {
|
||||
try {
|
||||
Thread.sleep(60000); // Update every one minutes
|
||||
Thread.sleep(interval);
|
||||
} catch (InterruptedException e1) {
|
||||
if (stop) break;
|
||||
}
|
||||
|
||||
try {
|
||||
// get full control of desktop
|
||||
Executions.activate(desktop);
|
||||
try {
|
||||
refreshDashboard();
|
||||
} catch (Error ex) {
|
||||
logger.log(Level.WARNING, "UpdateInfo Thread error="+ex.getLocalizedMessage(), ex);
|
||||
break;
|
||||
} finally {
|
||||
// release full control of desktop
|
||||
Executions.deactivate(desktop);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.log(Level.WARNING, "UpdateInfo Thread error="+e.getLocalizedMessage(), e);
|
||||
if (desktop.isAlive()) {
|
||||
refreshDashboard();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh dashboard content
|
||||
*/
|
||||
public void refreshDashboard()
|
||||
{
|
||||
ServerPushTemplate template = new ServerPushTemplate(desktop);
|
||||
for(int i = 0; i < dashboardPanels.size(); i++)
|
||||
dashboardPanels.get(i).refresh();
|
||||
dashboardPanels.get(i).refresh(template);
|
||||
|
||||
appDesktop.onServerPush();
|
||||
appDesktop.onServerPush(template);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
stop = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add DashboardPanel to the auto refresh list
|
||||
* @param dashboardPanel
|
||||
*/
|
||||
public void add(DashboardPanel dashboardPanel) {
|
||||
dashboardPanels.add(dashboardPanel);
|
||||
}
|
||||
|
|
|
@ -13,17 +13,22 @@
|
|||
*****************************************************************************/
|
||||
package org.adempiere.webui.dashboard;
|
||||
|
||||
import org.adempiere.webui.util.IServerPushCallback;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
|
||||
/**
|
||||
* Interface for dashboard panel
|
||||
* @author Elaine
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public interface IDashboardPanel {
|
||||
public interface IDashboardPanel extends IServerPushCallback {
|
||||
|
||||
/**
|
||||
* Refresh content of panel
|
||||
* Refresh content of panel. For performance reason, keep the activate of desktop as short
|
||||
* as possible.
|
||||
* @param template
|
||||
*/
|
||||
public void refresh();
|
||||
public void refresh(ServerPushTemplate template);
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ import org.adempiere.webui.dashboard.DashboardRunnable;
|
|||
import org.adempiere.webui.event.MenuListener;
|
||||
import org.adempiere.webui.panel.HeaderPanel;
|
||||
import org.adempiere.webui.panel.SidePanel;
|
||||
import org.adempiere.webui.util.IServerPushCallback;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.compiere.model.MMenu;
|
||||
import org.compiere.model.X_AD_Menu;
|
||||
import org.compiere.model.X_PA_DashboardContent;
|
||||
|
@ -65,7 +67,7 @@ import org.zkoss.zul.Panelchildren;
|
|||
* @date Mar 2, 2007
|
||||
* @version $Revision: 0.10 $
|
||||
*/
|
||||
public class DefaultDesktop extends TabbedDesktop implements MenuListener, Serializable, EventListener
|
||||
public class DefaultDesktop extends TabbedDesktop implements MenuListener, Serializable, EventListener, IServerPushCallback
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 9056511175189603883L;
|
||||
|
@ -79,6 +81,12 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
|||
private Thread dashboardThread;
|
||||
|
||||
private DashboardRunnable dashboardRunnable;
|
||||
|
||||
private int noOfNotice;
|
||||
|
||||
private int noOfRequest;
|
||||
|
||||
private int noOfWorkflow;
|
||||
|
||||
public DefaultDesktop()
|
||||
{
|
||||
|
@ -348,15 +356,13 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
|||
}
|
||||
}
|
||||
|
||||
public void onServerPush()
|
||||
public void onServerPush(ServerPushTemplate template)
|
||||
{
|
||||
int noOfNotice = DPActivities.getNoticeCount();
|
||||
int noOfRequest = DPActivities.getRequestCount();
|
||||
int noOfWorkflow = DPActivities.getWorkflowCount();
|
||||
int total = noOfNotice + noOfRequest + noOfWorkflow;
|
||||
noOfNotice = DPActivities.getNoticeCount();
|
||||
noOfRequest = DPActivities.getRequestCount();
|
||||
noOfWorkflow = DPActivities.getWorkflowCount();
|
||||
|
||||
windowContainer.setTabTitle(0, "Home (" + total + ")",
|
||||
"Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow);
|
||||
template.execute(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -384,4 +390,10 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
|||
dashboardThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUI() {
|
||||
int total = noOfNotice + noOfRequest + noOfWorkflow;
|
||||
windowContainer.setTabTitle(0, "Home (" + total + ")",
|
||||
"Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.adempiere.webui.apps.ProcessDialog;
|
|||
import org.adempiere.webui.component.Window;
|
||||
import org.adempiere.webui.panel.ADForm;
|
||||
import org.adempiere.webui.part.UIPart;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.adempiere.webui.window.ADWindow;
|
||||
import org.compiere.model.MQuery;
|
||||
import org.compiere.util.WebDoc;
|
||||
|
@ -171,7 +172,10 @@ public interface IDesktop extends UIPart {
|
|||
public void logout();
|
||||
|
||||
/**
|
||||
* Invoke by the server push thread.
|
||||
* Invoke by the server push thread. If the desktop argument is not null, must activate desktop
|
||||
* before making update to UI. For performance reason, keep the activate of desktop as short
|
||||
* as possible.
|
||||
* @param template
|
||||
*/
|
||||
public void onServerPush();
|
||||
public void onServerPush(ServerPushTemplate template);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.adempiere.webui.dashboard.DashboardRunnable;
|
|||
import org.adempiere.webui.event.MenuListener;
|
||||
import org.adempiere.webui.panel.HeaderPanel;
|
||||
import org.adempiere.webui.panel.SidePanel;
|
||||
import org.adempiere.webui.util.IServerPushCallback;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.compiere.model.MMenu;
|
||||
import org.compiere.model.X_AD_Menu;
|
||||
import org.compiere.model.X_PA_DashboardContent;
|
||||
|
@ -58,7 +60,7 @@ import org.zkoss.zul.Panelchildren;
|
|||
/**
|
||||
* @author hengsin
|
||||
*/
|
||||
public class NavBar2Desktop extends TabbedDesktop implements MenuListener, Serializable, EventListener
|
||||
public class NavBar2Desktop extends TabbedDesktop implements MenuListener, Serializable, EventListener, IServerPushCallback
|
||||
{
|
||||
|
||||
private static final String FAVOURITES_PATH = "/zul/favourites.zul";
|
||||
|
@ -79,6 +81,12 @@ public class NavBar2Desktop extends TabbedDesktop implements MenuListener, Seria
|
|||
|
||||
private Accordion shortcutPanel;
|
||||
|
||||
private int noOfNotice;
|
||||
|
||||
private int noOfRequest;
|
||||
|
||||
private int noOfWorkflow;
|
||||
|
||||
public NavBar2Desktop()
|
||||
{
|
||||
super();
|
||||
|
@ -388,15 +396,13 @@ public class NavBar2Desktop extends TabbedDesktop implements MenuListener, Seria
|
|||
}
|
||||
}
|
||||
|
||||
public void onServerPush()
|
||||
public void onServerPush(ServerPushTemplate template)
|
||||
{
|
||||
int noOfNotice = DPActivities.getNoticeCount();
|
||||
int noOfRequest = DPActivities.getRequestCount();
|
||||
int noOfWorkflow = DPActivities.getWorkflowCount();
|
||||
int total = noOfNotice + noOfRequest + noOfWorkflow;
|
||||
noOfNotice = DPActivities.getNoticeCount();
|
||||
noOfRequest = DPActivities.getRequestCount();
|
||||
noOfWorkflow = DPActivities.getWorkflowCount();
|
||||
|
||||
shortcutPanel.setLabel(1, "Activities (" + total + ")");
|
||||
shortcutPanel.setTooltiptext(1, "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow);
|
||||
template.execute(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -424,4 +430,10 @@ public class NavBar2Desktop extends TabbedDesktop implements MenuListener, Seria
|
|||
dashboardThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUI() {
|
||||
int total = noOfNotice + noOfRequest + noOfWorkflow;
|
||||
shortcutPanel.setLabel(1, "Activities (" + total + ")");
|
||||
shortcutPanel.setTooltiptext(1, "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ import org.adempiere.webui.dashboard.DashboardRunnable;
|
|||
import org.adempiere.webui.event.MenuListener;
|
||||
import org.adempiere.webui.panel.HeaderPanel;
|
||||
import org.adempiere.webui.panel.SidePanel;
|
||||
import org.adempiere.webui.util.IServerPushCallback;
|
||||
import org.adempiere.webui.util.ServerPushTemplate;
|
||||
import org.compiere.model.MMenu;
|
||||
import org.compiere.model.X_AD_Menu;
|
||||
import org.compiere.model.X_PA_DashboardContent;
|
||||
|
@ -62,7 +64,7 @@ import org.zkoss.zul.Treerow;
|
|||
/**
|
||||
* @author hengsin
|
||||
*/
|
||||
public class NavBarDesktop extends TabbedDesktop implements MenuListener, Serializable, EventListener
|
||||
public class NavBarDesktop extends TabbedDesktop implements MenuListener, Serializable, EventListener, IServerPushCallback
|
||||
{
|
||||
|
||||
private static final String FAVOURITES_PATH = "/zul/favourites.zul";
|
||||
|
@ -88,6 +90,12 @@ public class NavBarDesktop extends TabbedDesktop implements MenuListener, Serial
|
|||
private West leftRegion;
|
||||
|
||||
private DPFavourites favPanel;
|
||||
|
||||
private int noOfNotice;
|
||||
|
||||
private int noOfRequest;
|
||||
|
||||
private int noOfWorkflow;
|
||||
|
||||
public NavBarDesktop()
|
||||
{
|
||||
|
@ -404,15 +412,13 @@ public class NavBarDesktop extends TabbedDesktop implements MenuListener, Serial
|
|||
}
|
||||
}
|
||||
|
||||
public void onServerPush()
|
||||
public void onServerPush(ServerPushTemplate template)
|
||||
{
|
||||
int noOfNotice = DPActivities.getNoticeCount();
|
||||
int noOfRequest = DPActivities.getRequestCount();
|
||||
int noOfWorkflow = DPActivities.getWorkflowCount();
|
||||
int total = noOfNotice + noOfRequest + noOfWorkflow;
|
||||
|
||||
navigationPanel.setLabel(2, "Activities (" + total + ")");
|
||||
navigationPanel.setTooltiptext(2, "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow);
|
||||
noOfNotice = DPActivities.getNoticeCount();
|
||||
noOfRequest = DPActivities.getRequestCount();
|
||||
noOfWorkflow = DPActivities.getWorkflowCount();
|
||||
|
||||
template.execute(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -440,4 +446,10 @@ public class NavBarDesktop extends TabbedDesktop implements MenuListener, Serial
|
|||
dashboardThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateUI() {
|
||||
int total = noOfNotice + noOfRequest + noOfWorkflow;
|
||||
navigationPanel.setLabel(2, "Activities (" + total + ")");
|
||||
navigationPanel.setTooltiptext(2, "Notice : " + noOfNotice + ", Request : " + noOfRequest + ", Workflow Activities : " + noOfWorkflow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2008 Low Heng Sin *
|
||||
* Copyright (C) 2008 Idalica Corporation *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.webui.util;
|
||||
|
||||
/**
|
||||
* Callback interface to perform UI update inside the UI thread or server push thread.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public interface IServerPushCallback {
|
||||
|
||||
/**
|
||||
* Callback method to perform UI related update. For performance reason, implementation of this method
|
||||
* must not perform potentially slow operation.
|
||||
*/
|
||||
public void updateUI();
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2008 Low Heng Sin *
|
||||
* Copyright (C) 2008 Idalica Corporation *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.webui.util;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.util.CLogger;
|
||||
import org.zkoss.zk.ui.Desktop;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
|
||||
/**
|
||||
* Zk UI update must be done in either UI thread or using server push. This class help to implement
|
||||
* that base on spring's jdbctemplate pattern.
|
||||
* @author hengsin
|
||||
*
|
||||
*/
|
||||
public class ServerPushTemplate {
|
||||
|
||||
private Desktop desktop;
|
||||
|
||||
private final static CLogger logger = CLogger.getCLogger(ServerPushTemplate.class);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param desktop
|
||||
*/
|
||||
public ServerPushTemplate(Desktop desktop) {
|
||||
this.desktop = desktop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute callback in UI thread
|
||||
* @param callback
|
||||
*/
|
||||
public void execute(IServerPushCallback callback) {
|
||||
boolean inUIThread = Executions.getCurrent() != null;
|
||||
|
||||
try {
|
||||
if (!inUIThread) {
|
||||
//1 second timeout
|
||||
Executions.activate(desktop, 1000);
|
||||
}
|
||||
callback.updateUI();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Server push error="+e.getLocalizedMessage(), e);
|
||||
} finally {
|
||||
if (!inUIThread) {
|
||||
Executions.deactivate(desktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return desktop
|
||||
*/
|
||||
public Desktop getDesktop() {
|
||||
return desktop;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue