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:
http://cvs.sakaiproject.org/release/1.5.1/docs/Sakai-Architecture-1.0.0.pdf - is a very short document describing the Sakai architecture at a very high-level.
http://cvs.sakaiproject.org/release/1.5.1/docs/Sakai-Java-Framework-1.5.0.pdf - a longer document describing the Java implementation of Sakai, pitched to a technical audience but managing to avoid getting bogged down in distracting technical detail.
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:
- a type (class), and
- a source, which is an arbitrary object.
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
Java 1.4.2: use yum install java to install java-1.4.2-sun-compat and j2sdk. We later converted to Java 1.5 (because the Shibboleth installation recommended this and we wanted to keep everything using the same version of java), there were literally no problems with the switch, everything worked apparently identically. We did do a reinstall and rebuild from source of sakai from these instructions, which may or may not have been necessary.
Tomcat 5.5.16: download from Apache site http://tomcat.apache.org/download-55.cgi#5.5.16, and install to /opt. Unzip core tomcat package, tomcat-admin and tomcat-compat to the same base directory /opt. The archives contain a top-level directory apache-tomcat-5.5.16/. Define environment variable:
CATALINA_HOME=/opt/apache-tomcat-5.5.16
Maven 1.0.2 - download from http://maven.apache.org/start/download.html and follow installation instructions given at http://maven.apache.org/start/install.html. In out case, download the archive file and unpack to /opt (the archive contains a top-level directory maven-1.0.2/.
Before you begin using Maven you will need to define the MAVEN_HOME environment variable which is the directory where you just unpacked the Maven install archive. You will also need to add MAVEN_HOME/bin to your path so that you can run the scripts provided with Maven.
You will also need to define the JAVA_HOME environment variable. This variable should be the directory where a Java Development Kit is installed (note that a JRE is not sufficient). This directory will contain the bin, jre and lib directories.
Place the relevant environment variable definitions in /etc/bashrc (noting our system is effectively dedicated for Sakai development/testing, so defining for all-users seems appropriate).
export JAVA_HOME=/opt/jdk/jdk1.5.0_06/ export MAVEN_HOME=/opt/maven-1.0.2 export PATH=$PATH:$MAVEN_HOME/bin
We choose to create a new user sakaivre as the "home user" for Maven configuration, repositories, etc.
su - useradd sakaivre
Place a Maven build.properties in the skaivre home directory:
maven.repo.remote = http://www.ibiblio.org/maven/,http://cvs.sakaiproject.org/maven/ maven.tomcat.home = /opt/apache-tomcat-5.5.16 ### Can use $CATALINA_HOME?
- Enable execute permissions on Maven executable:
chmod a+x /opt/maven-1.0.2/bin/*
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:
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:
#!/bin/bash
#
# 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.
- Deployment seems to be hardwired to Tomcat, not allowing other servlet containers (no longer the case with the current version)
- Deployment structure breaks chroot model (we think) Fixed in 2.1.2? (no longer the case with the current version)
- Unexpected interactions with file ownership/protection settings?
3. Sakai configuration
The following notes come from http://cvs.sakaiproject.org/release/2.0.1/SourceInstallGuide.html#Configuration:
- Create sakai folder for properties files Sakai runs with a default set of properties for its various components. To override them you'll want to specify them in a sakai.properties file which should be located in $CATALINA_HOME/sakai by default. This directory is not created by maven, so you'll have to do so manually. Once this directory is created, there are several *.properties files you can place inside which can override default properties. (works for 2.2 as well)
- The sakai.properties file The main configuration file for Sakai is called sakai.properties, and you can either create it from scratch or copy in a known working copy. A sample sakai.properties file which self-documents many of the standard properties in its comments can be found in:
sakai-src/docs/sakai.properties
(works for 2.2 as well)
- Creating a persistent Sakai use database appears to be very easy: there's a one-line change/addition in sakai.properties, that causes the user database to be saved as a sequence of SQL commands when the portal is closed down:
# two hsqldb storage options: first for in-memory (no persistence between runs), # second for disk based #url@javax.sql.BaseDataSource=jdbc:hsqldb:. url@javax.sql.BaseDataSource=jdbc:hsqldb:${sakai.home}/db/sakai.db(It turns out that this is a default configuration for Sakai 2.2.)
4. References
http://dsg.port.ac.uk/events/workshops/VRE05/schedule.html - Sakai VRE demonstrator workshop schedule and notes, Portsmouth, January 2006.
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].
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".
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".
Rob Harrop and Jan Machacek, Pro Spring, apress 2005, 1-59059-4.
http://www.parc.com/research/projects/aspectj/default.html - PARC page about AspectJ.
4.1. Other links
SakaiNotes/OriginalNotes - original notes about installing Sakai, based on an older version of the software. These notes are obsolete and are being lodged here for historical reference.
SakaiVre - Sakai VRE demonstrator project at Oxford, for which this work is being conducted.
http://tyne.dl.ac.uk/Sakai/sakai_doc/node54.html - Daresbury notes about Sakai installation
http://bug.sakaiproject.org/confluence/display/ENC/Sakai+2.0+Configuration - Sakai configuration outline
http://bugs.sakaiproject.org/confluence/display/DOC/Post-Installation+Configuration - Post-Installation Configuration (Sakai 2.2)
-- GrahamKlyne 2006-02-10 15:01:32


