Sakai Conditional Release Developer's Guide
Motivation
Design
The first design attempt produced a plan for a system that would encapsulate into a Rule
arbitrarily many queries to arbitrarily many Sakai services. In this way, if a particular resource were protected by a Rule
, accessing the resource could cause a request to the GradebookService
, another request to ContentHostingService
, and so on. This design was deemed too chatty for reasonable performance in the Resources tool, which must conform to many of the performance characteristics of a file system.
...
For example, we want to be able to restrict access to a particular folder to just those students who score above an 80 on a recent quiz. When the instructor grades her students, each assignment grade goes out into Sakai as a Excerpt
hidden | true |
---|
gradebook.updateItemScore
hidden | true |
---|
Sakai has a built-in mechanism for responding to events, called the NotificationService
. Clients of the service ask it to create objects of type Notification
. The Notification
extends Sakai Entity
and specifies three additional key pieces of information: Excerpt
- one or more strings containing event types to respond to. These are called functions.
- a string called a resource filter which indicates which resource may be affected by the event.
- an object of type
NotificationAction
which has thenotify()
method for taking action in response to the event.
...
NotificationAction
called ResourceReleaseRule
, which also implements Predicate
from Apache commons-collections. The purpose of Predicate
is to add a hidden | true |
---|
boolean evaluate(Object arg)
hidden | true |
---|
notify()
method checks the condition and then takes the necessary action to update the state of the ContentHostingService
....
We now have all the pieces to describe exactly how conditional release works. Since the application of conditions is asynchronous, there can be an arbitrary space of time between steps 2 and 3: hidden Excerpt
- Instructor edits details on an item in the Resources tool and is presented with "Only if the following conditions is met" option. The list of available assignments and their conditions is passed from the
ConditionService
with no direct dependency from the Resources tool and theGradebookService
. - Instructor saves the details, and within
ResourcesAction
aPredicate
is created from the condition parameters and is added to a fresh instance ofResourceReleaseRule
which in turn is added to a fresh instance ofNotification
, along with the event type (function) to respond to and the resource filter (the resource's ID). TheNotificationService
takes care of persisting theNotification
. - As events propagate through Sakai,
BaseNotificationService
examines each one for a matching function in its stored list ofNotifications
. If a storedNotification
matches both the function and resource filter of the inbound event, its embeddedNotificationAction
is dereferenced and itsnotify()
method is called. - In the case of a
ResourceReleaseRule
, an argument necessary for evaluating the embeddedPredicate
will be pulled from the event and the embeddedPredicate
will be evaluated. In response to the evaluation, the access rules of the underlying content resource will either be modified or left alone.
...
...
BooleanExpression
The Predicate
within the ResourceReleaseRule
is delegated to another class called BooleanExpression
. The BooleanExpression
is how we programmatically encapsulate such English language questions as "Is the assignment score above 80?" We have a conventional boolean expression here, with a left term, an operator, and a right term. What makes this interesting is that at the time the instructor sets up the condition, a necessary piece of information to answer the question is missing. In our example, the missing piece is the left term, the assignment score in question. This data only materializes later, at the time the instructor submits one or more assignment grades.
...
Sakai's BaseNotificationService
has its limitations, notably that it requires any implementations of NotificationAction
to be physically inside its component {{WEB-INF
}} directory. Also, it uses manual manipulation of DOM objects for persistence, which is error-prone and yields object storage in the database as a lump of XML.
TO-DO
Here are a few less glamorous things that need doing. These are some suggestions that any volunteer developer could tackle.
- event pack should not have to declare a dependency on conditions-impl. This is in there now in order to avoid a
ClassdefNotFound
error when we ask theNotificationService
to reconstitute aResourceReleaseRule
from the database. It should be able to get aClass
object from the SakaiComponentManager
instead. Look inBaseNotificationService
for where it does this:Code Block m_action = (NotificationAction) Class.forName(className).newInstance();
GradebookExternalAssessmentServiceImpl
should not use a static cover of theEventTrackingService
. This is a case of doing the quick thing rather than the right thing. There's a Spring bean configuration file in there. We just need to modify it to add an injectedEventTrackingService
.- The behavior of the content tool UI should not depend on the index number of items in the
<select>
tags. There are hard-coded references to magic indexes inResourcesAction
,ListItem
, andsakai_properties_scripts.vm
. It's ugly. - Speaking of ugly, the UI does not degrade gracefully if any parts of the form become very long. The box for adding a point value becomes orphaned on the next line. Someone with HTML chops could make it nice.