From 309eb5366f9de208afa336975ffd81cc0e4e5566 Mon Sep 17 00:00:00 2001 From: hengsin Date: Tue, 14 Sep 2021 22:16:07 +0800 Subject: [PATCH] IDEMPIERE-4960 Performance improvement for the opening of info window (#876) * IDEMPIERE-4960 Performance improvement for the opening of info window * IDEMPIERE-4960 Performance improvement for the opening of info window Query.scroll and Query.list basically offer the same db performance, the previous change is unnecessary. --- .../src/org/adempiere/model/MInfoProcess.java | 16 ++- .../src/org/adempiere/model/MInfoRelated.java | 15 ++- .../src/org/compiere/model/GridWindow.java | 2 +- .../src/org/compiere/model/GridWindowVO.java | 123 ++++++++++-------- .../src/org/compiere/model/MInfoColumn.java | 17 ++- .../src/org/compiere/model/MInfoWindow.java | 74 +++++++++-- .../src/org/compiere/util/Env.java | 44 +------ .../webui/factory/DefaultInfoFactory.java | 2 +- .../org/adempiere/webui/info/InfoWindow.java | 2 +- .../adempiere/webui/panel/HelpController.java | 2 +- .../org/adempiere/webui/panel/InfoPanel.java | 26 +--- 11 files changed, 182 insertions(+), 141 deletions(-) diff --git a/org.adempiere.base/src/org/adempiere/model/MInfoProcess.java b/org.adempiere.base/src/org/adempiere/model/MInfoProcess.java index 30a89218e1..9b0be4c70c 100644 --- a/org.adempiere.base/src/org/adempiere/model/MInfoProcess.java +++ b/org.adempiere.base/src/org/adempiere/model/MInfoProcess.java @@ -23,6 +23,7 @@ import org.compiere.model.X_AD_InfoProcess; import org.compiere.util.Env; import org.compiere.util.Evaluatee; import org.compiere.util.Evaluator; +import org.idempiere.cache.ImmutablePOSupport; /** * Contain info of process in info window @@ -30,11 +31,12 @@ import org.compiere.util.Evaluator; * @author hieplq * */ -public class MInfoProcess extends X_AD_InfoProcess implements IInfoColumn { +public class MInfoProcess extends X_AD_InfoProcess implements IInfoColumn, ImmutablePOSupport { + /** * */ - private static final long serialVersionUID = -5586972894900686397L; + private static final long serialVersionUID = 7833442401205258074L; /** * {@inheritDoc} @@ -115,5 +117,15 @@ public class MInfoProcess extends X_AD_InfoProcess implements IInfoColumn { public MInfoColumn getAD_InfoColumn (){ return (MInfoColumn)super.getAD_InfoColumn(); } + + @Override + public MInfoProcess markImmutable() { + if (is_Immutable()) + return this; + + makeImmutable(); + + return this; + } } diff --git a/org.adempiere.base/src/org/adempiere/model/MInfoRelated.java b/org.adempiere.base/src/org/adempiere/model/MInfoRelated.java index 149efce5fb..73663160d4 100644 --- a/org.adempiere.base/src/org/adempiere/model/MInfoRelated.java +++ b/org.adempiere.base/src/org/adempiere/model/MInfoRelated.java @@ -21,12 +21,13 @@ import org.compiere.model.MInfoColumn; import org.compiere.model.Query; import org.compiere.model.X_AD_InfoRelated; import org.compiere.util.Env; +import org.idempiere.cache.ImmutablePOSupport; -public class MInfoRelated extends X_AD_InfoRelated implements IInfoColumn { +public class MInfoRelated extends X_AD_InfoRelated implements IInfoColumn, ImmutablePOSupport { /** * */ - private static final long serialVersionUID = -6216174103510277333L; + private static final long serialVersionUID = 4000783886138460291L; public MInfoRelated(Properties ctx, int AD_InfoRelated_ID, String trxName) { super(ctx, AD_InfoRelated_ID, trxName); @@ -78,5 +79,15 @@ public class MInfoRelated extends X_AD_InfoRelated implements IInfoColumn { public MInfoColumn getAD_InfoColumn (){ return (MInfoColumn) getParentRelatedColumn(); } + + @Override + public MInfoRelated markImmutable() { + if (is_Immutable()) + return this; + + makeImmutable(); + + return this; + } } diff --git a/org.adempiere.base/src/org/compiere/model/GridWindow.java b/org.adempiere.base/src/org/compiere/model/GridWindow.java index 2c569a8702..872a06d2a4 100644 --- a/org.adempiere.base/src/org/compiere/model/GridWindow.java +++ b/org.adempiere.base/src/org/compiere/model/GridWindow.java @@ -83,7 +83,7 @@ public class GridWindow implements Serializable public static GridWindow get (Properties ctx, int WindowNo, int AD_Window_ID, boolean virtual) { if (log.isLoggable(Level.CONFIG)) log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID); - GridWindowVO mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID); + GridWindowVO mWindowVO = GridWindowVO.get (AD_Window_ID, WindowNo); if (mWindowVO == null) return null; return new GridWindow(mWindowVO, virtual); diff --git a/org.adempiere.base/src/org/compiere/model/GridWindowVO.java b/org.adempiere.base/src/org/compiere/model/GridWindowVO.java index 473c7c0cee..43bbe61a8f 100644 --- a/org.adempiere.base/src/org/compiere/model/GridWindowVO.java +++ b/org.adempiere.base/src/org/compiere/model/GridWindowVO.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Properties; import java.util.logging.Level; +import org.compiere.util.CCache; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; @@ -40,7 +41,51 @@ public class GridWindowVO implements Serializable * */ private static final long serialVersionUID = 6884332743173214735L; + + private static final CLogger log = CLogger.getCLogger(GridWindowVO.class); + /** Window Cache */ + private static CCache s_windowsvo + = new CCache(I_AD_Window.Table_Name, I_AD_Window.Table_Name+"|GridWindowVO", 10); + + /** + * + * @param AD_Window_ID + * @param windowNo + * @return {@link GridWindowVO} + */ + public static GridWindowVO get(int AD_Window_ID, int windowNo) + { + return get(AD_Window_ID, windowNo, -1); + } + + /** + * + * @param AD_Window_ID + * @param windowNo + * @param AD_Menu_ID + * @return {@link GridWindowVO} + */ + public static GridWindowVO get(int AD_Window_ID, int windowNo, int AD_Menu_ID) + { + GridWindowVO mWindowVO = s_windowsvo.get(AD_Window_ID); + if (mWindowVO != null) + { + mWindowVO = mWindowVO.clone(windowNo); + if (log.isLoggable(Level.INFO)) log.info("Cached=" + mWindowVO); + } + if (mWindowVO == null) + { + if (log.isLoggable(Level.CONFIG)) log.config("create local"); + mWindowVO = GridWindowVO.create (Env.getCtx(), windowNo, AD_Window_ID, AD_Menu_ID); + if (mWindowVO != null) + { + s_windowsvo.put(AD_Window_ID, mWindowVO); + } + } + return mWindowVO; + } + /** * Create Window Value Object * @param WindowNo window no for ctx @@ -120,60 +165,34 @@ public class GridWindowVO implements Serializable // -- Get Window - StringBuilder sql = new StringBuilder("SELECT Name,Description,Help,WindowType, " - + "AD_Color_ID,AD_Image_ID,WinHeight,WinWidth, " - + "IsSOTrx, AD_Window_UU "); - - if (Env.isBaseLanguage(vo.ctx, "AD_Window")) - sql.append("FROM AD_Window w WHERE w.AD_Window_ID=? AND w.IsActive='Y'"); + MWindow window = MWindow.get(AD_Window_ID); + boolean base = Env.isBaseLanguage(vo.ctx, "AD_Window"); + if (window != null) + { + vo.Name = base ? window.getName() : window.get_Translation(MWindow.COLUMNNAME_Name); + vo.Description = base ? window.getDescription() : window.get_Translation(MWindow.COLUMNNAME_Description); + if (vo.Description == null) + vo.Description = ""; + vo.Help = base ? window.getHelp() : window.get_Translation(MWindow.COLUMNNAME_Help); + if (vo.Help == null) + vo.Help = ""; + vo.WindowType = window.getWindowType(); + // + vo.AD_Color_ID = window.getAD_Color_ID(); + vo.AD_Image_ID = window.getAD_Image_ID(); + //vo.IsReadWrite = rs.getString(7); + // + vo.WinHeight = window.getWinHeight(); + vo.WinWidth = window.getWinWidth(); + // + vo.IsSOTrx = window.isSOTrx(); + vo.AD_Window_UU = window.getAD_Window_UU(); + } else - sql.append("FROM AD_Window_vt w WHERE w.AD_Window_ID=?") - .append(" AND AD_Language='") - .append(Env.getAD_Language(vo.ctx)).append("'"); - - PreparedStatement pstmt = null; - ResultSet rs = null; - try { - // create statement - pstmt = DB.prepareStatement(sql.toString(), null); - pstmt.setInt(1, vo.AD_Window_ID); - // get data - rs = pstmt.executeQuery(); - if (rs.next()) - { - vo.Name = rs.getString(1); - vo.Description = rs.getString(2); - if (vo.Description == null) - vo.Description = ""; - vo.Help = rs.getString(3); - if (vo.Help == null) - vo.Help = ""; - vo.WindowType = rs.getString(4); - // - vo.AD_Color_ID = rs.getInt(5); - vo.AD_Image_ID = rs.getInt(6); - //vo.IsReadWrite = rs.getString(7); - // - vo.WinHeight = rs.getInt(7); - vo.WinWidth = rs.getInt(8); - // - vo.IsSOTrx = "Y".equals(rs.getString(9)); - vo.AD_Window_UU = rs.getString(10); - } - else - vo = null; - } - catch (SQLException ex) - { - CLogger.get().log(Level.SEVERE, sql.toString(), ex); - return null; - } - finally - { - DB.close(rs, pstmt); - rs = null; pstmt = null; + vo = null; } + // Ensure ASP exceptions MRole role = MRole.getDefault(ctx, false); final Boolean windowAccess = vo!=null ? role.getWindowAccess(vo.AD_Window_ID) : null; @@ -184,7 +203,7 @@ public class GridWindowVO implements Serializable if (vo == null) { CLogger.get().log(Level.SEVERE, "No Window - AD_Window_ID=" + AD_Window_ID - + ", AD_Role_ID=" + role + " - " + sql); + + ", AD_Role_ID=" + role); CLogger.get().saveError("AccessTableNoView", "(Not found)"); return null; } diff --git a/org.adempiere.base/src/org/compiere/model/MInfoColumn.java b/org.adempiere.base/src/org/compiere/model/MInfoColumn.java index 376246ed58..82147d4fc4 100644 --- a/org.adempiere.base/src/org/compiere/model/MInfoColumn.java +++ b/org.adempiere.base/src/org/compiere/model/MInfoColumn.java @@ -29,6 +29,7 @@ import org.compiere.util.Evaluatee; import org.compiere.util.Evaluator; import org.compiere.util.Msg; import org.compiere.util.Util; +import org.idempiere.cache.ImmutablePOSupport; /** * Info Window Column Model @@ -36,12 +37,12 @@ import org.compiere.util.Util; * @author Jorg Janke * @version $Id: MInfoColumn.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ */ -public class MInfoColumn extends X_AD_InfoColumn implements IInfoColumn +public class MInfoColumn extends X_AD_InfoColumn implements IInfoColumn, ImmutablePOSupport { /** * */ - private static final long serialVersionUID = -6313260451237775302L; + private static final long serialVersionUID = 3909164419255524834L; /** * Stanfard Constructor @@ -226,4 +227,16 @@ public class MInfoColumn extends X_AD_InfoColumn implements IInfoColumn public I_AD_Val_Rule getAD_Val_Rule() throws RuntimeException { return MValRule.getCopy(getCtx(), getAD_Val_Rule_ID(), get_TrxName()); } + + @Override + public PO markImmutable() { + if (is_Immutable()) + return this; + + makeImmutable(); + if (m_parent != null && !m_parent.is_Immutable()) + m_parent.markImmutable(); + + return this; + } } // MInfoColumn diff --git a/org.adempiere.base/src/org/compiere/model/MInfoWindow.java b/org.adempiere.base/src/org/compiere/model/MInfoWindow.java index 74d4f14732..6c705129a9 100644 --- a/org.adempiere.base/src/org/compiere/model/MInfoWindow.java +++ b/org.adempiere.base/src/org/compiere/model/MInfoWindow.java @@ -33,6 +33,9 @@ import org.compiere.model.AccessSqlParser.TableInfo; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Msg; +import org.compiere.util.Util; +import org.idempiere.cache.ImmutableIntPOCache; +import org.idempiere.cache.ImmutablePOSupport; /** * Info Window Model @@ -40,13 +43,16 @@ import org.compiere.util.Msg; * @author Jorg Janke * @version $Id: MInfoWindow.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $ */ -public class MInfoWindow extends X_AD_InfoWindow +public class MInfoWindow extends X_AD_InfoWindow implements ImmutablePOSupport { /** * */ - private static final long serialVersionUID = -1619434756919905441L; + private static final long serialVersionUID = 6723480469706009814L; + /** Cache */ + private static ImmutableIntPOCache s_cache = new ImmutableIntPOCache(Table_Name, 20); + /** * Standard Constructor * @param ctx context @@ -75,7 +81,16 @@ public class MInfoWindow extends X_AD_InfoWindow */ public MInfoWindow(MInfoWindow copy) { - this(Env.getCtx(), 0, (String)null); + this(copy, (String) null); + } + + /** + * Copy constructor + * @param copy + */ + public MInfoWindow(MInfoWindow copy, String trxName) + { + this(Env.getCtx(), 0, trxName); copyPO(copy); this.m_validateEachColumn = copy.m_validateEachColumn; this.m_infocolumns = copy.m_infocolumns != null ? Arrays.stream(copy.m_infocolumns).map(MInfoColumn::new).toArray(MInfoColumn[]::new) : null; @@ -105,18 +120,23 @@ public class MInfoWindow extends X_AD_InfoWindow /** * @author xolali * @param AD_InfoWindow_ID - * @return + * @return {@link MInfoWindow} */ public static MInfoWindow getInfoWindow(int AD_InfoWindow_ID) { - - if (AD_InfoWindow_ID != 0) { - - MInfoWindow infoWin = (MInfoWindow)new Query(Env.getCtx(), Table_Name, "AD_InfoWindow_ID=?", null) + if (AD_InfoWindow_ID > 0) { + Integer key = Integer.valueOf(AD_InfoWindow_ID); + MInfoWindow infoWin = s_cache.get(key); + if (infoWin != null) + return infoWin; + + infoWin = (MInfoWindow)new Query(Env.getCtx(), Table_Name, "AD_InfoWindow_ID=?", null) .setParameters(AD_InfoWindow_ID) .first(); - if (infoWin != null) + if (infoWin != null) { + s_cache.put(key, infoWin); return infoWin; + } } return null; @@ -195,12 +215,19 @@ public class MInfoWindow extends X_AD_InfoWindow } - /** return true if the current role can access to the specified info window ; otherwise return null */ + /** + * @param infoWindowID + * @param trxName + * return MInfoWindow if the current role can access to the specified info window ; otherwise return null + * */ public static MInfoWindow get(int infoWindowID, String trxName) { - MInfoWindow iw = new MInfoWindow(Env.getCtx(), infoWindowID, null); + MInfoWindow iw = getInfoWindow(infoWindowID); Boolean access = MRole.getDefault().getInfoAccess(iw.getAD_InfoWindow_ID()); - if (access != null && access.booleanValue()) + if (access != null && access.booleanValue()) { + if (!Util.isEmpty(trxName, true)) + iw = new MInfoWindow(iw, trxName); return iw; + } return null; } @@ -471,6 +498,25 @@ public class MInfoWindow extends X_AD_InfoWindow boolean isValidateEachColumn() { return m_validateEachColumn; } - - + + @Override + public MInfoWindow markImmutable() { + if (is_Immutable()) + return this; + + makeImmutable(); + if (m_infocolumns != null && m_infocolumns.length > 0) + Arrays.stream(m_infocolumns).forEach(e -> e.markImmutable()); + if (m_infoProcess != null && m_infoProcess.length > 0) + Arrays.stream(m_infoProcess).forEach(e -> e.markImmutable()); + if (m_infoRelated != null && m_infoRelated.length > 0) + Arrays.stream(m_infoRelated).forEach(e -> e.markImmutable()); + + return this; + } + + @Override + public I_AD_Table getAD_Table() throws RuntimeException { + return MTable.get(Env.getCtx(), getAD_Table_ID(), get_TrxName()); + } } // MInfoWindow diff --git a/org.adempiere.base/src/org/compiere/util/Env.java b/org.adempiere.base/src/org/compiere/util/Env.java index 7e6b2eec42..86fdceedb0 100644 --- a/org.adempiere.base/src/org/compiere/util/Env.java +++ b/org.adempiere.base/src/org/compiere/util/Env.java @@ -29,7 +29,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -47,7 +46,6 @@ import org.adempiere.util.ServerContextProvider; import org.compiere.Adempiere; import org.compiere.db.CConnection; import org.compiere.model.GridWindowVO; -import org.compiere.model.I_AD_Window; import org.compiere.model.MClient; import org.compiere.model.MColumn; import org.compiere.model.MLookupCache; @@ -1922,10 +1920,6 @@ public final class Env return p; } - /** Window Cache */ - private static CCache s_windowsvo - = new CCache(I_AD_Window.Table_Name, I_AD_Window.Table_Name+"|GridWindowVO", 10); - /** * Get Window Model * @@ -1937,46 +1931,10 @@ public final class Env public static GridWindowVO getMWindowVO (int WindowNo, int AD_Window_ID, int AD_Menu_ID) { if (log.isLoggable(Level.CONFIG)) log.config("Window=" + WindowNo + ", AD_Window_ID=" + AD_Window_ID); - GridWindowVO mWindowVO = null; - if (AD_Window_ID != 0 && Ini.isCacheWindow()) // try cache - { - mWindowVO = s_windowsvo.get(AD_Window_ID); - if (mWindowVO != null) - { - mWindowVO = mWindowVO.clone(WindowNo); - if (log.isLoggable(Level.INFO)) log.info("Cached=" + mWindowVO); - } - } - - // Create Window Model on Client - if (mWindowVO == null) - { - if (log.isLoggable(Level.CONFIG)) log.config("create local"); - mWindowVO = GridWindowVO.create (Env.getCtx(), WindowNo, AD_Window_ID, AD_Menu_ID); - if (mWindowVO != null) - s_windowsvo.put(AD_Window_ID, mWindowVO); - } // from Client + GridWindowVO mWindowVO = GridWindowVO.get(AD_Window_ID, WindowNo, AD_Menu_ID); if (mWindowVO == null) return null; - // Check (remote) context - if (!mWindowVO.ctx.equals(Env.getCtx())) - { - // Remote Context is called by value, not reference - // Add Window properties to context - Enumeration keyEnum = mWindowVO.ctx.keys(); - while (keyEnum.hasMoreElements()) - { - String key = (String)keyEnum.nextElement(); - if (key.startsWith(WindowNo+"|")) - { - String value = mWindowVO.ctx.getProperty (key); - Env.setContext(Env.getCtx(), key, value); - } - } - // Sync Context - mWindowVO.setCtx(Env.getCtx()); - } return mWindowVO; } // getWindow diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultInfoFactory.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultInfoFactory.java index 971c8d787a..28b9347e45 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultInfoFactory.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultInfoFactory.java @@ -189,7 +189,7 @@ public class DefaultInfoFactory implements IInfoFactory { @Override public InfoWindow create(int AD_InfoWindow_ID, String predefinedContextVariables) { - MInfoWindow infoWindow = new MInfoWindow(Env.getCtx(), AD_InfoWindow_ID, (String)null); + MInfoWindow infoWindow = MInfoWindow.getInfoWindow(AD_InfoWindow_ID); String tableName = infoWindow.getAD_Table().getTableName(); String keyColumn = tableName + "_ID"; InfoPanel info = create(-1, tableName, keyColumn, null, false, null, AD_InfoWindow_ID, false, predefinedContextVariables); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java index 8c9a22edd7..926040c902 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java @@ -584,7 +584,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL @Override protected void loadInfoWindowData (){ if (m_infoWindowID > 0) { - infoWindow = new MInfoWindow(Env.getCtx(), m_infoWindowID, null); + infoWindow = MInfoWindow.getInfoWindow(m_infoWindowID); }else { infoWindow = MInfoWindow.get(p_tableName, (String)null); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/HelpController.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/HelpController.java index fa64027c88..fd184433d1 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/HelpController.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/HelpController.java @@ -427,7 +427,7 @@ public class HelpController } else if (ctxType.equals(X_AD_CtxHelp.CTXTYPE_Info)) { - MInfoWindow info = new MInfoWindow(Env.getCtx(), recordId, null); + MInfoWindow info = MInfoWindow.getInfoWindow(recordId); // Load User Def MUserDefInfo userDef = MUserDefInfo.getBestMatch(Env.getCtx(), info.getAD_InfoWindow_ID()); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java index f1f027de76..e8d92abb4a 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java @@ -1943,29 +1943,11 @@ public abstract class InfoPanel extends Window implements EventListener, if (m_SO_Window_ID > 0) return m_SO_Window_ID; // - String sql = "SELECT AD_Window_ID, PO_Window_ID FROM AD_Table WHERE TableName=?"; - PreparedStatement pstmt = null; - ResultSet rs = null; - try + MTable table = MTable.get(Env.getCtx(), tableName); + if (table != null) { - pstmt = DB.prepareStatement(sql, null); - pstmt.setString(1, tableName); - rs = pstmt.executeQuery(); - if (rs.next()) - { - m_SO_Window_ID = rs.getInt(1); - m_PO_Window_ID = rs.getInt(2); - } - } - catch (Exception e) - { - log.log(Level.SEVERE, sql, e); - } - finally - { - DB.close(rs, pstmt); - rs = null; - pstmt = null; + m_SO_Window_ID = table.getAD_Window_ID(); + m_PO_Window_ID = table.getPO_Window_ID(); } // if (!isSOTrx && m_PO_Window_ID > 0)