Index: lams_learning/.classpath =================================================================== RCS file: /usr/local/cvsroot/lams_learning/.classpath,v diff -u -r1.6.6.3 -r1.6.6.4 --- lams_learning/.classpath 8 May 2009 04:21:34 -0000 1.6.6.3 +++ lams_learning/.classpath 3 Jul 2009 01:24:46 -0000 1.6.6.4 @@ -3,13 +3,11 @@ - - - - + + Index: lams_learning/conf/xdoclet/web-settings.xml =================================================================== RCS file: /usr/local/cvsroot/lams_learning/conf/xdoclet/web-settings.xml,v diff -u -r1.21 -r1.21.2.1 --- lams_learning/conf/xdoclet/web-settings.xml 26 Mar 2009 10:00:35 -0000 1.21 +++ lams_learning/conf/xdoclet/web-settings.xml 3 Jul 2009 01:24:45 -0000 1.21.2.1 @@ -8,13 +8,17 @@ learningMessageSource + + contextClass + org.jboss.spring.factory.VFSXmlWebApplicationContext + contextConfigLocation locatorFactorySelector - classpath*:/org/lamsfoundation/lams/**/beanRefContext.xml + classpath:/org/lamsfoundation/lams/beanRefContext.xml parentContextKey Index: lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml,v diff -u -r1.24.2.1 -r1.24.2.2 --- lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml 22 Apr 2009 06:39:05 -0000 1.24.2.1 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/learningApplicationContext.xml 3 Jul 2009 01:24:45 -0000 1.24.2.2 @@ -43,7 +43,7 @@ PROPAGATION_REQUIRED - PROPAGATION_REQUIRED + PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED @@ -53,7 +53,9 @@ PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED - PROPAGATION_REQUIRED + PROPAGATION_REQUIRED + PROPAGATION_REQUIRED + PROPAGATION_REQUIRED,readOnly Index: lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java,v diff -u -r1.96.4.3 -r1.96.4.4 --- lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java 1 May 2009 06:13:55 -0000 1.96.4.3 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/service/LearnerService.java 3 Jul 2009 01:24:45 -0000 1.96.4.4 @@ -77,7 +77,7 @@ import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.MessageService; -import org.springframework.dao.DeadlockLoserDataAccessException; +import org.springframework.dao.DataIntegrityViolationException; /** * This class is a facade over the Learning middle tier. @@ -114,9 +114,8 @@ } /** - * Creates a new instance of LearnerService. To be used by Spring, assuming - * the Spring will set up the progress engine via method injection. If you - * are creating the bean manually then use the other constructor. + * Creates a new instance of LearnerService. To be used by Spring, assuming the Spring will set up the progress + * engine via method injection. If you are creating the bean manually then use the other constructor. */ public LearnerService() { } @@ -225,8 +224,7 @@ } /** - * Get the lesson data for a particular lesson. In a DTO format suitable for - * sending to the client. + * Get the lesson data for a particular lesson. In a DTO format suitable for sending to the client. */ public LessonDTO getLessonData(Long lessonId) { Lesson lesson = getLesson(lessonId); @@ -235,21 +233,18 @@ /** *

- * Joins a User to a lesson as a learner. It could either be a new lesson or - * a lesson that has been started. + * Joins a User to a lesson as a learner. It could either be a new lesson or a lesson that has been started. *

* *

- * In terms of new lesson, a new learner progress would be initialized. Tool - * session for the next activity will be initialized if necessary. + * In terms of new lesson, a new learner progress would be initialized. Tool session for the next activity will be + * initialized if necessary. *

* *

- * In terms of an started lesson, the learner progress will be returned - * without calculation. Tool session will be initialized if necessary. Note - * that we won't initialize tool session for current activity because we - * assume tool session will always initialize before it becomes a current - * activity.

- * Create a lams tool session for learner against a tool activity. This will - * have concurrency issues interms of grouped tool session because it might - * be inserting some tool session that has already been inserted by other - * member in the group. If the unique_check is broken, we need to query the - * database to get the instance instead of inserting it. It should be done - * in the Spring rollback strategy. + * Create a lams tool session for learner against a tool activity. This will have concurrency issues interms of + * grouped tool session because it might be inserting some tool session that has already been inserted by other + * member in the group. If the unique_check is broken, we need to query the database to get the instance instead of + * inserting it. It should be done in the Spring rollback strategy. *

* - * Once lams tool session is inserted, we need to notify the tool to its own - * session. + * Once lams tool session is inserted, we need to notify the tool to its own session. * * @param toolActivity * @param learner @@ -978,7 +954,33 @@ private void createToolSessionFor(ToolActivity toolActivity, User learner, Lesson lesson) throws LamsToolServiceException, ToolException { // if the tool session already exists, createToolSession() will return null - ToolSession toolSession = lamsCoreToolService.createToolSession(learner, toolActivity, lesson); + ToolSession toolSession = null; + try { + toolSession = lamsCoreToolService.createToolSession(learner, toolActivity, lesson); + } catch (DataIntegrityViolationException e) { + LearnerService.log.warn("There was an attempt to create two tool sessions with the same name. Retrying...", + e); + /* + * LDEV-1533: Two users tried to create a tool session with the same name. One of them was successful, the + * other got an error. The second one will now retry. This might create a loop; on the other hand the second + * attempt should be successful, since either the existing session will be retrieved or a session with a new + * name will be created. + * + * This workaround can not be in LamsCoreToolService (initially it was). If the exception occurs, the + * transaction is unusable anymore and any further DB actions will throw an error. We need to restart the + * transaction on the higher level - here. + * + * This exception should never occur, as lamsCoreToolService.createToolSession is now synchronized. + * Nevertheless, it sometimes occurs, so additional security measures stay. + */ + try { + Thread.sleep(2000); + } catch (InterruptedException e1) { + // do nothing, it does not hurt us + } + + toolSession = lamsCoreToolService.createToolSession(learner, toolActivity, lesson); + } if (toolSession != null) { toolActivity.getToolSessions().add(toolSession); lamsCoreToolService.notifyToolsToCreateSession(toolSession, toolActivity); @@ -1004,8 +1006,7 @@ /** * @throws LearnerServiceException * @see org.lamsfoundation.lams.learning.service.ICoreLearnerService#determineBranch(org.lamsfoundation.lams.lesson.Lesson, - * org.lamsfoundation.lams.learningdesign.BranchingActivity, - * java.lang.Integer) + * org.lamsfoundation.lams.learningdesign.BranchingActivity, java.lang.Integer) */ public SequenceActivity determineBranch(Lesson lesson, BranchingActivity branchingActivity, Integer learnerId) throws LearnerServiceException { @@ -1034,10 +1035,9 @@ } /** - * Get all the conditions for this branching activity, ordered by order id. - * Go through each condition until we find one that passes and that is the - * required branch. If no conditions match, use the branch that is the - * "default" branch for this branching activity. + * Get all the conditions for this branching activity, ordered by order id. Go through each condition until we find + * one that passes and that is the required branch. If no conditions match, use the branch that is the "default" + * branch for this branching activity. */ private SequenceActivity determineToolBasedBranch(Lesson lesson, ToolBranchingActivity branchingActivity, User learner) { @@ -1169,8 +1169,7 @@ * gate to check * @param learner * learner who is knocking to the gate - * @return true if learner satisfied any of the conditions - * and is allowed to pass + * @return true if learner satisfied any of the conditions and is allowed to pass */ private boolean determineConditionGateStatus(GateActivity gate, User learner) { boolean shouldOpenGate = false; @@ -1230,13 +1229,11 @@ } /** - * Select a particular branch - we are in preview mode and the author has - * selected a particular activity. + * Select a particular branch - we are in preview mode and the author has selected a particular activity. * * @throws LearnerServiceException * @see org.lamsfoundation.lams.learning.service.ICoreLearnerService#determineBranch(org.lamsfoundation.lams.lesson.Lesson, - * org.lamsfoundation.lams.learningdesign.BranchingActivity, - * java.lang.Integer) + * org.lamsfoundation.lams.learningdesign.BranchingActivity, java.lang.Integer) */ public SequenceActivity selectBranch(Lesson lesson, BranchingActivity branchingActivity, Integer learnerId, Long branchId) throws LearnerServiceException { Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java,v diff -u -r1.43 -r1.43.4.1 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java 15 Jan 2009 07:54:29 -0000 1.43 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/action/LearnerAction.java 3 Jul 2009 01:24:45 -0000 1.43.4.1 @@ -21,12 +21,11 @@ * **************************************************************** */ -/* $$Id$$ */ +/* $$Id$$ */ package org.lamsfoundation.lams.learning.web.action; import java.io.IOException; import java.io.PrintWriter; -import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -38,7 +37,6 @@ import org.apache.struts.action.ActionMapping; import org.lamsfoundation.lams.learning.service.ICoreLearnerService; import org.lamsfoundation.lams.learning.service.LearnerServiceProxy; -import org.lamsfoundation.lams.learning.web.bean.ActivityURL; import org.lamsfoundation.lams.learning.web.util.ActivityMapping; import org.lamsfoundation.lams.learning.web.util.LearningWebUtil; import org.lamsfoundation.lams.learningdesign.Activity; @@ -57,624 +55,646 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; - -/** +/** * - *

The action servlet that interacts with learner to start a lams learner - * module, join a user to the lesson and allows a user to exit a lesson.

+ *

+ * The action servlet that interacts with learner to start a lams learner module, join a user to the lesson and allows a + * user to exit a lesson. + *

* - *

It is also responsible for the interaction between lams server and - * flash. Flash will call method implemented in this class to get progress - * data or trigger a lams server calculation here

+ *

+ * It is also responsible for the interaction between lams server and flash. Flash will call method implemented in this + * class to get progress data or trigger a lams server calculation here + *

* - * Note:It needs to extend the LamsDispatchAction which has - * been customized to accomodate struts features to solve duplicate - * submission problem. + * Note:It needs to extend the LamsDispatchAction which has been customized to accomodate struts + * features to solve duplicate submission problem. * * @author Jacky Fang * @since 3/03/2005 * @version 1.1 * * ----------------XDoclet Tags-------------------- * - * @struts:action path="/learner" - * parameter="method" - * validate="false" - * @struts:action-forward name="displayActivity" path="/DisplayActivity.do" - * @struts:action-forward name="displayProgress" path="/progress.jsp" - * ----------------XDoclet Tags-------------------- + * @struts:action path="/learner" parameter="method" validate="false" + * @struts:action-forward name="displayActivity" path="/DisplayActivity.do" + * @struts:action-forward name="displayProgress" path="/progress.jsp" ----------------XDoclet Tags-------------------- * */ -public class LearnerAction extends LamsDispatchAction -{ - //--------------------------------------------------------------------- +public class LearnerAction extends LamsDispatchAction { + // --------------------------------------------------------------------- // Instance variables - //--------------------------------------------------------------------- - private static Logger log = Logger.getLogger(LearnerAction.class); - - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- + private static Logger log = Logger.getLogger(LearnerAction.class); + + // --------------------------------------------------------------------- // Class level constants - Struts forward - //--------------------------------------------------------------------- - - private static IAuditService auditService; - - private ActionForward redirectToURL(ActionMapping mapping, HttpServletResponse response, String url) throws IOException, ServletException { - if ( url != null ) { - String fullURL = WebUtil.convertToFullURL(url); - response.sendRedirect(response.encodeRedirectURL(fullURL)); - } else { - throw new ServletException("Tried to redirect to url but url is null"); - } - return null; - } + // --------------------------------------------------------------------- - /** Handle an exception - either thrown by the service or by the web layer. Allows the exception - * to be logged properly and ensure that an actual message goes back to Flash. - * - * @param e - * @param methodKey - * @param learnerService - * @return - */ - protected FlashMessage handleException(Exception e, String methodKey, ICoreLearnerService learnerService) { - log.error("Exception thrown "+methodKey,e); - String[] msg = new String[1]; - msg[0] = e.getMessage(); - - getAuditService().log(LearnerAction.class.getName()+":"+methodKey, e.toString()); - - return new FlashMessage(methodKey, - learnerService.getMessageService().getMessage("error.system.learner", msg), - FlashMessage.CRITICAL_ERROR); + private static IAuditService auditService; + + private ActionForward redirectToURL(ActionMapping mapping, HttpServletResponse response, String url) + throws IOException, ServletException { + if (url != null) { + String fullURL = WebUtil.convertToFullURL(url); + response.sendRedirect(response.encodeRedirectURL(fullURL)); + } else { + throw new ServletException("Tried to redirect to url but url is null"); } + return null; + } /** - *

The structs dispatch action that joins a learner into a lesson. This - * call is used for a user to start a lesson.

+ * Handle an exception - either thrown by the service or by the web layer. Allows the exception to be logged + * properly and ensure that an actual message goes back to Flash. * - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. + * @param e + * @param methodKey + * @param learnerService + * @return + */ + protected FlashMessage handleException(Exception e, String methodKey, ICoreLearnerService learnerService) { + LearnerAction.log.error("Exception thrown " + methodKey, e); + String[] msg = new String[1]; + msg[0] = e.getMessage(); + + getAuditService().log(LearnerAction.class.getName() + ":" + methodKey, e.toString()); + + return new FlashMessage(methodKey, learnerService.getMessageService().getMessage("error.system.learner", msg), + FlashMessage.CRITICAL_ERROR); + } + + /** + *

+ * The structs dispatch action that joins a learner into a lesson. This call is used for a user to start a lesson. + *

* - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. * + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. + * * @throws IOException * @throws ServletException */ - public ActionForward joinLesson(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - //initialize service object - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - Integer learner = null; - try { - - //get user and lesson based on request. - learner = LearningWebUtil.getUserId(); - long lessonID = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); - - - if(log.isDebugEnabled()) - log.debug("The learner ["+learner+"] is joining the lesson ["+lessonID+"]"); - - //join user to the lesson on the server - LearnerProgress learnerProgress = learnerService.joinLesson(learner,lessonID); - - if(log.isDebugEnabled()) - log.debug("The learner ["+learner+"] joined lesson. The" - +"progress data is:"+learnerProgress.toString()); - - LearningWebUtil.putLearnerProgressInRequest(request,learnerProgress); - - ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); - String url = "learning/" + activityMapping.getDisplayActivityAction(lessonID); - - redirectToURL(mapping, response, url); - - } catch (Exception e ) { - log.error("An error occurred while learner "+learner+" attempting to join the lesson.",e); - return mapping.findForward(ActivityMapping.ERROR); - } - - return null; + public ActionForward joinLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // initialize service object + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Integer learner = null; + try { + + // get user and lesson based on request. + learner = LearningWebUtil.getUserId(); + long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("The learner [" + learner + "] is joining the lesson [" + lessonID + "]"); + } + + // join user to the lesson on the server + LearnerProgress learnerProgress = learnerService.joinLesson(learner, lessonID); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("The learner [" + learner + "] joined lesson. The" + "progress data is:" + + learnerProgress.toString()); + } + + LearningWebUtil.putLearnerProgressInRequest(request, learnerProgress); + + ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet() + .getServletContext()); + String url = "learning/" + activityMapping.getDisplayActivityAction(lessonID); + + redirectToURL(mapping, response, url); + + } catch (Exception e) { + LearnerAction.log + .error("An error occurred while learner " + learner + " attempting to join the lesson.", e); + return mapping.findForward(ActivityMapping.ERROR); + } + + return null; } - + /** - *

The structs dispatch action that joins a learner into a lesson. This - * call is used for a user to resume a lesson.

+ *

+ * The structs dispatch action that joins a learner into a lesson. This call is used for a user to resume a lesson. + *

* - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. * - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * * @throws IOException * @throws ServletException */ - public ActionForward resumeLesson(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - //initialize service object - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + public ActionForward resumeLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // initialize service object + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - FlashMessage message = null; - try { - - //get user and lesson based on request. - Integer learner = LearningWebUtil.getUserId(); - long lessonID = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); - - - if(log.isDebugEnabled()) - log.debug("The learner ["+learner+"] is joining the lesson ["+lessonID+"]"); - - //join user to the lesson on the server - LearnerProgress learnerProgress = learnerService.joinLesson(learner,lessonID); - - if(log.isDebugEnabled()) - log.debug("The learner ["+learner+"] joined lesson. The" - +"porgress data is:"+learnerProgress.toString()); - - LearningWebUtil.putLearnerProgressInRequest(request,learnerProgress); - - //serialize a acknowledgement flash message with the path of display next - //activity - - ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); - message = new FlashMessage("joinLesson", activityMapping.getDisplayActivityAction(null)); - - } catch (Exception e ) { - message = handleException(e, "joinLesson", learnerService); - } - - String wddxPacket = WDDXProcessor.serialize(message); - if(log.isDebugEnabled()) - log.debug("Sending Lesson joined acknowledge message to flash:"+wddxPacket); - - //we hand over the control to flash. - response.getWriter().print(wddxPacket); - return null; + FlashMessage message = null; + try { + + // get user and lesson based on request. + Integer learner = LearningWebUtil.getUserId(); + long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("The learner [" + learner + "] is joining the lesson [" + lessonID + "]"); + } + + // join user to the lesson on the server + LearnerProgress learnerProgress = learnerService.joinLesson(learner, lessonID); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("The learner [" + learner + "] joined lesson. The" + "porgress data is:" + + learnerProgress.toString()); + } + + LearningWebUtil.putLearnerProgressInRequest(request, learnerProgress); + + // serialize a acknowledgement flash message with the path of display next + // activity + + ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet() + .getServletContext()); + message = new FlashMessage("joinLesson", activityMapping.getDisplayActivityAction(null)); + + } catch (Exception e) { + message = handleException(e, "joinLesson", learnerService); + } + + String wddxPacket = WDDXProcessor.serialize(message); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Sending Lesson joined acknowledge message to flash:" + wddxPacket); + } + + // we hand over the control to flash. + response.getWriter().print(wddxPacket); + return null; } /** - *

Exit the current lesson that is running in the leaner window. It - * expects lesson id passed as parameter from flash component. + *

+ * Exit the current lesson that is running in the leaner window. It expects lesson id passed as parameter from flash + * component. * - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. * - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * * @throws IOException * @throws ServletException */ - public ActionForward exitLesson(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - //initialize service object - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + public ActionForward exitLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + // initialize service object + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - FlashMessage message = null; - try { - // get user and lesson based on request. - Integer learner = LearningWebUtil.getUserId(); - Long lessonID = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); - - if(log.isDebugEnabled()) - log.debug("Exiting lesson, lesson id is: "+lessonID); - - learnerService.exitLesson(learner, lessonID); - - //send acknowledgment to flash as it is triggered by flash - message = new FlashMessage("exitLesson", true); + FlashMessage message = null; + try { + // get user and lesson based on request. + Integer learner = LearningWebUtil.getUserId(); + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); - } catch (Exception e ) { - message = handleException(e, "exitLesson", learnerService); - } - - String wddxPacket = WDDXProcessor.serialize(message); - if(log.isDebugEnabled()) - log.debug("Sending Exit Lesson acknowledge message to flash:"+wddxPacket); - response.getWriter().print(wddxPacket); - return null; + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Exiting lesson, lesson id is: " + lessonID); + } + + learnerService.exitLesson(learner, lessonID); + + // send acknowledgment to flash as it is triggered by flash + message = new FlashMessage("exitLesson", true); + + } catch (Exception e) { + message = handleException(e, "exitLesson", learnerService); + } + + String wddxPacket = WDDXProcessor.serialize(message); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Sending Exit Lesson acknowledge message to flash:" + wddxPacket); + } + response.getWriter().print(wddxPacket); + return null; } - + /** - * Gets the basic lesson details (name, descripton, etc) for a lesson. Contains a LessonDTO. - * Takes a single parameter lessonID + * Gets the basic lesson details (name, descripton, etc) for a lesson. Contains a LessonDTO. Takes a single + * parameter lessonID */ - public ActionForward getLesson(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { + public ActionForward getLesson(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { - //initialize service object - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + // initialize service object + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - FlashMessage message = null; - try { + FlashMessage message = null; + try { - Long lessonID = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); + Long lessonID = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); - if(log.isDebugEnabled()) - log.debug("get lesson..."+lessonID); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("get lesson..." + lessonID); + } - LessonDTO dto = learnerService.getLessonData(lessonID); - - //send acknowledgment to flash as it is triggerred by flash - message = new FlashMessage("getLesson",dto); + LessonDTO dto = learnerService.getLessonData(lessonID); - } catch (Exception e ) { - message = handleException(e, "getLesson", learnerService); - } - - String wddxPacket = WDDXProcessor.serialize(message); - if(log.isDebugEnabled()) - log.debug("Sending getLesson data message to flash:"+wddxPacket); - response.getWriter().print(wddxPacket); - return null; + // send acknowledgment to flash as it is triggerred by flash + message = new FlashMessage("getLesson", dto); + + } catch (Exception e) { + message = handleException(e, "getLesson", learnerService); + } + + String wddxPacket = WDDXProcessor.serialize(message); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Sending getLesson data message to flash:" + wddxPacket); + } + response.getWriter().print(wddxPacket); + return null; } - + /** - *

The struts dispatch action to retrieve the progress data from the - * server and tailor it into the object struture that expected by flash. - * A wddx packet with object data struture is sent back in the end of this - * call. It is used to construct or restore the flash learner progress - * bar

+ *

+ * The struts dispatch action to retrieve the progress data from the server and tailor it into the object struture + * that expected by flash. A wddx packet with object data struture is sent back in the end of this call. It is used + * to construct or restore the flash learner progress bar + *

* - *

Gets the most recent copy from the database - not the cached version. - * That way if the cached version has problems, at least we start off right! + *

+ * Gets the most recent copy from the database - not the cached version. That way if the cached version has + * problems, at least we start off right! *

* - *

As this process is expensive, the server is only expecting this call - * whenever is necessary. For example, starting, resuming and restoring - * a new lesson. And it should not happen every time that learner is - * progressing to next activity.

+ *

+ * As this process is expensive, the server is only expecting this call whenever is necessary. For example, + * starting, resuming and restoring a new lesson. And it should not happen every time that learner is progressing to + * next activity. + *

* - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. * - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * @throws IOException * @throws ServletException */ - public ActionForward getFlashProgressData(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - if(log.isDebugEnabled()) - log.debug("Getting Flash progress data..."); - - FlashMessage message = null; - try { - - //SessionBean sessionBean = LearningWebUtil.getSessionBean(request,getServlet().getServletContext()); - - Integer learnerId = LearningWebUtil.getUserId(); - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - - Long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID ); - LearnerProgressDTO learnerProgress = learnerService.getProgressDTOByLessonId(lessonId, learnerId); - - message = new FlashMessage("getFlashProgressData",learnerProgress); + public ActionForward getFlashProgressData(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Getting Flash progress data..."); + } - } catch (Exception e ) { - message = handleException(e, "getFlashProgressData", LearnerServiceProxy.getLearnerService(getServlet().getServletContext())); - } - - String wddxPacket = WDDXProcessor.serialize(message); - if(log.isDebugEnabled()) - log.debug("Sending learner progress data to flash:"+wddxPacket); - response.getWriter().print(wddxPacket); + FlashMessage message = null; + try { - //don't need to return a action forward because it sent the wddx packet - //back already. - return null; + // SessionBean sessionBean = LearningWebUtil.getSessionBean(request,getServlet().getServletContext()); + + Integer learnerId = LearningWebUtil.getUserId(); + ICoreLearnerService learnerService = LearnerServiceProxy + .getLearnerService(getServlet().getServletContext()); + + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + LearnerProgressDTO learnerProgress = learnerService.getProgressDTOByLessonId(lessonId, learnerId); + + message = new FlashMessage("getFlashProgressData", learnerProgress); + + } catch (Exception e) { + message = handleException(e, "getFlashProgressData", LearnerServiceProxy.getLearnerService(getServlet() + .getServletContext())); + } + + String wddxPacket = WDDXProcessor.serialize(message); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Sending learner progress data to flash:" + wddxPacket); + } + response.getWriter().print(wddxPacket); + + // don't need to return a action forward because it sent the wddx packet + // back already. + return null; } - + /** - *

The struts dispatch action to view the activity. This will be called - * by flash progress bar to check up the activity component. The lams side - * will calculate the url and send a flash message back to the - * flash component.

+ *

+ * The struts dispatch action to view the activity. This will be called by flash progress bar to check up the + * activity component. The lams side will calculate the url and send a flash message back to the flash component. + *

* - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. * - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * @throws IOException * @throws ServletException */ - public ActionForward getLearnerActivityURL(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - if(log.isDebugEnabled()) - log.debug("Getting url for learner activity..."); + public ActionForward getLearnerActivityURL(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Getting url for learner activity..."); + } - FlashMessage message = null; - try { + FlashMessage message = null; + try { - // get the activity id and calculate the url for this activity. - long activityId = WebUtil.readLongParam(request,AttributeNames.PARAM_ACTIVITY_ID); - String url = getLearnerActivityURL(request, activityId); - - //send data back to flash. - ProgressActivityDTO activityDTO = new ProgressActivityDTO(new Long(activityId),url); - message = new FlashMessage("getLearnerActivityURL",activityDTO); + // get the activity id and calculate the url for this activity. + long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + String url = getLearnerActivityURL(request, activityId); - } catch (Exception e ) { - message = handleException(e, "getLearnerActivityURL", LearnerServiceProxy.getLearnerService(getServlet().getServletContext())); - } - - String wddxPacket = WDDXProcessor.serialize(message); - if(log.isDebugEnabled()) - log.debug("Sending learner activity url data to flash:"+wddxPacket); - - response.getWriter().print(wddxPacket); - return null; + // send data back to flash. + ProgressActivityDTO activityDTO = new ProgressActivityDTO(new Long(activityId), url); + message = new FlashMessage("getLearnerActivityURL", activityDTO); + + } catch (Exception e) { + message = handleException(e, "getLearnerActivityURL", LearnerServiceProxy.getLearnerService(getServlet() + .getServletContext())); + } + + String wddxPacket = WDDXProcessor.serialize(message); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Sending learner activity url data to flash:" + wddxPacket); + } + + response.getWriter().print(wddxPacket); + return null; } - /** - * @param request - * @param activityId - * @return - */ - private String getLearnerActivityURL(HttpServletRequest request, long activityId) { - //initialize service object - ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + /** + * @param request + * @param activityId + * @return + */ + private String getLearnerActivityURL(HttpServletRequest request, long activityId) { + // initialize service object + ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - //getting requested object according to coming parameters - Integer learnerId = LearningWebUtil.getUserId(); - User learner = (User)LearnerServiceProxy.getUserManagementService(getServlet().getServletContext()).findById(User.class,learnerId); + // getting requested object according to coming parameters + Integer learnerId = LearningWebUtil.getUserId(); + User learner = (User) LearnerServiceProxy.getUserManagementService(getServlet().getServletContext()).findById( + User.class, learnerId); - Activity requestedActivity = learnerService.getActivity(new Long(activityId)); - Lesson lesson = learnerService.getLessonByActivity(requestedActivity); - String url = activityMapping.calculateActivityURLForProgressView(lesson,learner,requestedActivity); - return url; - } - + Activity requestedActivity = learnerService.getActivity(new Long(activityId)); + Lesson lesson = learnerService.getLessonByActivity(requestedActivity); + String url = activityMapping.calculateActivityURLForProgressView(lesson, learner, requestedActivity); + return url; + } + /** - * Gets the same url as getLearnerActivityURL() but forwards directly to the url, rather than - * returning the url in a Flash packet. + * Gets the same url as getLearnerActivityURL() but forwards directly to the url, rather than returning the url in a + * Flash packet. * - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * @throws IOException * @throws ServletException */ - public ActionForward displayProgress(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - Integer learnerId = LearningWebUtil.getUserId(); - Long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID ); - - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - Object[] ret = learnerService.getStructuredActivityURLs(learnerId, lessonId);; - request.setAttribute("progressList", (List)ret[0]); - request.setAttribute("currentActivityID", ret[1]); - - return mapping.findForward("displayProgress"); + public ActionForward displayProgress(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + Integer learnerId = LearningWebUtil.getUserId(); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + Object[] ret = learnerService.getStructuredActivityURLs(learnerId, lessonId); + ; + request.setAttribute("progressList", ret[0]); + request.setAttribute("currentActivityID", ret[1]); + + return mapping.findForward("displayProgress"); } - + /** * Forces a move to a destination Activity in the learning sequence, returning a WDDX packet * - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * @throws IOException * @throws ServletException */ - public ActionForward forceMove(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException { - FlashMessage flashMessage = null; - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); - Long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); - - try { - String url; - Activity targetActivity = forceMoveShared(request, learnerService, lessonId); - - if(!targetActivity.isFloating()) url = activityMapping.getDisplayActivityAction(null); - else url = activityMapping.getActivityURL(targetActivity); - - //TODO: update for moving to Floating Activity in Flash Learner - flashMessage = new FlashMessage("forceMove", activityMapping.getDisplayActivityAction(null)); - } catch (Exception e) { - flashMessage = handleException(e, "forceMove", learnerService); - } + public ActionForward forceMove(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + FlashMessage flashMessage = null; + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); - PrintWriter writer = response.getWriter(); - writer.println(flashMessage.serializeMessage()); - return null; - + try { + String url; + Activity targetActivity = forceMoveShared(request, learnerService, lessonId); + + if (!targetActivity.isFloating()) { + url = activityMapping.getDisplayActivityAction(null); + } else { + url = activityMapping.getActivityURL(targetActivity); + } + + // TODO: update for moving to Floating Activity in Flash Learner + flashMessage = new FlashMessage("forceMove", activityMapping.getDisplayActivityAction(null)); + } catch (Exception e) { + flashMessage = handleException(e, "forceMove", learnerService); + } + + PrintWriter writer = response.getWriter(); + writer.println(flashMessage.serializeMessage()); + return null; + } /** - * Forces a move to a destination Activity in the learning sequence, redirecting to the new - * page rather than returning a WDDX packet. + * Forces a move to a destination Activity in the learning sequence, redirecting to the new page rather than + * returning a WDDX packet. * - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * @throws IOException * @throws ServletException */ - public ActionForward forceMoveRedirect(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException { - ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); - ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); - Long lessonId = WebUtil.readLongParam(request,AttributeNames.PARAM_LESSON_ID); - - try { - String url; - Activity targetActivity = forceMoveShared(request, learnerService,lessonId); - - if(!targetActivity.isFloating()) url = "/learning" + activityMapping.getDisplayActivityAction(lessonId); - else url = activityMapping.getActivityURL(targetActivity); - - return redirectToURL(mapping, response, url); - } catch (Exception e) { - log.error("Exception throw doing force move",e); - throw new ServletException(e); - } + public ActionForward forceMoveRedirect(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + ICoreLearnerService learnerService = LearnerServiceProxy.getLearnerService(getServlet().getServletContext()); + ActivityMapping activityMapping = LearnerServiceProxy.getActivityMapping(this.getServlet().getServletContext()); + Long lessonId = WebUtil.readLongParam(request, AttributeNames.PARAM_LESSON_ID); + + try { + String url; + Activity targetActivity = forceMoveShared(request, learnerService, lessonId); + + if (!targetActivity.isFloating()) { + url = "/learning" + activityMapping.getDisplayActivityAction(lessonId); + } else { + url = activityMapping.getActivityURL(targetActivity); + } + + return redirectToURL(mapping, response, url); + } catch (Exception e) { + LearnerAction.log.error("Exception throw doing force move", e); + throw new ServletException(e); + } } /** - * @param request - * @return targetActivity The activity we are moving to. - */ - private Activity forceMoveShared(HttpServletRequest request, ICoreLearnerService learnerService, Long lessonId) { + * @param request + * @return targetActivity The activity we are moving to. + */ + private Activity forceMoveShared(HttpServletRequest request, ICoreLearnerService learnerService, Long lessonId) { - //getting requested object according to coming parameters - Integer learnerId = LearningWebUtil.getUserId(); + // getting requested object according to coming parameters + Integer learnerId = LearningWebUtil.getUserId(); - //get parameters - Long fromActivityId = null; - Long toActivityId = null; - - String fromActId = request.getParameter(AttributeNames.PARAM_CURRENT_ACTIVITY_ID); - String toActId = request.getParameter(AttributeNames.PARAM_DEST_ACTIVITY_ID); - if(fromActId != null) - try{ - fromActivityId = new Long(Long.parseLong(fromActId)); - }catch(Exception e){ - fromActivityId = null; - } - - if(toActId != null) - try{ - toActivityId = new Long(Long.parseLong(toActId)); - }catch(Exception e){ - toActivityId = null; - } - - - Activity fromActivity = null; - Activity toActivity = null; - - if(fromActivityId != null) - fromActivity = learnerService.getActivity(fromActivityId); - - if(toActivityId != null) - toActivity = learnerService.getActivity(toActivityId); - - learnerService.moveToActivity(learnerId, lessonId, fromActivity, toActivity); - - if ( log.isDebugEnabled() ) { - log.debug("Force move for learner "+learnerId+" lesson "+lessonId+". "); - } - - return toActivity; + // get parameters + Long fromActivityId = null; + Long toActivityId = null; + + String fromActId = request.getParameter(AttributeNames.PARAM_CURRENT_ACTIVITY_ID); + String toActId = request.getParameter(AttributeNames.PARAM_DEST_ACTIVITY_ID); + if (fromActId != null) { + try { + fromActivityId = new Long(Long.parseLong(fromActId)); + } catch (Exception e) { + fromActivityId = null; + } } - - /** - * Get AuditService bean. - * @return - */ - private IAuditService getAuditService(){ - if(auditService==null){ - WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet().getServletContext()); - auditService = (IAuditService) ctx.getBean("auditService"); - } - return auditService; + + if (toActId != null) { + try { + toActivityId = new Long(Long.parseLong(toActId)); + } catch (Exception e) { + toActivityId = null; + } } - + + Activity fromActivity = null; + Activity toActivity = null; + + if (fromActivityId != null) { + fromActivity = learnerService.getActivity(fromActivityId); + } + + if (toActivityId != null) { + toActivity = learnerService.getActivity(toActivityId); + } + + learnerService.moveToActivity(learnerId, lessonId, fromActivity, toActivity); + + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Force move for learner " + learnerId + " lesson " + lessonId + ". "); + } + + return toActivity; + } + /** - * Gets the same url as getLearnerActivityURL() but forwards directly to the url, rather than - * returning the url in a Flash packet. + * Get AuditService bean. * - * @param mapping An ActionMapping class that will be used by the Action class to tell - * the ActionServlet where to send the end-user. - * @param form The ActionForm class that will contain any data submitted - * by the end-user via a form. - * @param request A standard Servlet HttpServletRequest class. - * @param response A standard Servlet HttpServletResponse class. - * @return An ActionForward class that will be returned to the ActionServlet indicating where - * the user is to go next. + * @return + */ + private IAuditService getAuditService() { + if (LearnerAction.auditService == null) { + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() + .getServletContext()); + LearnerAction.auditService = (IAuditService) ctx.getBean("auditService"); + } + return LearnerAction.auditService; + } + + /** + * Gets the same url as getLearnerActivityURL() but forwards directly to the url, rather than returning the url in a + * Flash packet. + * + * @param mapping + * An ActionMapping class that will be used by the Action class to tell the ActionServlet where to + * send the end-user. + * @param form + * The ActionForm class that will contain any data submitted by the end-user via a form. + * @param request + * A standard Servlet HttpServletRequest class. + * @param response + * A standard Servlet HttpServletResponse class. + * @return An ActionForward class that will be returned to the ActionServlet indicating where the user is to go + * next. * @throws IOException * @throws ServletException */ - public ActionForward forwardToLearnerActivityURL(ActionMapping mapping, - ActionForm form, - HttpServletRequest request, - HttpServletResponse response) throws IOException, - ServletException - { - long activityId = WebUtil.readLongParam(request,AttributeNames.PARAM_ACTIVITY_ID); - if(log.isDebugEnabled()) - log.debug("Forwarding to the url for learner activity..."+activityId); - - String url = getLearnerActivityURL(request, activityId); - return redirectToURL(mapping, response, url); + public ActionForward forwardToLearnerActivityURL(ActionMapping mapping, ActionForm form, + HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + long activityId = WebUtil.readLongParam(request, AttributeNames.PARAM_ACTIVITY_ID); + if (LearnerAction.log.isDebugEnabled()) { + LearnerAction.log.debug("Forwarding to the url for learner activity..." + activityId); + } + + String url = getLearnerActivityURL(request, activityId); + return redirectToURL(mapping, response, url); } - } \ No newline at end of file Index: lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java =================================================================== RCS file: /usr/local/cvsroot/lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java,v diff -u -r1.27.2.2 -r1.27.2.3 --- lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java 1 May 2009 03:00:14 -0000 1.27.2.2 +++ lams_learning/src/java/org/lamsfoundation/lams/learning/web/util/LearningWebUtil.java 3 Jul 2009 01:24:46 -0000 1.27.2.3 @@ -48,6 +48,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.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; @@ -61,17 +62,16 @@ public class LearningWebUtil { private static Logger log = Logger.getLogger(LearningWebUtil.class); - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- // Class level constants - session attributes - //--------------------------------------------------------------------- + // --------------------------------------------------------------------- public static final String PARAM_PROGRESS_ID = "progressID"; - // public static final String POPUP_WINDOW_NAME = "LearnerActivity"; - // public static final String LEARNER_WINDOW_NAME = "lWindow"; + // public static final String POPUP_WINDOW_NAME = "LearnerActivity"; + // public static final String LEARNER_WINDOW_NAME = "lWindow"; /** - * Helper method to retrieve the user data. Gets the id from the user - * details in the shared session + * Helper method to retrieve the user data. Gets the id from the user details in the shared session * * @return the user id */ @@ -82,8 +82,8 @@ } /** - * Helper method to retrieve the user data. Gets the id from the user - * details in the shared session then retrieves the real user object. + * Helper method to retrieve the user data. Gets the id from the user details in the shared session then retrieves + * the real user object. */ public static User getUser(ICoreLearnerService learnerService) { HttpSession ss = SessionManager.getSession(); @@ -93,9 +93,8 @@ } /** - * Put the learner progress in the request. This allows some optimisation - * between the code that updates the progress and the next action which will - * access the progress. + * Put the learner progress in the request. This allows some optimisation between the code that updates the progress + * and the next action which will access the progress. */ public static void putLearnerProgressInRequest(HttpServletRequest request, LearnerProgress progress) { if (progress != null) { @@ -106,22 +105,20 @@ } /** - * Get the current learner progress. Check the request - in some cases it - * may be there. + * Get the current learner progress. Check the request - in some cases it may be there. * - * If not, the learner progress id might be in the request (if we've just - * come from complete activity). If so, get it from the db using the learner - * progress. + * If not, the learner progress id might be in the request (if we've just come from complete activity). If so, get + * it from the db using the learner progress. * - * If the learner progress id isn't available, then we have to look it up - * using activity based on the activity / activity id in the request. + * If the learner progress id isn't available, then we have to look it up using activity based on the activity / + * activity id in the request. */ public static LearnerProgress getLearnerProgress(HttpServletRequest request, ICoreLearnerService learnerService) { LearnerProgress learnerProgress = (LearnerProgress) request .getAttribute(ActivityAction.LEARNER_PROGRESS_REQUEST_ATTRIBUTE); if (learnerProgress != null) { - if (log.isDebugEnabled()) { - log.debug("getLearnerProgress: found progress in the request"); + if (LearningWebUtil.log.isDebugEnabled()) { + LearningWebUtil.log.debug("getLearnerProgress: found progress in the request"); } return learnerProgress; } @@ -131,14 +128,16 @@ // temp hack until Flash side updates it call. if (learnerProgressId == null) { learnerProgressId = WebUtil.readLongParam(request, "progressId", true); - if (learnerProgressId != null) - log.warn("Flash client still using progressId, instead of progressID in a learner call"); + if (learnerProgressId != null) { + LearningWebUtil.log + .warn("Flash client still using progressId, instead of progressID in a learner call"); + } } if (learnerProgressId != null) { learnerProgress = learnerService.getProgressById(new Long(learnerProgressId)); - if (learnerProgress != null && log.isDebugEnabled()) { - log.debug("getLearnerProgress: found progress via progress id"); + if (learnerProgress != null && LearningWebUtil.log.isDebugEnabled()) { + LearningWebUtil.log.debug("getLearnerProgress: found progress via progress id"); } } @@ -149,8 +148,8 @@ Activity act = getActivityFromRequest(request, learnerService); Lesson lesson = learnerService.getLessonByActivity(act); learnerProgress = learnerService.getProgress(learnerId, lesson.getLessonId()); - if (learnerProgress != null && log.isDebugEnabled()) { - log.debug("getLearnerProgress: found progress via learner id and activity"); + if (learnerProgress != null && LearningWebUtil.log.isDebugEnabled()) { + LearningWebUtil.log.debug("getLearnerProgress: found progress via learner id and activity"); } } @@ -159,9 +158,8 @@ } /** - * Get the activity from request. We assume there is a parameter coming in - * if there is no activity can be found in the http request. Then the - * activity id parameter is used to retrieve from database. + * Get the activity from request. We assume there is a parameter coming in if there is no activity can be found in + * the http request. Then the activity id parameter is used to retrieve from database. * * @param request * @return @@ -183,9 +181,8 @@ } /** - * Put an activity into the request. Calls LearnerService to get the - * activity, to ensure that it is a "real" activity, not one of the cglib - * proxies. activity. + * Put an activity into the request. Calls LearnerService to get the activity, to ensure that it is a "real" + * activity, not one of the cglib proxies. activity. * * @param request * @param activity @@ -201,18 +198,16 @@ } /** - * "Complete" an activity from the web layer's perspective. Used for - * CompleteActivityAction and the Gate and Grouping actions. Calls the - * learningService to actually complete the activity and progress. + * "Complete" an activity from the web layer's perspective. Used for CompleteActivityAction and the Gate and + * Grouping actions. Calls the learningService to actually complete the activity and progress. * * @param redirect - * Should this call redirect to the next screen (true) or use - * a forward (false) + * Should this call redirect to the next screen (true) or use a forward (false) * @param windowName - * Name of the window that triggered this code. Normally - * LearnerActivity (the popup window) or lWindow (normal - * learner window) + * Name of the window that triggered this code. Normally LearnerActivity (the popup window) or + * lWindow (normal learner window) * @throws UnsupportedEncodingException + * @throws InterruptedException * */ public static ActionForward completeActivity(HttpServletRequest request, HttpServletResponse response, @@ -228,12 +223,24 @@ } else if (progress.getCompletedActivities().containsKey(currentActivity)) { return actionMappings.getCloseForward(currentActivity, lesson.getLessonId()); } else { - // Set activity as complete - progress = learnerService.completeActivity(learnerId, currentActivity, progress); + // 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); + } } - if (currentActivity != null && currentActivity.isFloating()) + if (currentActivity != null && currentActivity.isFloating()) { return actionMappings.getCloseForward(currentActivity, lesson.getLessonId()); + } LearningWebUtil.putActivityInRequest(request, progress.getNextActivity(), learnerService); LearningWebUtil.putLearnerProgressInRequest(request, progress); @@ -267,19 +274,20 @@ activityForm.setLessonID(currentLesson.getLessonId()); LearningDesign currentDesign = currentLesson.getLearningDesign(); - if (currentDesign != null) + if (currentDesign != null) { activityForm.setVersion(currentDesign.getDesignVersion()); + } } - if (log.isDebugEnabled()) - log.debug("Entering activity: progress summary is " + activityForm.getProgressSummary()); + if (LearningWebUtil.log.isDebugEnabled()) { + LearningWebUtil.log.debug("Entering activity: progress summary is " + activityForm.getProgressSummary()); + } } /** - * Setup the progress string, version and lesson id in the actionForm. The - * values will go in the map with the keys "progressSummary", "lessonID", - * "version". + * Setup the progress string, version and lesson id in the actionForm. The values will go in the map with the keys + * "progressSummary", "lessonID", "version". */ public static void setupProgressInRequest(DynaActionForm actionForm, HttpServletRequest request, LearnerProgress learnerProgress) { @@ -299,12 +307,14 @@ actionForm.set("lessonID", currentLesson.getLessonId()); LearningDesign currentDesign = currentLesson.getLearningDesign(); - if (currentDesign != null) + if (currentDesign != null) { actionForm.set("version", currentDesign.getDesignVersion()); + } } - if (log.isDebugEnabled()) - log.debug("Entering activity: progress summary is " + actionForm.get("progressSummary")); + if (LearningWebUtil.log.isDebugEnabled()) { + LearningWebUtil.log.debug("Entering activity: progress summary is " + actionForm.get("progressSummary")); + } } Index: lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumOutputFactory.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumOutputFactory.java,v diff -u -r1.6 -r1.6.6.1 --- lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumOutputFactory.java 31 Oct 2008 05:57:38 -0000 1.6 +++ lams_tool_forum/src/java/org/lamsfoundation/lams/tool/forum/service/ForumOutputFactory.java 3 Jul 2009 01:27:42 -0000 1.6.6.1 @@ -58,7 +58,7 @@ * @see org.lamsfoundation.lams.tool.OutputDefinitionFactory#getToolOutputDefinitions(java.lang.Object) */ @Override - public SortedMap getToolOutputDefinitions(Object toolContentObject) + public SortedMap getToolOutputDefinitions(Object toolContentObject, int definitionType) throws ToolException { SortedMap definitionMap = new TreeMap(); Index: lams_tool_sbmt/src/java/org/lamsfoundation/lams/tool/sbmt/service/SubmitFilesService.java =================================================================== RCS file: /usr/local/cvsroot/lams_tool_sbmt/src/java/org/lamsfoundation/lams/tool/sbmt/service/SubmitFilesService.java,v diff -u -r1.78.4.2 -r1.78.4.3 --- lams_tool_sbmt/src/java/org/lamsfoundation/lams/tool/sbmt/service/SubmitFilesService.java 1 May 2009 06:13:54 -0000 1.78.4.2 +++ lams_tool_sbmt/src/java/org/lamsfoundation/lams/tool/sbmt/service/SubmitFilesService.java 3 Jul 2009 01:27:42 -0000 1.78.4.3 @@ -183,8 +183,7 @@ /** * (non-Javadoc) * - * @see org.lamsfoundation.lams.tool.ToolContentManager#copyToolContent(java.lang.Long, - * java.lang.Long) + * @see org.lamsfoundation.lams.tool.ToolContentManager#copyToolContent(java.lang.Long, java.lang.Long) */ public void copyToolContent(Long fromContentId, Long toContentId) throws ToolException { if (toContentId == null) { @@ -226,9 +225,8 @@ } /** - * If the toolContentID does not exist, then get default tool content id - * from tool core and initialize a emtpy SubmitFilesContent - * return. + * If the toolContentID does not exist, then get default tool content id from tool core and initialize a emtpy + * SubmitFilesContent return. * * @param toolContentId * @return @@ -293,8 +291,7 @@ } /** - * Export the XML fragment for the tool's content, along with any files - * needed for the content. + * Export the XML fragment for the tool's content, along with any files needed for the content. * * @throws ExportToolContentException */ @@ -359,16 +356,15 @@ } /** - * Get the definitions for possible output for an activity, based on the - * toolContentId. These may be definitions that are always available for the - * tool (e.g. number of marks for Multiple Choice) or a custom definition - * created for a particular activity such as the answer to the third - * question contains the word Koala and hence the need for the toolContentId + * Get the definitions for possible output for an activity, based on the toolContentId. These may be definitions + * that are always available for the tool (e.g. number of marks for Multiple Choice) or a custom definition created + * for a particular activity such as the answer to the third question contains the word Koala and hence the need for + * the toolContentId * - * @return SortedMap of ToolOutputDefinitions with the key being the name of - * each definition + * @return SortedMap of ToolOutputDefinitions with the key being the name of each definition */ - public SortedMap getToolOutputDefinitions(Long toolContentId) throws ToolException { + public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) + throws ToolException { return new TreeMap(); } @@ -411,12 +407,11 @@ } /** - * This method verifies the credentials of the SubmitFiles Tool and gives it - * the Ticket to login and access the Content Repository. + * This method verifies the credentials of the SubmitFiles Tool and gives it the Ticket to login and + * access the Content Repository. * - * A valid ticket is needed in order to access the content from the - * repository. This method would be called evertime the tool needs to - * upload/download files from the content repository. + * A valid ticket is needed in order to access the content from the repository. This method would be called evertime + * the tool needs to upload/download files from the content repository. * * @return ITicket The ticket for repostory access * @throws SubmitFilesException @@ -437,8 +432,8 @@ } /** - * This method deletes the content with the given uuid and - * versionID from the content repository + * This method deletes the content with the given uuid and versionID from the content + * repository * * @param uuid * The uuid of the node to be deleted @@ -582,8 +577,8 @@ /** * Get the tool output for the given tool output names. * - * @see org.lamsfoundation.lams.tool.ToolSessionManager#getToolOutput(java.util.List, - * java.lang.Long, java.lang.Long) + * @see org.lamsfoundation.lams.tool.ToolSessionManager#getToolOutput(java.util.List, java.lang.Long, + * java.lang.Long) */ public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { return new TreeMap(); @@ -592,8 +587,8 @@ /** * Get the tool output for the given tool output name. * - * @see org.lamsfoundation.lams.tool.ToolSessionManager#getToolOutput(java.lang.String, - * java.lang.Long, java.lang.Long) + * @see org.lamsfoundation.lams.tool.ToolSessionManager#getToolOutput(java.lang.String, java.lang.Long, + * java.lang.Long) */ public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { return null; @@ -602,8 +597,7 @@ /** * (non-Javadoc) * - * @see org.lamsfoundation.lams.tool.ToolSessionManager# - * uploadFileToContent(Long,FormFile ) + * @see org.lamsfoundation.lams.tool.ToolSessionManager# uploadFileToContent(Long,FormFile ) */ public InstructionFiles uploadFileToContent(Long contentID, FormFile uploadFile, String fileType) throws SubmitFilesException { @@ -625,8 +619,7 @@ /** * (non-Javadoc) * - * @see org.lamsfoundation.lams.tool.ToolSessionManager# - * uploadFileToSession(Long,FormFile,String,Long ) + * @see org.lamsfoundation.lams.tool.ToolSessionManager# uploadFileToSession(Long,FormFile,String,Long ) */ public void uploadFileToSession(Long sessionID, FormFile uploadFile, String fileDescription, Integer userID) throws SubmitFilesException { @@ -718,9 +711,8 @@ } /** - * This method save SubmissionDetails list into a map container: key is user - * id, value is a list container, which contains all - * FileDetailsDTO object belong to this user. + * This method save SubmissionDetails list into a map container: key is user id, value is a list container, which + * contains all FileDetailsDTO object belong to this user. */ public SortedMap getFilesUploadedBySession(Long sessionID, Locale currentLocale) { List list = submissionDetailsDAO.getSubmissionDetailsBySession(sessionID); @@ -871,8 +863,8 @@ @SuppressWarnings("unchecked") public void sendMarksToGradebook(SubmitUser user, Long toolSessionID) { submissionDetailsDAO.getSubmissionDetailsBySession(toolSessionID); - List detailsList = (List) submissionDetailsDAO.getBySessionAndLearner( - toolSessionID, user.getUserID()); + List detailsList = submissionDetailsDAO.getBySessionAndLearner(toolSessionID, user + .getUserID()); if (detailsList != null) { Float totalMark = null; for (SubmissionDetails details : detailsList) { @@ -984,8 +976,7 @@ } /** - * Set the description, throws away the title value as this is not supported - * in 2.0 + * Set the description, throws away the title value as this is not supported in 2.0 */ public void setReflectiveData(Long toolContentId, String title, String description) throws ToolException, DataMissingException { @@ -1049,9 +1040,9 @@ return submitUserDAO.getContentUser(contentId, userID); } - /*************************************************************************** + /******************************************************************************************************************* * Property Injection Methods - **************************************************************************/ + ******************************************************************************************************************/ /** * @param submitFilesContentDAO