Sakai notes

Sakai (http://sakaiproject.org/) is an open source portal environment, implemented in Java, created to support composite web applications, motivated by the requirements of Virtual Learning Environments (VLEs), and is currently being deployed experimentally to support Virtual Research Environments (VREs).

Two documents provide a good overview of the Sakai architecture and its implementation in Java:

1. Sakai Architecture and Java Framework

Sakai employs the services of a Java application server and servlet engine, commonly Tomcat, and is built using two key supporting libraries: Spring and JavaServer Faces. A helicopter has been described as "10,000 spare parts flying in close formation". A Sakai-based system might be viewed similarly as several web applications in close formation. This tongue-in-cheek description attempts to capture the idea that static dependencies between the various service components in Sakai are minimized through Dependency Injection, based on the Spring framework.

A Sakai application takes over an entire Tomcat servlet engine instance, and uses separate web applications and contexts within the engine for each of the tools and service components. When an application is loaded, it is dynamically linked to the tools and services upon which it depends, rather than having particular services linked statically to the program image. This is the essence of the "Dependency Injection" (or "Inversion of Control") pattern.

1.1. Dependency injection

Inversion of Control is a generic mechanism whereby an object is connected to its dependencies (or collaborators). Dependency Injection is a specific mechnism for achieving Inversion of Control.

Sakai (via Spring) supports two forms of Inversion of Control:

Dependency Pull
a service location model, in which a component uses a registry or container API to discover and load the services that it needs, and
Dependency Injection
a service injection model, in which the run time container includes a component registry that "injects" links to required services into new applications as they are loaded.

The former approach creates a component application dependency on the service registry facility, making it harder to use the component in a different environment, or to test it in isolation. Using the latter approach, a service can be implemented as a Plain Old Java Object (POJO), with the requirement that it provides JavaBean "setter" methods for the injection of the service objects upon which it depends. While Sakai supports either model (service injection or service location) for linking service depednencies, to my mind the service injection approach is crucial for flexibility and maintainability.

1.2. Sakai API: Tool Portability Profile (TPP)

Sakai does not provide a fixed API for portal tools, but rather provides a collection of APIs that are wired together using the service injection described above, with the intent that any potentially re-usable logic is moved out of an individual tool into a supporting service API. A basic set of such APIs, with particular (but not exclusive) emphasis on presentation, constitutes a Tool Portability Profile (TPP), which is as about as close as one gets to a "Sakai API".

The presentation services are based on a collection of JavaServer Faces that abstract presentation components away from specific presentation elements toward application-relevant user interface components.

Sakai provides several approaches to aggregation of tool content, including iframe and non-iframe based methods. A significant feature of Sakai rendering is that the Sakai interface (and overall layout of the aggragated display?) is handled separately from individual tool rendering. This alows flexibility in choosing an approach that is suitable for for Sakai "native" tools or one that also includes legacy web application displays. It is claimed (plausibly, in my view) that this makes Sakai more amenable to repurposing for environments other than learning support.

There is a good overview presentation of Sakai tool development here [2].

1.3. Spring application context

Spring's ApplicationContext is an extension of its BeanFactory, which more fully handles the configuration and dependency injection of beans based on a purely declarative configuration description. ApplicationContext also has support for internationalization (I18N), event publication, resource management, further lifecycle management, and automatic configuration of infrastructure resources.

The I18N support is mainly a framefork for defining multilingual message texts, and mechanisms for retrieving an appropriate localization of a message.

The event publishing support provides a mechanism for asynchonous communication between Spring applications within[?] the application context.

The resource management provides acces to various blobs of data that are typically obtained from the local file system, JAR files or the Web, but possibly also from other sources.

[I'm not yet sure what the others mean, but hopefully all will be made clear.]

At the time of writing I'm not sure if Sakai uses these ideas, but they seem sufficiently important and useful that I think it probably should, so I'm adding these notes.

1.4. Spring event model

Spring supports an event model that is used in conjunction with an ApplicationContext object. An event is an instance of a class derived from Spring's ApplicationEvent. Each event consists of at least:

Events are distributed within an application context by a publish/subscribe mechanism. Application classes are listeners if they implement the ApplicationListener interface, and recive all events published to the application context. Events are published by calling the application context's publishEvent method.

It appears that an event's source is conventionally a reference to the object that publishes the event, but that doesn't seem to be enforced by the Spring framework.

1.5. Spring Aspect Oriented programming (AOP)

Spring implements a restricted form of Aspect oriented Programming (AOP) [3][4]. A key restriction of Spring AOP is that only method invocation join points are provided.

AOP is a programming technique and technology that allows separation of concerns in the implementation of complex software systems. Each aspect on an application can be implemented by separate, stand-alone code, the pieces then being woven together to create the complete application.

Compare this with conventional object oriented programming in which a class typically inherits or explicitly references all the added functionality that the application requires to be associated with that class. This leads to complex interdependencies of the source code, which in turn makes it difficult to test components in isolation, or repurpose common components for different applications.

[This next paragraph is speculative, and may not be entirely correct...]

An application build using AOP may consist of a class hierarchy that is largely derived from the specific application requirements, combined with software components called "aspects" that implement "cross cutting concerns". These aspects typically provide functionality that is re-usable in a variety of disparate applications, though may also be used to provide functionality that recurrs in various guises within a single application. Commonly offered examples of application-independent aspects are logging and access control checks. An example used in the book Pro Spring [5], which is more application specific, is an obscenity filter for a web log content management system.

Key aspect oriented programming concepts include (these are precised from [5], pp158-159):

joinpoint
a specific point in the execution of an application at which code for some cross-cutting concern may be invoked.
advice

some code that is executed at a particular joinpoint.

pointcut

a collection of joinpoints determining when advice should be executed in some given application.

aspect

a combination of some advice and pointcuts for a given application. Thus, we see that an aspect is a description of how some common crosscutting concern function is combined with a base application to create an enhanced application.

weaving
the process of inserting aspects into application code.
target (target object, advised object)
an object whose execution is modified by some aspect.
introduction
modifying the structure of an object to implement additional methods. Can be used to procure an object's implementation of a specific interface not provided by its class code.

Traditional AOP developments, such as AspectJ [6] use a static form of weaving, in which pointcuts are connected to their corresponding advice as part of the program compilation process. Spring AOP uses a dynamic form of weaving that creates proxy classes at runtime for the target classes, which proxies activate the advice and target object methods as required.

[I still would like to figure out the relationship, if any, between Spring dependency injection and AOP]

1.6. JavaServer Faces

[TBD]

1.7. IRC chat

There exists an IRC channel, #sakai on irc.freenode.net, but it is empty and has no (or almost no) traffic

2. Installing Sakai

These notes describe out installation of Sakai on Scientific Linux 4.02 (a Redhat enterprise clone).

We have decided not to use the quickstart install, instead following instructions per http://cvs.sakaiproject.org/release/1.5.0/index-dev.html.

The host we are using is sakai-vre-demo.oucs.oc.ac.uk.

2.1. File protections

Our first attempt at installtion ran into a couple of problems due to file protections. Tomcat was installed as root, with root owner/group for all the Tomcat directories. This caused problems when installing Sakai.

Our proposed approach is to install all Tomcat files under a new user tomcat, group tomcat, and make the Tomcat install files all group writeable. Then add group tomcat to the user used to install the Sakai software (sakaivre in our case. We have also declared all directories to carry the group sticky bit, so that new files are created with the same group ownetrship.

Everying inder $CATALINA_HOME/webapps needs to be changed to have group full access permission (g+rw).

We also want to ensure that Tomcat always runs as user tomcat.

2.2. Prerequisites

}}}

export MAVEN_HOME=/opt/maven-1.0.2 export PATH=$PATH:$MAVEN_HOME/bin }}}

useradd sakaivre }}}

maven.tomcat.home = /opt/apache-tomcat-5.5.16 ### Can use $CATALINA_HOME? }}}

}}}

If Tomcat is run at this point, browsing to http://sakai-vre-demo.oucs.oc.ac.uk:8080 will display the standard`Tomcat front page. http://sakai-vre-demo.oucs.oc.ac.uk:8080/jsp-examples displays example data and confirms JSP operation.

2.3. Sakai installation

After initially spending some time trying to install the wrong version of Sakai (1.5 not 2.1.2) - see SakaiNotes/OriginalNotes. Adrian spotted our mistake, so we tried again using a similar approach and it worked. As Adrian said, it should take less that 3 hours, if you're doing it right. The instructions I followed were the ones at: http://cvs.sakaiproject.org/release/2.1.2/InstallGuide.html for the source install.

Before the JAVA_OPTS were set, the Tomcat start up was taking ages and attempts to access port 8080 resulted in timeouts. In such a situation, the normal Tomcat shutdown.sh script does not work, presumably because it too can't connect. Thus the "killall java" command.

The following script captures the sequence used to install Sakai on our Scientific Linux system:

### as root 
su -

#install java
yum install java

#create the user and group
useradd tomcat
usermod -G tomcat syeates
usermod -G tomcat zool0635

#create dircetories for the compnents we're going to install
for filename in /opt/maven /opt/sakai  /opt/apache-tomcat;
do
    mkdir -p $filename
    chown tomcat:tomcat $filename
done

### as tomcat
su - tomcat

#java is already installed
export JAVA_HOME=/opt/jdk/jdk1.5.0_06/


# install tomcat
cd /opt/apache-tomcat
wget http://apache.rmplc.co.uk/tomcat/tomcat-5/v5.5.16/bin/apache-tomcat-5.5.16.tar.gz
tar -xzf apache-tomcat-5.5.16.tar.gz
wget http://apache.rmplc.co.uk/tomcat/tomcat-5/v5.5.16/bin/apache-tomcat-5.5.16-compat.tar.gz
tar -xzf apache-tomcat-5.5.16-compat.tar.gz
wget http://apache.rmplc.co.uk/tomcat/tomcat-5/v5.5.16/bin/apache-tomcat-5.5.16-admin.tar.gz
tar -xzf apache-tomcat-5.5.16-admin.tar.gz


#remember where we've kept it
export CATALINA_HOME=/opt/apache-tomcat/apache-tomcat-5.5.16/

# we're not caring about non-roman characters to start with
#emacs  $CATALINA_HOME/conf/server.xml 


cat > $CATALINA_HOME/webapps/ROOT/index.html << EOF
<html>
<head>
  <meta http-equiv="refresh" content="0;url=/portal">
</head>
<body>
  redirecting to /portal ...
</body>
</html>
EOF

# install maven
cd /opt/maven
wget http://apache.mirror.positive-internet.com/maven/binaries/maven-1.0.2.tar.gz
tar -xzf maven-1.0.2.tar.gz

# set some maven defualts in our home dircetory
cat > /home/tomcat/build.properties << EOF
maven.repo.remote=http://source.sakaiproject.org/maven/
maven.tomcat.home = /opt/apache-tomcat/apache-tomcat-5.5.16/
EOF

#remember whre we've kept it
export MAVEN_HOME=/opt/maven/maven-1.0.2/

# install sakai
cd /opt/sakai

wget http://cvs.sakaiproject.org/release/2.1.2/sakai_2-1-2/sakai-src_2-1-2.tar.gz
tar -xzf sakai-src_2-1-2.tar.gz

# run maven on sakai
cd /opt/sakai/sakai-src
$MAVEN_HOME/bin/maven 
$MAVEN_HOME/bin/maven sakai
$MAVEN_HOME/bin/maven sakai:deploy

# this is sometimes needed because the normal shutdown times out / doesn't work when the JVM is very low on memory
killall java

# these JAVA_OPTS differ from the recommended in that there is no "-Xms1500m" or 
# "-XX:PermSize=128m" options removing these options allows {{{.../bin/shutdown

# command to work and reduces the need to use kill or killall on the # sakai system. JAVA_OPTS="-server -Xmx1500m -XX:NewSize=400m -XX:MaxNewSize=400m -XX:MaxPermSize=128m -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails" $CATALINA_HOME/bin/startup.sh $CATALINA_HOME/bin/shutdown.sh

}}}

The resulting page looks like:

http://www.flickr.com/photos/stuartyeates/135327822/

The install uses quite a bit of space:

243136  /opt/apache-tomcat
13648   /opt/maven
402212  /opt/sakai
149644  /home/tomcat/

The size of /home/tomcat/ is due to the presence of the maven repository, which a cache of all the libraries that maven has downloaded from the web.

Sakai 2.1.2 does a number of things better than 1.5, and a number of our earlier criticisms are no longer valid.

2.4. Things that can go wrong with the install

* Maven expects paths (in build.properties and elsewhere) to end in trailing slashes, their absence will lead to a sakai that is installed but doesn't start when tomcat starts.

* Maven fails to download activation.jar and mail.jar. These are SUN jars protected by a click through licence. Download them by hand and insert them into the maven repository.

* If maven is failing to find jars once they are installed, maven may have created a second repository. Check you're using the right one.

2.5. Configuration of auto-startup

init.d stops and starts programs when the system is shutdown and restarted. The following /etc/init.d/tomcat file tells init.d what to do. On Redhat based systems, this file is also used by the chkconfig and service commands to provide easy-to-use service configuration and management.

File /etc/init.d/tomcat:

#
# tomcat        
#
# chkconfig: 45 95 5
# description:  Start up the Tomcat servlet engine.
# processname: tomcat
#
# Source function library.
. /etc/init.d/functions


RETVAL=$?
export CATALINA_HOME=/opt/apache-tomcat/apache-tomcat-5.5.16/
export JAVA_HOME=/opt/jdk/jdk1.5.0_06/

case "$1" in
 start)
        if [ -f $CATALINA_HOME/bin/startup.sh ];
          then
            echo $"Starting Tomcat"
            export JAVA_OPTS="-server -Xmx1500m  -XX:MaxNewSize=400m -XX:PermSize=128m -XX:MaxPermSize=128m -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails"
            /bin/su tomcat $CATALINA_HOME/bin/startup.sh
        fi
        ;;
 stop)
        if [ -f $CATALINA_HOME/bin/shutdown.sh ];
          then
            echo $"Stopping Tomcat"
            /bin/su tomcat $CATALINA_HOME/bin/shutdown.sh
        fi
        ;;
 *)
        echo $"Usage: $0 {start|stop}"
        exit 1
        ;;
esac

exit $RETVAL

2.6. Notes

We think the following are questionable. This is work-in-progress, so our views may change as we get on further with Sakai.

3. Sakai configuration

The following notes come from http://cvs.sakaiproject.org/release/2.0.1/SourceInstallGuide.html#Configuration:

}}}

# second for disk based #url@javax.sql.BaseDataSource=jdbc:hsqldb:. url@javax.sql.BaseDataSource=jdbc:hsqldb:${sakai.home}/db/sakai.db }}}

4. References

  1. http://dsg.port.ac.uk/events/workshops/VRE05/schedule.html - Sakai VRE demonstrator workshop schedule and notes, Portsmouth, January 2006.

  2. http://dsg.port.ac.uk/events/workshops/VRE05/talks/Miguel%20Gonzalez%20Losa.ppt - "Tools development with Sakai Java Framework" - presentation from the Sakai VRE workshop [1].

  3. http://aosd.net/ - "aosd.net is home to the annual Aspect-Oriented Software Development conference and is intended to provide a comprehensive source of information about AOSD".

  4. http://aopalliance.sourceforge.net/ - "The AOP Alliance project is a joint open-source project between several software engineering people who are interested in AOP and Java".

  5. Rob Harrop and Jan Machacek, Pro Spring, apress 2005, 1-59059-4.

  6. http://www.parc.com/research/projects/aspectj/default.html - PARC page about AspectJ.


-- GrahamKlyne 2006-02-10 15:01:32

Creative Commons License
The content of this wiki is licensed under the Creative Commons Attribution-ShareAlike 2.0 England & Wales Licence.

OSS Watch is funded by the Joint Information Systems Committee (JISC) and is situated within the Research Technologies Service (RTS) of the University of Oxford.