Saturday, March 18, 2006

Mapping group types

To use Enterprise Services, you need to create a set of mappings between the objects used in the various Java method calls, and the data in your system. One of the most important aspects of doing this mapping is establishing what types of Groups you are working with.

IMS Enterprise mandates specifying a group Type for every Group instance, such as "Module" or "Course". These are identified with a Scheme attribute, so there is the potential to map groups across diverse systems based on value spaces. There is also a Level value for hinting at relative granularity, which can sometimes be useful.

For example, if you created a vocabulary of the types of groups Moodle supports as being in the scheme:


And for LAMS:


(these are just examples, I don't know what structures Moodle and LAMS actually use - ask Alex!)

When calling the service, you can then correlate the types so that you get the right types of groups.

For example, if LAMS is the provider, and Moodle is the client, and a call returns a Group with the type "lams:sequenceGroup:2", you might assert that you're dealing with the equivalent of a Moodle Group rather than a whole new course.

These mapping rules can then be encoded into an interface you wrap around the SDK at the client end so that it just returns the kind of groups that make sense in local terms, rather than any and all generic IMS groups.

This is important, because in a lot of MIS systems groups are keyed on all kinds of factors, like semester and campus, and also often contain both canonical and actual courses, so doing a straight transfer from MIS->VLE can generate zillions of courses if you don't sort out the mapping rules.

Monday, March 13, 2006

Enterprise "version 2" Considered Harmful

A lot of people have been mentioning the "version 2" of Enterprise Services mentioned on the IMS site.

For the record, this isn't a more advanced or later version of the spec, instead its the Asynchronous binding, which while it was produced by the IMS team, none of the working group members were interested in implementing or testing it. Therefore, its basically there as experimental only, with no reference implementation, and without having gone through the iterative testing process that got most of the bugs out of ES v1.0. Which means it probably won't work without messing around with the XSDs and WSDL.

Basically, don't bother with "v2" unless you really, really have to do point-to-point async transactions, and you can't think of another alternative.

Thursday, March 02, 2006

Example client code

The article over at CETIS only explains how to code the difficult end of enterprise - the server. How do you implement a client?

Below is a code snippet that might shed some light. Its from an application that aggregates groups and resources from a range of sources, in this case this is the method it uses to get information about people who are members of a group.

The array of java objects returned by the call represent Persons (in this case), and you can do the usual sort of operations on them like getFormatName() and so on.

Pretty much any enterprise API call is coded in exactly the same fashion.

(Apologies for the lines scooting off the end of the page...)

* Get the members of a group from the service
* @param id the id of the group to get members for
* @param url the location of the service
* @return a set of persons
* @throws PlexException
public PersonDType[] readPersonsForGroup(IdentifierDType id, String url) throws PlexException{
_readPersonsRequest = new _readPersonsForGroupRequest();
_responseHolder = new _readPersonsForGroupResponseHolder();
_responseHeaderInfoHolder = new _syncResponseHeaderInfoHolder();
try {
_requestHeaderInfo = HeaderInfoHelper.newRequestHeaderInfo();
PersonManagementServiceSyncLocator loc = new PersonManagementServiceSyncLocator();
PersonManagementServiceSyncSoapStub svc = (PersonManagementServiceSyncSoapStub)loc.getPersonManagementServiceSyncSoap(new;
_status = _responseHeaderInfoHolder.value.getStatusInfo();
_persons = _responseHolder.value.getPersonSet();
}catch (Exception e){
throw new PlexException("There was a problem connecting to the remote service");
if (_persons == null || _status.getCodeMajor().getValue().equals("failure")){
throw new PlexException("There was a problem with the remote service ("+_status.getDescription()+")");
if (_status.getCodeMajor().getValue().equals("unsupported")){
throw new PlexException("The remote service doesn't support this type of request");
return _persons.getPerson();

Hey, ho, lets go!

This is the new home of the Enterprise SDK - all the old stuff (such as it was) is still on the Sourceforge site which you can access over from the link list. This is where I'm going to announce any updates, and publish any new documentation. If you've got support questions, feature requests, or bugs, then use the regular SF features.

Congratulations to MINTED and JoinIn on getting their projects started!