SCORM 2004 in Sakai: A REST Runtime That Holds Up
We replaced Wicket SJAX with Spring REST, added site-to-site import, and explain why SCORM 2004 remains our supported standard.
SCORM 2004 in Sakai: A REST Runtime That Holds Up
We finished a rewrite of the Sakai SCORM 2004 player that removes Wicket synchronous Ajax and moves runtime calls to Spring REST controllers. The result is simpler to reason about, easier to debug, and friendlier to test. The same work adds site-to-site import so instructors can move SCORM packages between course sites without manual downloads.
What changed
- The browser runtime now calls stable HTTP endpoints instead of tunneling through Wicket components.
- Controllers are stateless and backed by Spring beans that handle launch, attempt state, runtime calls, and sequencing.
- Requests and responses are logged with clear correlation IDs so a trace connects a content click to a database write.
- The import flow copies a package from a source site into a target site and rebinds ownership to the new site. Attempt data remains scoped per site.
How SCORM 2004 talks to the LMS
SCORM 2004 defines a browser-based Runtime API. When a package launches inside the LMS frame set, the content looks up the API_1484_11 object and calls a small set of methods:
Initialize("")starts the session and returns success or an error code.GetValue(element)reads acmi.*data model element, for examplecmi.locationorcmi.score.scaled.SetValue(element, value)writes to the model, for examplecmi.progress_measureorcmi.suspend_data.Commit("")asks the LMS to persist pending changes.Terminate("")ends the session and triggers sequencing decisions.
In the old player those calls crossed a Wicket boundary through hidden frames and synchronous Ajax. In the new player the JavaScript adapter marshals each call into a JSON request and sends it to REST endpoints. Example shape:
POST /scorm/runtime/v1/set-value
Content-Type: application/json
{
"attemptId": "4e1a...",
"element": "cmi.score.scaled",
"value": "0.92"
}
200 OK
Content-Type: application/json
{ "result": "true", "error": 0 }
The controller validates the element against the SCORM 2004 data model, applies size limits such as the 64 KB cap for cmi.suspend_data, and persists the write under the current attempt. Commit flushes any buffered values. Terminate runs the sequencing engine before closing the attempt so the next activity can be determined.
A quick tour of the data model
SCORM 2004 standardizes names and constraints so the LMS and content agree on meaning.
- Location and resume:
cmi.locationandcmi.suspend_datalet content save resume points and private state.suspend_datais opaque to the LMS and limited in size. - Progress and scoring:
cmi.progress_measure,cmi.completion_status,cmi.success_status, andcmi.score.scaledcarry what instructors expect to see in the gradebook. - Objectives and interactions:
cmi.objectivesandcmi.interactionsallow fine grained reporting. The player stores them as structured records and enforces indexing rules. - Error handling: every call maps to numeric errors such as 0 for success, 101 for general exception, 201 for invalid argument, 301 for not initialized. The REST layer returns a clear HTTP status plus the SCORM error for the content to read back through
GetLastError().
Sequencing and navigation
SCORM 2004 adds a sequencing and navigation model that 1.2 did not standardize. The LMS evaluates prerequisites, flow, and choice rules using the activity tree from the manifest. In our player, sequencing lives in a service that runs during launch, SetValue on key elements, and Terminate. This keeps navigation logic out of controllers and makes it testable.
Why REST over Wicket SJAX
- Clear boundaries: runtime adapter, controllers, services, and persistence do one job each.
- Better observability: each request carries an attempt ID and trace ID. Logs show element writes and decisions.
- Easier testing: unit tests mock the store or sequencing, and integration tests replay captured HTTP traffic.
- Debug with real tools: network tab, curl, and packet captures tell the story without digging into component serialization.
Site-to-site import
The new import action lets a user select a source site and copy its SCORM packages into a target site. The system reads package metadata, copies the ZIP and manifest, and reassigns ownership to the target. Attempts and tracking stay with the original site, which is what most instructors want when rolling content forward to a new term.
Why we continue to support SCORM 2004
People have tried to replace SCORM for a long time, but it remains the format that meets day to day needs for packaged content in an LMS.
- Installed base: institutions and publishers have large libraries of SCORM content that need to keep working.
- Defined grade semantics: SCORM 2004 has a clear data model for completion, success, and score. Gradebook mapping is predictable.
- Sequencing: the standard supports instructor intent about order and prerequisites.
- Authoring ecosystem: popular tools export SCORM 2004 first. Teams can produce content without custom integration work.
Alternatives improve other use cases but do not replace this one outright.
- xAPI focuses on flexible activity statements across systems. It is great for analytics pipelines and informal learning, but it does not define LMS grade semantics or sequencing by itself.
- cmi5 layers launch and LMS rules on top of xAPI. Adoption is growing, but many campuses and vendors still prioritize SCORM packaging.
- LTI launches external tools. It is not a content runtime or tracking spec, so it solves a different problem.
- Common Cartridge is a packaging format for course materials. It does not define a browser runtime or the SCORM data model.
Given the constraints in higher education, SCORM 2004 remains the dependable way to deliver packaged, trackable modules inside the LMS. Our job is to make that path reliable and debuggable.
What is next
- Expand automated tests around runtime controllers and the sequencing service.
- Document REST request and response shapes so support teams can reproduce issues quickly.
- Gather feedback from early adopters, then tune logging and limits where it helps instructors the most.
If your course pushes SCORM hard, try the new player and let us know where it can be sharper.
References
- Runtime rewrite patch: https://github.com/sakaiproject/sakai/commit/1fcb7d191870ac404f1c9e656840ff2358b6f5b6.patch
- Import from site patch: https://github.com/sakaiproject/sakai/commit/35ce2445b1347748886a5e722f6d821a0f2d760d.patch