IDEMPIERE-4653 Improve timeout handling of window tab (#534)
* IDEMPIERE-4653 Improve timeout handling of window tab * IDEMPIERE-4653 Improve timeout handling of window tab Fix error with find and refresh.
This commit is contained in:
parent
cdb21c0698
commit
e1ba21360f
|
@ -0,0 +1,10 @@
|
||||||
|
SET SQLBLANKLINES ON
|
||||||
|
SET DEFINE OFF
|
||||||
|
|
||||||
|
-- Jan 19, 2021, 1:34:10 PM MYT
|
||||||
|
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The window tab took too long to return results.',0,0,'Y',TO_DATE('2021-01-19 13:34:09','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2021-01-19 13:34:09','YYYY-MM-DD HH24:MI:SS'),100,200659,'GridTabLoadTimeoutError','D','f016a5f8-3783-4640-b713-8f0e1b4d3bb6')
|
||||||
|
;
|
||||||
|
|
||||||
|
SELECT register_migration_script('202101190630_IDEMPIERE-4653.sql') FROM dual
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
-- Jan 19, 2021, 1:34:10 PM MYT
|
||||||
|
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The window tab took too long to return results.',0,0,'Y',TO_TIMESTAMP('2021-01-19 13:34:09','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2021-01-19 13:34:09','YYYY-MM-DD HH24:MI:SS'),100,200659,'GridTabLoadTimeoutError','D','f016a5f8-3783-4640-b713-8f0e1b4d3bb6')
|
||||||
|
;
|
||||||
|
|
||||||
|
SELECT register_migration_script('202101190630_IDEMPIERE-4653.sql') FROM dual
|
||||||
|
;
|
||||||
|
|
|
@ -199,9 +199,18 @@ public class DBException extends AdempiereException
|
||||||
* @param e
|
* @param e
|
||||||
*/
|
*/
|
||||||
public static boolean isTimeout(Exception e) {
|
public static boolean isTimeout(Exception e) {
|
||||||
if (DB.isPostgreSQL())
|
SQLException se = null;
|
||||||
return isSQLState(e, "57014");
|
if (e instanceof SQLException) {
|
||||||
return isErrorCode(e, 1013);
|
se = (SQLException) e;
|
||||||
|
} else if (e.getCause() != null && e.getCause() instanceof SQLException) {
|
||||||
|
se = (SQLException) e.getCause();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (se != null) {
|
||||||
|
return DB.getDatabase().isQueryTimeout(se);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 8443012394354164942L;
|
private static final long serialVersionUID = 5086068543834849233L;
|
||||||
|
|
||||||
public static final String DEFAULT_STATUS_MESSAGE = "NavigateOrUpdate";
|
public static final String DEFAULT_STATUS_MESSAGE = "NavigateOrUpdate";
|
||||||
|
|
||||||
|
@ -3469,4 +3469,12 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
||||||
return max > 0 && noRecords > max;
|
return max > 0 && noRecords > max;
|
||||||
} // isQueryMax
|
} // isQueryMax
|
||||||
|
|
||||||
|
/***
|
||||||
|
* reset to empty
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
m_mTable.reset();
|
||||||
|
setCurrentRow(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
} // GridTab
|
} // GridTab
|
||||||
|
|
|
@ -49,7 +49,6 @@ import java.util.logging.Level;
|
||||||
import javax.swing.event.TableModelListener;
|
import javax.swing.event.TableModelListener;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
|
||||||
import org.adempiere.exceptions.DBException;
|
import org.adempiere.exceptions.DBException;
|
||||||
import org.adempiere.util.ServerContext;
|
import org.adempiere.util.ServerContext;
|
||||||
import org.compiere.Adempiere;
|
import org.compiere.Adempiere;
|
||||||
|
@ -104,7 +103,11 @@ public class GridTable extends AbstractTableModel
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -3190218965990521698L;
|
private static final long serialVersionUID = -1869219003783467319L;
|
||||||
|
|
||||||
|
public static final int DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = 30;
|
||||||
|
|
||||||
|
public static final String LOAD_TIMEOUT_ERROR_MESSAGE = "GridTabLoadTimeoutError";
|
||||||
|
|
||||||
public static final String DATA_REFRESH_MESSAGE = "Refreshed";
|
public static final String DATA_REFRESH_MESSAGE = "Refreshed";
|
||||||
public static final String DATA_UPDATE_COPIED_MESSAGE = "UpdateCopied";
|
public static final String DATA_UPDATE_COPIED_MESSAGE = "UpdateCopied";
|
||||||
|
@ -1087,7 +1090,7 @@ public class GridTable extends AbstractTableModel
|
||||||
// need to wait for data read into buffer
|
// need to wait for data read into buffer
|
||||||
int loops = 0;
|
int loops = 0;
|
||||||
//wait for [timeout] seconds
|
//wait for [timeout] seconds
|
||||||
int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, 30, Env.getAD_Client_ID(Env.getCtx()));
|
int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
while (row >= m_sort.size() && m_loaderFuture != null && !m_loaderFuture.isDone() && loops < timeout)
|
while (row >= m_sort.size() && m_loaderFuture != null && !m_loaderFuture.isDone() && loops < timeout)
|
||||||
{
|
{
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("Waiting for loader row=" + row + ", size=" + m_sort.size());
|
if (log.isLoggable(Level.FINE)) log.fine("Waiting for loader row=" + row + ", size=" + m_sort.size());
|
||||||
|
@ -1107,7 +1110,9 @@ public class GridTable extends AbstractTableModel
|
||||||
}
|
}
|
||||||
if (row >= m_sort.size()) {
|
if (row >= m_sort.size()) {
|
||||||
log.warning("Reached " + timeout + " seconds timeout loading row " + (row+1) + " for SQL=" + m_SQL);
|
log.warning("Reached " + timeout + " seconds timeout loading row " + (row+1) + " for SQL=" + m_SQL);
|
||||||
throw new IllegalStateException("Timeout loading row " + (row+1));
|
//adjust row count
|
||||||
|
m_rowCount = m_sort.size();
|
||||||
|
throw new DBException("GridTabLoadTimeoutError");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3550,18 +3555,16 @@ public class GridTable extends AbstractTableModel
|
||||||
{
|
{
|
||||||
pstmt = DB.prepareStatement(m_SQL_Count, null);
|
pstmt = DB.prepareStatement(m_SQL_Count, null);
|
||||||
setParameter (pstmt, true);
|
setParameter (pstmt, true);
|
||||||
|
int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
|
if (timeout > 0)
|
||||||
|
pstmt.setQueryTimeout(timeout);
|
||||||
rs = pstmt.executeQuery();
|
rs = pstmt.executeQuery();
|
||||||
if (rs.next())
|
if (rs.next())
|
||||||
rows = rs.getInt(1);
|
rows = rs.getInt(1);
|
||||||
}
|
}
|
||||||
catch (SQLException e0)
|
catch (SQLException e0)
|
||||||
{
|
{
|
||||||
// Zoom Query may have invalid where clause
|
throw new DBException(e0);
|
||||||
if (DBException.isInvalidIdentifierError(e0))
|
|
||||||
log.warning("Count - " + e0.getLocalizedMessage() + "\nSQL=" + m_SQL_Count);
|
|
||||||
else
|
|
||||||
throw new AdempiereException(e0);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -3602,6 +3605,9 @@ public class GridTable extends AbstractTableModel
|
||||||
if (m_virtual)
|
if (m_virtual)
|
||||||
m_pstmt.setFetchSize(100);
|
m_pstmt.setFetchSize(100);
|
||||||
setParameter (m_pstmt, false);
|
setParameter (m_pstmt, false);
|
||||||
|
int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
|
if (timeout > 0)
|
||||||
|
m_pstmt.setQueryTimeout(timeout);
|
||||||
m_rs = m_pstmt.executeQuery();
|
m_rs = m_pstmt.executeQuery();
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
|
@ -4042,4 +4048,25 @@ public class GridTable extends AbstractTableModel
|
||||||
{
|
{
|
||||||
return m_rowChanged;
|
return m_rowChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset to empty
|
||||||
|
*/
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
if (m_buffer != null)
|
||||||
|
m_buffer.clear();
|
||||||
|
m_changed = false;
|
||||||
|
m_rowChanged = -1;
|
||||||
|
if (m_sort != null)
|
||||||
|
m_sort.clear();
|
||||||
|
if (m_virtualBuffer != null)
|
||||||
|
m_virtualBuffer.clear();
|
||||||
|
m_rowCount = 0;
|
||||||
|
m_rowData = null;
|
||||||
|
m_oldValue = null;
|
||||||
|
m_inserting = false;
|
||||||
|
m_lastSortColumnIndex = -1;
|
||||||
|
m_lastSortedAscending = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.logging.Level;
|
||||||
|
|
||||||
import org.adempiere.base.Core;
|
import org.adempiere.base.Core;
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.adempiere.exceptions.DBException;
|
||||||
import org.adempiere.util.Callback;
|
import org.adempiere.util.Callback;
|
||||||
import org.adempiere.webui.AdempiereIdGenerator;
|
import org.adempiere.webui.AdempiereIdGenerator;
|
||||||
import org.adempiere.webui.AdempiereWebUI;
|
import org.adempiere.webui.AdempiereWebUI;
|
||||||
|
@ -1161,10 +1162,24 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
|
||||||
public void query (boolean onlyCurrentRows, int onlyCurrentDays, int maxRows)
|
public void query (boolean onlyCurrentRows, int onlyCurrentDays, int maxRows)
|
||||||
{
|
{
|
||||||
boolean open = gridTab.isOpen();
|
boolean open = gridTab.isOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
gridTab.query(onlyCurrentRows, onlyCurrentDays, maxRows);
|
gridTab.query(onlyCurrentRows, onlyCurrentDays, maxRows);
|
||||||
if (listPanel.isVisible() && !open)
|
if (listPanel.isVisible() && !open)
|
||||||
gridTab.getTableModel().fireTableDataChanged();
|
gridTab.getTableModel().fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (DBException.isTimeout(e))
|
||||||
|
{
|
||||||
|
FDialog.error(windowNo, GridTable.LOAD_TIMEOUT_ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FDialog.error(windowNo, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reset detail data grid for new parent record that's not saved yet
|
* reset detail data grid for new parent record that's not saved yet
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Properties;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.DBException;
|
||||||
import org.adempiere.util.Callback;
|
import org.adempiere.util.Callback;
|
||||||
import org.adempiere.webui.AdempiereIdGenerator;
|
import org.adempiere.webui.AdempiereIdGenerator;
|
||||||
import org.adempiere.webui.AdempiereWebUI;
|
import org.adempiere.webui.AdempiereWebUI;
|
||||||
|
@ -1922,7 +1923,18 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
||||||
protected void doOnRefresh(final boolean fireEvent) {
|
protected void doOnRefresh(final boolean fireEvent) {
|
||||||
IADTabpanel headerTab = adTabbox.getSelectedTabpanel();
|
IADTabpanel headerTab = adTabbox.getSelectedTabpanel();
|
||||||
IADTabpanel detailTab = adTabbox.getSelectedDetailADTabpanel();
|
IADTabpanel detailTab = adTabbox.getSelectedDetailADTabpanel();
|
||||||
|
try {
|
||||||
adTabbox.getSelectedGridTab().dataRefreshAll(fireEvent, true);
|
adTabbox.getSelectedGridTab().dataRefreshAll(fireEvent, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (DBException.isTimeout(e)) {
|
||||||
|
FDialog.error(getWindowNo(), "GridTabLoadTimeoutError");
|
||||||
|
} else {
|
||||||
|
FDialog.error(getWindowNo(), "Error", e.getMessage());
|
||||||
|
}
|
||||||
|
adTabbox.getSelectedGridTab().reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
adTabbox.getSelectedGridTab().refreshParentTabs();
|
adTabbox.getSelectedGridTab().refreshParentTabs();
|
||||||
headerTab.dynamicDisplay(0);
|
headerTab.dynamicDisplay(0);
|
||||||
if (detailTab != null)
|
if (detailTab != null)
|
||||||
|
|
|
@ -80,6 +80,7 @@ import org.adempiere.webui.util.ZKUpdateUtil;
|
||||||
import org.compiere.model.GridField;
|
import org.compiere.model.GridField;
|
||||||
import org.compiere.model.GridFieldVO;
|
import org.compiere.model.GridFieldVO;
|
||||||
import org.compiere.model.GridTab;
|
import org.compiere.model.GridTab;
|
||||||
|
import org.compiere.model.GridTable;
|
||||||
import org.compiere.model.Lookup;
|
import org.compiere.model.Lookup;
|
||||||
import org.compiere.model.MColumn;
|
import org.compiere.model.MColumn;
|
||||||
import org.compiere.model.MLookup;
|
import org.compiere.model.MLookup;
|
||||||
|
@ -88,6 +89,7 @@ import org.compiere.model.MLookupInfo;
|
||||||
import org.compiere.model.MProduct;
|
import org.compiere.model.MProduct;
|
||||||
import org.compiere.model.MQuery;
|
import org.compiere.model.MQuery;
|
||||||
import org.compiere.model.MRole;
|
import org.compiere.model.MRole;
|
||||||
|
import org.compiere.model.MSysConfig;
|
||||||
import org.compiere.model.MTable;
|
import org.compiere.model.MTable;
|
||||||
import org.compiere.model.MUserQuery;
|
import org.compiere.model.MUserQuery;
|
||||||
import org.compiere.model.SystemIDs;
|
import org.compiere.model.SystemIDs;
|
||||||
|
@ -2471,21 +2473,32 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
||||||
if (log.isLoggable(Level.INFO))
|
if (log.isLoggable(Level.INFO))
|
||||||
Env.setContext(Env.getCtx(), m_targetWindowNo, TABNO, GridTab.CTX_FindSQL, finalSQL);
|
Env.setContext(Env.getCtx(), m_targetWindowNo, TABNO, GridTab.CTX_FindSQL, finalSQL);
|
||||||
|
|
||||||
// Execute Qusery
|
// Execute Query
|
||||||
|
int timeout = MSysConfig.getIntValue(MSysConfig.GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS,
|
||||||
|
GridTable.DEFAULT_GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS, Env.getAD_Client_ID(Env.getCtx()));
|
||||||
m_total = 999999;
|
m_total = 999999;
|
||||||
Statement stmt = null;
|
Statement stmt = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
stmt = DB.createStatement();
|
stmt = DB.createStatement();
|
||||||
|
if (timeout > 0)
|
||||||
|
stmt.setQueryTimeout(timeout);
|
||||||
rs = stmt.executeQuery(finalSQL);
|
rs = stmt.executeQuery(finalSQL);
|
||||||
if (rs.next())
|
if (rs.next())
|
||||||
m_total = rs.getInt(1);
|
m_total = rs.getInt(1);
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
if (DB.getDatabase().isQueryTimeout(e))
|
||||||
|
{
|
||||||
|
throw new DBException(Msg.getMsg(Env.getCtx(), GridTable.LOAD_TIMEOUT_ERROR_MESSAGE));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
throw new DBException(e);
|
throw new DBException(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DB.close(rs, stmt);
|
DB.close(rs, stmt);
|
||||||
|
|
Loading…
Reference in New Issue