Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java =================================================================== diff -u -r8aded0b18a5a7712622ae56f38923fa297449977 -rbe48a755dd63857599487663be908aa200adbaa6 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java (.../LearningWebUtil.java) (revision 8aded0b18a5a7712622ae56f38923fa297449977) +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java (.../LearningWebUtil.java) (revision be48a755dd63857599487663be908aa200adbaa6) @@ -50,7 +50,7 @@ import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; -import org.springframework.dao.CannotAcquireLockException; +import org.springframework.dao.DataAccessException; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; @@ -69,6 +69,8 @@ // --------------------------------------------------------------------- public static final String PARAM_PROGRESS_ID = "progressID"; + private static final int COMPLETE_ACTIVITY_MAX_ATTEMPTS = 3; + // public static final String POPUP_WINDOW_NAME = "LearnerActivity"; // public static final String LEARNER_WINDOW_NAME = "lWindow"; @@ -225,19 +227,7 @@ } else if (progress.getCompletedActivities().containsKey(currentActivity)) { return actionMappings.getCloseForward(currentActivity, lesson.getLessonId()); } else { - // Set activity as complete; synchronized and repeated because of deadlock exceptions - try { - progress = learnerService.completeActivity(learnerId, currentActivity, progress); - } catch (CannotAcquireLockException e) { - LearningWebUtil.log.warn("Can not acquire lock to complete activity " + currentActivity.getActivityId() - + " by learner " + learnerId + ". Retrying..."); - try { - Thread.sleep(2000); - } catch (InterruptedException e1) { - // do nothing, it does not hurt us... - } - progress = learnerService.completeActivity(learnerId, currentActivity, progress); - } + progress = LearningWebUtil.completeActivity(learnerService, learnerId, progress, currentActivity, 1); } if ((currentActivity != null) && currentActivity.isFloating()) { @@ -416,4 +406,30 @@ } return positionDTO; } + + /** + * Tries to complete the activity for the learner. Because of concurrency problems (deadlocks, indexes when + * inserting) the operation can fail and the easiet recovery is to repeat it. + */ + private static LearnerProgress completeActivity(ICoreLearnerService learnerService, Integer learnerId, + LearnerProgress progress, Activity currentActivity, int attempt) { + try { + progress = learnerService.completeActivity(learnerId, currentActivity, progress); + } catch (DataAccessException e) { + attempt++; + StringBuilder message = new StringBuilder("Could not complete activity due to a data access exception."); + if (attempt <= LearningWebUtil.COMPLETE_ACTIVITY_MAX_ATTEMPTS) { + message.append("Retrying. Attempt #").append(attempt).append(". The exception was: ") + .append(e.getMessage()); + LearningWebUtil.log.warn(message.toString()); + LearningWebUtil.completeActivity(learnerService, learnerId, progress, currentActivity, attempt); + } else { + message.append("Reached limit of retries: " + LearningWebUtil.COMPLETE_ACTIVITY_MAX_ATTEMPTS); + LearningWebUtil.log.warn(message.toString()); + throw e; + } + } + + return progress; + } } \ No newline at end of file