This page covers some background to the progress engine, the overall system design as well as the implementation algorithm.
This page is based on the original LAMS 1.1 Progress Engine document in the lams_document project. It has been updated to reflect LAMS 2.1, but the original document makes more comparisons with LAMS 1.0, so if you want to see how the progress engine has evolved, check the original document. The UML diagrams on this page have been taken from that document (as screenshots) or are in one of the MagicDraw files in lams_common/design. MagicDraw v10 is the best version for updating these diagrams - you open the .zip file from within MagicDraw to access the diagrams.
|Table of Contents|
Secondly, the loading page is a good place to send update progress bar message to the Flash client. If you are familiar with LAMS before 2.0, you will notice that In LAMS 1.0 we had the entry JSP page of each tool is doing updates of the Flash progress bar. This results resulted in a tight dependency between tool and the Flash progress bar. Furthermore, update code on all tools' JSP generates duplicate code and consequently a maintainability nightmare.
Isn't the loading page is extra overhead and makes LAMS very "chatty" (ie a lot of calls to the server)? Yes, but for the benefits it has brought use, it was worth the overhead. If usage and/or profiling show an issue in this area then we will optimise the code however the overall methodology appears sound at this stage and there are other areas we can look at for performance improvements.
Move to next activity
Figure 5 Move to Next Activity - Sequence Diagram
Above diagram shows the overall algorithm used to complete the moving from one activity to the other. This process usually triggered by clicking on the "Finished" button of a particular tool page. Originally we did Step 2 to Step 6 has to be done 8 in one transaction so as to ensure there is no inconsistent state between tool and LAMS server. After that, However when we implemented Live Edit, there was an increased chance that calculating the learner progress would fail due to some case we hadn't considered (setting up Live Edit while allowing the learners to proceed and not putting in synchronisation points which may slow down the progress engine wasn't easy). So we split the update into two transactions, so that the tool is always able to persist their data, and then it forwards to a URL in the learning web app to do all of the progress updates.
It is important to notice that LAMS travel from tool web application to lams_learning web application by via http URL redirecting. The calls. This means that any calls to the core services that are NOT in the tool's Spring contexts are available to the learning logic. The tool's do not include all the context.xml files for the core, so some of the service beans are not available.
The lams_learning is responsible for calculating the URL for next activity and forward to it. Two major algorithms, Calculate the next activity at service layer and Mapping the Activity to the URL, are hidden in above diagram, which will be explained in following sections.
This has been changed to include a call to the "CompleteActivityAction", rather than going straight to then next activityIn the diagram above, many of the calls such as Calculate Learner Progress, Put Activity in Request, etc, are really calls to other classes, but the other classes have to be hidden or the diagram would be impossible to read.
Calculate the next activity at service layer
Note: The "recently completed activities" list referred to in the diagram doesn't seem to be used - potentially this could be dropped. The functionality is implemented by the method LearnerProgress.populateCurrentCompletedActivityList() so we could try dropping this method and test to ensure that the progress engine is still working correctly.
Mapping the Activity to the URL
Figure 7 Calculate the URL from Learner Progress- Activity Diagram
Once the service layer progress engine calculated the next activity to move on to and returned the learner progress, the web layer progress engine needs to figure out what is the proper URL for the next activity. Figure 7 illustrates the algorithm to fulfill this functionality.
Some calls do redirects, some do forwards. The intention is that in moving to the next activity, something should redirect to ensure that we don't accidently go back to the last screen. Normally the redirect is done via the displayTool.jsp but in other cases it is handled by the Struts "forward", which can be setup to be either a forward or a redirect. One day it would be nice to document exact at which point in the processed a redirect is done, so that we can ensure all "next activity" calls do a redirect but don't do a whole pile of redirects.
Join a lesson with Retrieving Progress Data - Needs Updating
Figure 8 Join lesson with retrieving progress data - Sequence Diagram
Based on the understanding of major progress engine algorithm and page loading mechanism, we can further the explanation of the joining lesson algorithm. The explanations of join lesson and retrieving progress data are combined because these two use cases usually happen consecutively. Once LAMS finishes joining the learner to the lesson and send the wddx acknowledgement message with the URL of loading page calculation struts action back to Flash, Flash sends the request to the LAMS server to grab entire learner progress structure to build up learner progress bar. The progress data request from Flash has to be sent after the Flash client receives the "Joined Lesson" message from LAMS because it needs to load the latest progress data.
Communication between Server progress engine and Flash Progress bar
Figure 9 Server and Flash Communication - Move to next activity
At present, the lesson and progress data are not cached, although the core User objects are cached. These are obvious candidates for caching, as they are complex structures and are required on every calculation of the next activity. Just putting the objects straight into the user's normal HttpSession or even the SharedSession doesn't work well. The HttpSession varies from web-app to web-app and some of the code to execute the "next" functionality is run within the tool's web-app, although the code itself lives in the lams-learning.jar. Putting it in the SharedSession would avoid this, but then we have to have two different entries for the lesson and progress data for the preview screen and the learner screen as both can be running simultaneously. Also, putting the lesson in the SharedSession is not a good idea as the Lesson is the same for all the users in the Lesson and potentially we could be caching a Learning Design (attached to the Lesson) which is now out of date due to a Live Edit. So the Lesson and the LearningDesign will probably need to be cached using the JBoss cache, which interacts with Hibernate so that the object in the cache is up to date.
In general, there is a lot of "put activity in the request", "get learner progress somehow", "put activity id/learning design id in the request parameters", etc in the progress engine. Originally it was carefully tuned so that each system screen got only what it needed, but then we'd change the screen to do more and we'd need more parameters, etc so it grew higglepiggldy. When we look at caching the progress data then we need to clean up where we put the activity in the request.
Making System Tools More Pluggable