Sakai Plugin

  • Tags : /
  • Latest : 0.4.2
  • Last Updated: 09 July 2009
  • Grails version : 1.1
  • Authors : null
0 vote
Dependency :
compile ":sakai:0.4.2"

Documentation

Summary

Installation

grails install-plugin sakai

Description

Introduction

This plugin adds facilities for running Grails apps inside Sakai, an open source collaboration system for educational institutions. See http://sakaiproject.org/portal

Unlike typical Java webapps, Sakai tools share a lot of third-party dependencies with each other, all in Tomcat's /shared/lib. Because Sakai and Grails will share a single copy of Spring and Hibernate jars, their versions must agree. Sakai was patched to use Spring 2.5.6.SEC01 on July 3, 2009. Sakai's older releases, and trunk code before that date won't work with this plugin. Likewise, you cannot (yet) use Grails 1.1.1 with Sakai until Sakai is patched to an updated version of Hibernate. Sakai still uses Hibernate 3.2.5.GA.

To summarize: use the sakai plugin with the trunk of Sakai and Grails 1.1.

Configuration Options

The sakai plugin adds three configuration settings which determine a little metadata about the tool. These settings should be added to Config.groovy.

grails.sakai.toolmode = true
grails.sakai.tool.name = "Grade Calc"
grails.sakai.tool.desc = "This tool calculates your overall grade for the term."

The toolmode property informs the plugin upon building a war file if you intend to run this application as a Sakai tool (meaning it will be accessed within Sakai under the /portal address). If you set toolmode to false it means you intend to access the application at its direct URL below the root.

War File for Sakai

The plugin adds a new script to grails, sakai-war. As the name implies, it creates a special war file suitable for dropping into a Sakai installation. The Sakai war file will have certain jar files removed from WEB-INF to avoid collisions, it adds a tool registration file to provide Sakai with tool metadata (name and description), and it modifies web.xml with a listener, a context loader, and a servlet.

Sakai Tags

Sakai tools run inside a portal-like environment. All access to tools is relative to the /portal URL and the specific placement of the tool. Since links inside the tool have to take this portal context into account, there is a <s:link> tag to be used in place of the <g:link> tag which will add the necessary context to the link as the tool runs inside the portal.

TODO: All of built-in grails tags should eventually have a Sakai version to enable correct links for things like remoteLink etc. Even better would be if the sakai plugin can actually override the default grails behavior, rather than necessitate entirely different tags, but I haven't learned how to do this yet.

The sakai plugin tag library also has an onload() convenience method to add the correct JavaScript calls to make the tool load properly in the portal (sizing the iframe, for instance). Here's how you would use that in your gsp:

<body onload="s.onload()">

Sakai Stub Context

One of the central goals of the sakai plugin for Grails is to enable developing Sakai code outside of Sakai as much as possible. Sakai is large, startup time is long, and the feedback loop during development is slow. To facilitate developing Sakai capabilities outside of Sakai, the sakai plugin loads a complete Sakai application context, which means all the services like UserDirectoryService and SiteService are available to call. The implementations are stubs only, so you won't get real, meaningful data from these "offline" services, but they will permit you to code as if the services were available. When you deploy your code to Sakai, of course, all of your calls will be directed to the real service.

To access the Sakai context in your controllers, services, and taglibs, simply add def sakai within the class. This is simply the standard Grails way of doing dependency injection. All of the Sakai services are then accessible by their names. Here's an example from a controller:

class HelloController

def sakai def greetings = { render "Hello, ${sakai.userDirectoryService.currentUser.displayName}!" }

If you need a little more lifelike behavior from any particular Sakai service, you can create your own implementation that overrides the stub. For example, say I want the display name of the current user to come back as "Professor Plum." I can write an implementation to that effect (very succinctly I might add, thanks to Groovy):

import org.sakaiproject.user.api.*

class UserServiceFactory {

static user = [ getDisplayName: { return "Professor Plum" } ] as User

static UserDirectoryService getInstance() { return [ getCurrentUser: { return user } ] as UserDirectoryService }

}

I would put that under src/groovy and call it UserServiceFactory.groovy. Then I modify resources.groovy under grails-app/conf/spring to specify my implementation of the service. Note that I specifically only want my implementation when I'm running in the development environment:

import grails.util.*

beans = { switch(GrailsUtil.environment) { case "development": userDirectoryService(UserServiceFactory) { bean -> bean.factoryMethod = "getInstance" } break } }