diff --git a/api/src/org/labkey/api/data/DbScope.java b/api/src/org/labkey/api/data/DbScope.java index 2166b10ab93..f285639b652 100644 --- a/api/src/org/labkey/api/data/DbScope.java +++ b/api/src/org/labkey/api/data/DbScope.java @@ -45,6 +45,7 @@ import org.labkey.api.util.GUID; import org.labkey.api.util.MemTracker; import org.labkey.api.util.TestContext; +import org.labkey.api.util.UnexpectedException; import org.labkey.data.xml.TablesDocument; import org.springframework.dao.DeadlockLoserDataAccessException; @@ -636,6 +637,11 @@ public void rethrow(Class clazz) throws T if (clazz.isAssignableFrom(getCause().getClass())) throw (T)getCause(); } + + public void throwRuntimeException() throws RuntimeException + { + throw UnexpectedException.wrap(getCause()); + } } /** Won't retry if we're already in a transaction diff --git a/query/src/org/labkey/query/controllers/QueryController.java b/query/src/org/labkey/query/controllers/QueryController.java index c1edbe070ce..0c752768459 100644 --- a/query/src/org/labkey/query/controllers/QueryController.java +++ b/query/src/org/labkey/query/controllers/QueryController.java @@ -2375,33 +2375,44 @@ public boolean handlePost(QueryForm form, BindException errors) throws Exception } DbSchema dbSchema = table.getSchema(); - dbSchema.getScope().executeWithRetry(tx -> + try { - try - { - updateService.deleteRows(getUser(), getContainer(), keyValues, null, null); - } - catch (SQLException x) - { - if (!RuntimeSQLException.isConstraintException(x)) - throw new RuntimeSQLException(x); - errors.reject(ERROR_MSG, getMessage(table.getSchema().getSqlDialect(), x)); - } - catch (DataIntegrityViolationException | OptimisticConflictException e) + dbSchema.getScope().executeWithRetry(tx -> { - errors.reject(ERROR_MSG, e.getMessage()); - } - catch (BatchValidationException x) - { - x.addToErrors(errors); - } - catch (Exception x) - { - errors.reject(ERROR_MSG, null == x.getMessage() ? x.toString() : x.getMessage()); - ExceptionUtil.logExceptionToMothership(getViewContext().getRequest(), x); - } - return !errors.hasErrors(); - }); + try + { + updateService.deleteRows(getUser(), getContainer(), keyValues, null, null); + } + catch (SQLException x) + { + if (!RuntimeSQLException.isConstraintException(x)) + throw new RuntimeSQLException(x); + errors.reject(ERROR_MSG, getMessage(table.getSchema().getSqlDialect(), x)); + } + catch (DataIntegrityViolationException | OptimisticConflictException e) + { + errors.reject(ERROR_MSG, e.getMessage()); + } + catch (BatchValidationException x) + { + x.addToErrors(errors); + } + catch (Exception x) + { + errors.reject(ERROR_MSG, null == x.getMessage() ? x.toString() : x.getMessage()); + ExceptionUtil.logExceptionToMothership(getViewContext().getRequest(), x); + } + // need to throw here to avoid committing tx + if (errors.hasErrors()) + throw new DbScope.RetryException(errors); + return true; + }); + } + catch (DbScope.RetryException x) + { + if (x.getCause() != errors) + x.throwRuntimeException(); + } return !errors.hasErrors(); }