From 2a3224ea4657584cbd871de1a617abf3229041da Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 17 Jun 2020 15:44:06 +0200 Subject: [PATCH] IDEMPIERE-4319 Cascade workflow activities (completing chained documents) exception problem (#122) Implemented a better approach: save the first workflow savepoint and rollback to that one in case of cascade activities --- .../src/org/compiere/util/Trx.java | 12 +++++++- .../src/org/compiere/wf/MWFActivity.java | 29 +++++++++++++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/util/Trx.java b/org.adempiere.base/src/org/compiere/util/Trx.java index ab2f85d437..573d4f5354 100644 --- a/org.adempiere.base/src/org/compiere/util/Trx.java +++ b/org.adempiere.base/src/org/compiere/util/Trx.java @@ -513,7 +513,17 @@ public class Trx return null; } } - + + private Savepoint m_lastWFSavepoint = null; + + public synchronized void setLastWFSavepoint(Savepoint savepoint) { + m_lastWFSavepoint = savepoint; + } + + public synchronized Savepoint getLastWFSavepoint() { + return m_lastWFSavepoint; + } + /** * Release Savepoint * @param savepoint diff --git a/org.adempiere.base/src/org/compiere/wf/MWFActivity.java b/org.adempiere.base/src/org/compiere/wf/MWFActivity.java index ef270b8955..d3c1b0eb2c 100644 --- a/org.adempiere.base/src/org/compiere/wf/MWFActivity.java +++ b/org.adempiere.base/src/org/compiere/wf/MWFActivity.java @@ -286,7 +286,13 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable if (log.isLoggable(Level.FINE)) log.fine(oldState + "->"+ WFState + ", Msg=" + getTextMsg()); super.setWFState (WFState); m_state = new StateEngine (getWFState()); - saveEx(); // closed in MWFProcess.checkActivities() + boolean valid = save(); + if (! valid) { + // the activity could not be updated, probably it was deleted by the rollback to savepoint + // so, set the ID to zero and save it again (insert) + setAD_WF_Activity_ID(0); + saveEx(); + } updateEventAudit(); // Inform Process @@ -336,7 +342,13 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable } else m_audit.setEventType(MWFEventAudit.EVENTTYPE_StateChanged); - m_audit.saveEx(); + boolean valid = m_audit.save(); + if (! valid) { + // the event audit could not be updated, probably it was deleted by the rollback to savepoint + // so, set the ID to zero and save it again (insert) + m_audit.setAD_WF_EventAudit_ID(0); + m_audit.saveEx(); + } } // updateEventAudit /** @@ -871,8 +883,15 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable // try { - if (!localTrx) - savepoint = trx.setSavepoint(null); + if (!localTrx) { + // when cascade workflows, avoid setting a savepoint for each workflow + // use the same first savepoint from the transaction + savepoint = trx.getLastWFSavepoint(); + if (savepoint == null) { + savepoint = trx.setSavepoint(null); + trx.setLastWFSavepoint(savepoint); + } + } if (!m_state.isValidAction(StateEngine.ACTION_Start)) { @@ -925,6 +944,7 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable try { trx.rollback(savepoint); + trx.setLastWFSavepoint(null); } catch (SQLException e1) {} } @@ -973,7 +993,6 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable if (contextLost) Env.getCtx().remove("#AD_Client_ID"); } - throw new AdempiereException(e); } finally {