Developing Sakai Services and Tools

Developing Sakai Services
and Tools
Mark J. Norton
Senior Technical Consultant
The Sakai Project
Page 1
Overview
•
•
•
•
•
•
•
General Information
Creating APIs
Implementing Service
Writing Tools
Framework Considerations
Development Example
Coming Attractions – Framework 2
Page 2
Building Tools with a Framework
Page 3
The Sakai Framework
• Architecture overview
– Sakai has a simple, layered architecture.
• The Sakai framework
– Common services are part of the framework
– JSF, Spring, Context, Hibernate
Page 4
Sakai Architecture
• Descriptions of the Sakai Architecture are
being collected into a set of documents
• The Tool Portability Profile defines how to
write Sakai tools and is being updated
• The architecture is intended to promote
tool portability and data interoperability
Page 5
Sakai Framework
Abstract Sakai Architecture
Client
The aggregator combines content
from various sources into a single
user interface experience.
Aggregator
The presentation layer allows the
user interface to be described
separately from the tool code.
Presentation
The tool handles events and
adjusts data for presentation back
to the user/client
Tool
Services provide abstract
capabilities for application logic and
common support functions.
Services
System
The system includes Tomcat, the
webserver, file system, databases,
etc..
Page 6
Sakai Design Patterns
• Separation of Tool Logic and UI
– Velocity and JSF separate UI representation.
• Service Injection
– Spring and JSF inject services as needed.
• Model – View – Controller
– JSF
• Object persistence via ORM
– Legacy uses XML fragments, later we use Hibernate.
• Coding to APIs
– Sakai APIs and OKI OSIDs.
Look for
the Pattern
Symbol
Page 7
Sakai Framework Technology
•
•
•
•
Hibernate for object persistence
Sakai APIs that imitate OKI OSIDs
Tools are based on APIs and servlets
JavaServer Faces separate out the
presentation from tool logic
• uPortal integrates tools at the UI level
Page 8
The Sakai 1 Framework
Browser
Apache &
Tomcat
response and request
Jetspeed
Portal
Velocity or JSF
iFrame Based
Portal
rendering
Tool
Component
Manager
Spring
injection
injection
Application
Services
Common
Services
Page 9
The Sakai Module
• A Sakai module consists of:
– A tool.
– Application services.
– Implementations of those services.
TheTool
Service Interface A
Service Interface B
Implementation of A
Implementation of B
Common
Services
Page 10
Design Methodology
•
•
•
•
•
•
Consider the users needs first.
Develop the user interface (prototyping).
Next consider your application services.
Develop their interfaces.
Implement them as components.
Write the tool to connect UI to services.
Page 11
Development Considerations
• User interface design is critical, but out of
scope for this workshop. Have a close
look at the Sakai Style Guide and consider
user centric design approaches.
• Let’s take a close look at what goes into
an application service interface and
implementation.
• Then we’ll explore tool development.
Page 12
Application Service Interfaces
Page 13
Application Service Interfaces
•
•
•
•
What is a Sakai Service?
What is available?
Common practices
Definitions
Interface
Design
Pattern
Page 14
Sakai Services - Definition
• A Sakai Service is a collection of classes
defined by an interface that provides an
integrated set of functionality.
– Roughly split between application and
common services.
– Tools call on services for the functions they
provide.
– Services may depend on other services.
– Services are portable, modular, and reusable.
Page 15
Two Kinds of Interfaces
• Sakai APIs
– Older legacy services and newer common
services.
– Sakai APIs are designed to make it easy to
create powerful Sakai tools
• OKI OSIDs
– Focused on access to data.
– OKI OSIDs are designed to maximize tool
portability to environments other than Sakai.
Page 16
OSIDs and APIs
• Sakai has interface requirements above
and beyond the OKI OSIDs
• There is no way to cleanly extend the OKI
OSIDs
• Therefore, Sakai is creating a set of APIs
that correspond as closely as possible to
the OSIDs, but extend them in various
ways.
• The OSIDs are covers over the Sakai
services.
Page 17
Sakai APIs
• Make tool development easier
• Promote portability between Sakai
environments
• Hide some data management details
• Simplify Error handling
• Provide re-usable system and application
services to tool developers
Page 18
Example – API vs. OSID
Org.osid.agent.Agent
OSID Adaptor Component
Interface
Implementation
Org.sakaiproject.common.service.Agent
Org.sakaiproject.common.component.agent.Agent
Page 19
The OKI Agent OSID
package org.osid.agent;
Serializable
Access only
Exceptions
OKI Interators
public interface Agent extends java.io.Serializable {
public String getDisplayName()
throws osid.shared.SharedException;
public osid.shared.Id getId()
throws osid.shared.SharedException;
public osid.shared.Type getType()
throws osid.shared.SharedException;
public PropertiesIterator getProperties()
throws osid.shared.SharedException;
Properties getPropertiesByType(Type propertiesType)
throws osid.shared.SharedException;
public TypeIterator getPropertiesTypes()
throws osid.shared.SharedException;
}
Page 20
The Sakai Agent API
package org.sakaiproject.service.common.agent;
Same name
POJO style
Java GUIDs
Sakai features
public interface Agent {
public String getDisplayName();
public void setDisplayName(String displayName);
public Long getId();
public String getReferenceName();
public void setReferenceName(String referenceName);
public Type getType();
public void setType(Type type);
public String getUuid();
public void setUuid(String uuid);
public Integer getVersion();
public Node getNode();
public void setNode(Node node);
public String getAlias();
public void setAlias(String alias);
}
Page 21
Which Interface Should I Use?
• Use the Sakai APIs:
– To develop Sakai tools
– To access Sakai service features
• Use the OKI OSIDs:
– For maximum tool portability
– When data modification isn’t relevant
Page 22
Sakai API Guidelines
•
•
•
•
•
•
Include convenience methods and
objects built on OKI methods (e.g.
equals())
Include Java-oriented methods which
directly relate to underlying OKI
language-neutral equivalents (e.g.
Calendar)
Include Java-oriented methods which
tie more directly to the Sakai
framework, increasing performance at
the expense of portability to non-Sakai
environments.
Extend beyond the OSIDs to allow
explicit exposure of out of band
agreements
Extend beyond the OSIDs to allow for
easy/simple/natural support of usecases not directly supported by current
OSID specifications
Methods should be evaluated carefully
for what exceptions are thrown
•
•
•
•
•
•
Java-based exception classes and
subclasses are used for the
exceptions thrown
Consider using exceptions which are
subclasses of RuntimeException: A
method is not required to declare in its
throws clause any subclasses of
RuntimeException that might be
thrown during the execution of the
method but not caught.
Implementations of the APIs may be
java beans: therefore the APIs use
set/get in a bean-compatible way
Methods may use/return Java-native
objects/interfaces, e.g. Calendar,
io.stream
The term 'properties' is used for
consistency with OKI, but the Java
interface used for this is a Map
Sakai iterators extend java.util.Iterator
Page 23
Including Services in a Module
• The service APIs associated with a Sakai
module should be contained in a subdirectory of the module (called service).
• Service APIs are deployed to the shared
lib directory of Tomcat via Maven.
• Services are registered with the Sakai
Component Manager to make them
available to the tool (and other services).
Page 24
Implementing Components
Page 25
Service Implementations
•
•
•
•
•
Further design considerations
Writing an application service
Using Common Services
Injecting dependent services
Persistence – hibernate
Page 26
OKI Application OSIDs
• There are a few OKI application level OSIDs:
– Repository, Grading, Course Management, and
Assessment. All of these are being developed.
• If your application is closely based on these
service use the existing implementations if
possible.
• If you need to create a new implementation,
use the OKI OSID 2.0 interface definitions and
have a close look at other implementations.
Page 27
Application Service Design
• Follow the best practices exhibited in other
services, for example use a Manager class
to create and access service objects.
• Give careful thought to the classes
included in the service.
• Non-OSID services don’t need an OSID
style cover interface.
Page 28
Application Service Characteristics
• Calls common services via injection.
• Deals with objects reflected in a user
interface.
• Defines a process or workflow.
• Might be tied to an app or tool.
• Designed to be generally usable in many
tools (repository service, for example).
Page 29
Migrating a Legacy Service
• Migration of legacy services will be
handled by the core Sakai development
team, in general.
• Since legacy tools are closely tied to these
services, service migration must be
coordinated with tool migration.
• Talk to Mark or Chuck before doing
anything!
Page 30
Creating a Brand New Service
• Define the Interface based on Sakai
service best practices.
• Use the TPP for guidelines.
• Define data modules and definitions.
• Use Hibernate for object persistence.
• Write a test harness application (or unit
tests).
• Submit the new service for evaluation and
release.
Page 31
Creating an Application Service
• Check to see if anyone has already created
something similar to this service.
• Define the interface based on Sakai best
practices.
• Use the TPP for guidelines.
• Define data modules and definitions.
• Use Hibernate for object persistence.
• Write a test harness application (or unit tests).
• Submit the new service for evaluation and
release.
Page 32
Using Common Services
Page 33
Dependency Injection
• Bean style access and setters
• Inserted at runtime by the Spring container
• Dependencies are defined in XML
configuration files, as appropriate.
• This is one of the standard design patterns
described further in the TPP document.
Injection
Design
Pattern
Page 34
Object Persistence
• Hibernate provides ORM support.
• Objects are persisted to a database.
• Hibernate handles atomic Java data types,
POJOs, collections, and complex objects.
• HQL allows selective object retrieval which
can be optimized by DBAs.
• Support for transactions, locking,
clustering, and multi-stage caching.
ORM
Design
Pattern
Page 35
Data Models
• Standards
– Use existing industry standards where
available.
• Data Elements
– Design and document your data elements
and organization.
• Access Model
– Use object persistence. Avoid DB
dependencies.
• Interchange – consider data migration
needs.
Page 36
Generic vs. Custom Repositories
• Sakai will provide a generic repository
• It will provide basic file management,
access control, and metadata support.
• You may have special needs which require
a custom repository.
• Capabilities can be layered on the Sakai
Repository or you can build one from
scratch.
Page 37
Example: Presentation Service
• The presentation service manages three
objects:
Slide
Presentation
Manager
Presentation
Show
Page 38
The Slide Class
• A simple POJO containing the following
data elements:
– URL
– Display Name
– Content
– Type (MIME type)
Page 39
The Slide Interface
package org.sakaiproject.service.presentation;
public interface Slide extends java.io.Serializable {
public String getUrl();
public void setUrl(String url);
public Serializable getContent();
public void setContent(Serializable content);
public String getDisplayName();
public void setDisplayName(String name);
public String getType();
public void setType(String type);
}
Page 40
Notes on the Slide Interface
• A POJO interface allows easy access via
Spring, Hibernate, and JavaServer Faces.
• URLs are represented by strings here, but
they could be Java URLs classes as well.
• Content type is managed by using a Type
object as a MIME type, similar to the OKI
Filing OSID.
Page 41
The Presentation Class
• The Presentation class is a structured
collection of slides:
– Identifier
– Title and Author properties
– Slide set
– Wait slide
Page 42
The Presentation API
public interface Presentation extends java.io.Serializable {
public static final String PRESENTATION_TITLE =
"org.sakaiproject.tools.presentation.title";
public Id getId();
public void setId (Id id);
public String getTitle ();
public void setTitle (String title);
public String getAuthor ();
public void setAuthor (String author);
public List getSlides();
public Slide getSlide (int offset);
public void addSlide(Slide slide);
public int getSlideCount();
public void deleteSlide (int position);
public void insertSlide(int position, Slide slide);
public Slide getWaitSlide();
public void setWaitSlide(Slide waitSlide);
}
Page 43
Notes on the Presentation API
• Convenience methods provided for easy
access to title and author properties.
• Access to a List object instead of an
iterator.
• Most of the heavy lifting is done by the
Presentation Manager class.
Page 44
Service Example: Agent
package osid.agent;
public interface Agent extends java.io.Serializable {
public String getDisplayName()
throws osid.shared.SharedException;
public osid.shared.Id getId()
throws osid.shared.SharedException;
public osid.shared.Type getType()
throws osid.shared.SharedException;
PropertiesIterator getProperties()
throws osid.shared.SharedException;
Properties getPropertiesByType(Type propertiesType)
throws osid.shared.SharedException;
TypeIterator getPropertiesTypes()
throws osid.shared.SharedException;
}
package org.sakaiproject.service.common.agent;
import org.sakaiproject.service.common.shared.Resource;
public interface Agent extends Resource { }
Page 45
Service
Example:
Resource
package org.sakaiproject.service.common.shared;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.exception.VersionException;
import org.sakaiproject.service.common.id.Id;
public interface Resource extends Comparable {
String getDescription();
String getDisplayName();
Id getId();
Type getType();
PropertiesIterator getProperties();
Properties getPropertiesByType(Type propertiesType);
TypeIterator getPropertyTypes();
void setDescription(String description);
void setDisplayName(String displayName);
void setType(Type type);
String getReference();
String getUrl();
boolean allowDelete();
boolean allowUpdate();
Properties addPropertiesType(Type propertiesType);
void removePropertiesType(Type propertiesType);
void delete() throws PermissionException;
Version getVersion();
boolean isCurrentVersion();
boolean isCurrentVersion(Version version);
void update() throws VersionException, PermissionException;
Page 46
void updateIgnoreVersion() throws PermissionException; }
Legacy Services
Page 47
Legacy Services
• Jon Andersen of U. Michigan will talk for
15 – 20 minutes on Sakai Legacy Services
including:
– Active user
– Active worksite
– Authorization
– Resources and content API
Page 48
Legacy Services
• Legacy services were created primarily for the
tools in the 1.0.0 release (Announcements,
Chat, Resources, etc)
• Legacy services manage all persistent data such
as current user, current site, security, and toolspecific information.
• Legacy services will evolve as JSF tools are
developered and OKI OSID services mature,
and a migration path will be provided.
Page 49
How to use Legacy Services
1. Identify the needed legacy service
2. Inject the legacy service into your own
tool bean or service
3. Use the legacy service in your tool bean
logic or service logic
4. Provide access methods in the tool bean
for the data or actions that the JSF page
requires
Page 50
Identify
Needed
Services
Q: How do I find
out about the
current user, site,
page or tool?
A: Use one of the
legacy services
(until Sakai 2.0)
package org.sakaiproject.service.framework.portal;
public interface PortalService {
…
String getCurrentSiteId();
String getCurrentSitePageId();
String getCurrentToolId();
…
}
package org.sakaiproject.service.legacy.user;
public interface UserDirectoryService {
…
User getCurrentUser();
…
}
package org.sakaiproject.service.legacy.site;
public interface SiteService {
…
boolean allowUpdateSite(String siteId);
…
}
Page 51
Inject needed services (1)
(faces-config.xml)
<faces-config>
<managed-bean-name>MyTool</managed-bean-name>
<managed-bean-class>org.sakaiproject.tool.mytool.MyTool</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<description>Service Dependency: UserDirectoryService</description>
<property-name>userDirectoryService</property-name>
<value>#{Components["org.sakaiproject.service.legacy.user.UserDirectoryService"]}</value>
</managed-property>
<managed-property>
<description>Service Dependency: SiteService</description>
<property-name>siteService</property-name>
<value>#{Components["org.sakaiproject.service.legacy.site.SiteService"]}</value>
</managed-property>
<managed-property>
<description>Service Dependency: PortalService</description>
<property-name>portalService</property-name>
<value>#{Components["org.sakaiproject.service.framework.portal.PortalService"]}</value>
</managed-property>
</managed-bean>
Legacy services are indexed by the
</faces-config>
class names of the service interfaces
Page 52
Inject needed services (2)
(MyTool.java)
…
public class MyTool implements ToolBean {
private UserDirectoryService m_userDirectoryService;
private SiteService m_siteService;
private PortalService m_portalService;
public void setUserDirectoryService(UserDirectoryService service) {
this.m_userDirectoryService = service;
}
public void setSiteService(SiteService service) {
this.m_siteService = service;
}
public void setPortalService(PortalService service) {
this.m_portalService = service;
}
…
}
Setters enable JSF to inject the
services selected by faces-config.xml
Page 53
Provide(MyTool.java)
access methods
…
public class MyTool implements ToolBean {
public User getCurrentUser() {
return m_userDirectoryService.getCurrentUser();
}
public String getCurrentSiteId() {
return m_portalService.getCurrentSiteId();
}
public boolean getCanCurrentUserModifySite() {
return m_siteService.allowUpdateSite(m_portalService.getCurrentSiteId());
}
…
}
Access methods enable the JSF page
to interact with the legacy services.
Page 54
Use(main.jsp)
in JSF
...
<%@ taglib uri="http://sakaiproject.org/jsf/sakai" prefix="sakai" %>
...
<f:view>
<sakai:view_container title="#{msgs.sample_title}">
<h:form>
JSF value references can access
...
<sakai:view_content>
JavaBean-style getters in service...
managed objects
<sakai:group_box title="#{msgs.sample_one_groupbox}">
<sakai:panel_edit>
...
<h:outputText value="Site ID (1.0.0)" />
<h:outputText value="#{MyTool.currentSiteId}" />
<h:outputText value="Current user" />
<h:outputText value="#{MyTool.currentUser.displayName}" />
<h:outputText value="Can current user modify the structure of this site?" />
<h:outputText value="#{MyTool.canCurrentUserModifySite}" />
</sakai:panel_edit>
</sakai:group_box>
...
</sakai:view_content>
</h:form>
</sakai:view_container>
</f:view>
Page 55
Identify Needed Services
http://cvs.sakaiproject.org/release/1.0.0/javadoc/index.html
Lots of services…
org.sakaiproject.service.framework.cluster
org.sakaiproject.service.framework.component
org.sakaiproject.service.framework.config
org.sakaiproject.service.framework.courier
org.sakaiproject.service.framework.current
org.sakaiproject.service.framework.email
org.sakaiproject.service.framework.log
org.sakaiproject.service.framework.memory
org.sakaiproject.service.framework.portal
org.sakaiproject.service.framework.session
org.sakaiproject.service.framework.sql
org.sakaiproject.service.legacy.alias
org.sakaiproject.service.legacy.announcement
org.sakaiproject.service.legacy.archive
org.sakaiproject.service.legacy.assignment
org.sakaiproject.service.legacy.calendar
org.sakaiproject.service.legacy.chat
org.sakaiproject.service.legacy.content
org.sakaiproject.service.legacy.digest
org.sakaiproject.service.legacy.discussion
org.sakaiproject.service.legacy.dissertation
org.sakaiproject.service.legacy.email
org.sakaiproject.service.legacy.event
org.sakaiproject.service.legacy.id
org.sakaiproject.service.legacy.news
org.sakaiproject.service.legacy.notification
org.sakaiproject.service.legacy.preference
org.sakaiproject.service.legacy.presence
org.sakaiproject.service.legacy.realm
org.sakaiproject.service.legacy.resource
org.sakaiproject.service.legacy.security
org.sakaiproject.service.legacy.site
org.sakaiproject.service.legacy.time
org.sakaiproject.service.legacy.user
… only a few that tools will likely access:
portal – Portal info
site – Manages Sakai sites
user – Current user, manage users
content – Uploaded files (resource
tool)
courier – Automatic refreshing when
content changes
email – Send email
log – Logging
sql – SQL access to Sakai DB
preference – User preferences
security – Check user permissions
(security)
Page 56
Resources and the Content API
(Javadoc)
• The ContentHostingService manages
uploaded files and folders, their properties,
and permissions.
Page 57
Resources and the Content API
(Javadoc)
package org.sakaiproject.service.legacy.content;
public interface ContentHostingService
extends ResourceService {
…
String getSiteCollection(String siteId);
ContentCollection getCollection(String collectionId);
ContentCollectionEdit addCollection(String collectionId);
ContentResource addResource(String id, String type, byte[] content,
ResourceProperties properties, int priority);
ContentResourceEdit editResource(String resourceId);
void commitResource(ContentResourceEdit editedResource);
void cancelResource(ContentResourceEdit editedResource);
boolean allowUpdateResource(String resourceId);
boolean allowUpdateCollection(String collectionId);
allowRename(String oldId, String newId);
allowAddCollection(String collectionId) ;
allowAddAttachmentResource();
ResourceProperties getProperties(String collectionOrResourceId);
…
Page 58
Legacy Service Patterns
• Objects - Service manages a collection of objects (ie,
ContentCollection, AnnouncementMessage, ChatMessage,
Calender, CalenderItem). Service manages entire lifecycle of the
objects.
• Security - allowXXX() methods check that the current user has
proper permissions for XXX operation. Also, some methods do
inline permissions checking and throw PermissionException if the
operation is not allowed.
• References - Many managed objects implement the Resource
interface, and can be referenced through an internal ID, a internal
string URI, or an externally accessible URL.
• Properties - Managed objects that implement Resource have
standard properties (created by, last modified, etc) and arbitrary toolspecific properties.
Page 59
Resources and the Content API
(Javadoc)
package org.sakaiproject.service.legacy.content;
public interface ContentHostingService
extends ResourceService {
…
Access objects
String getSiteCollection(String siteId);
ContentCollection getCollection(String collectionId);
ContentCollectionEdit addCollection(String collectionId);
Edit objects
ContentResource addResource(String id, String type,
byte[] content, ResourceProperties properties, int priority);
ContentResourceEdit editResource(String resourceId);
void commitResource(ContentResourceEdit editedResource);
void cancelResource(ContentResourceEdit editedResource);
boolean allowUpdateResource(String resourceId);
Check permissions
boolean allowUpdateCollection(String collectionId);
allowRename(String oldId, String newId);
allowAddCollection(String collectionId) ;
allowAddAttachmentResource();
ResourceProperties getProperties(String collectionOrResourceId);
…
Access properties
Page 60
Resources and the Content API
Example code snippet from the Presentation Service
package org.sakaiproject.service.legacy.content;
public class PresentationManagerImpl implements PresentationManager {
…
public List getPresentations() {
String home = contentHostingService.getSiteCollection(PortalService.getCurrentSiteId());
String collectionId = home + “Presentations/”;
try {
ContentCollection collection = contentHostingService.getCollection(collectionId);
int size = newMembers.size();
for (int i = 0; i< size; i++) {
Resource resource = (Resource) newMembers.get(i);
String nextId = resource.getId();
boolean isCollection =
resource.getProperties().getBooleanProperty(ResourceProperties.PROP_IS_COLLECTION);
if (isCollection) {
loadPresentation(nextId);
}
catch (PermissionException e) {
(Inform the user that they are not allowed to do that)
}
catch (IdUnusedException e) { …}
catch (TypeException e) { … }
catch (EmptyException e) { …}
return this.presentations;
}
}
Page 61
JSF toolConfig Variable
(Javadoc)
• The implicit JSF variable “toolConfig” provides convenient access to
some common textual information that might be displayed in a tool.
More properties will be available in the Sakai 1.5 release.
1.0.0 release
Added in 1.5.0 release (or in CVS now)
#{toolConfig.toolId}
#{toolConfig.pageId}
#{toolConfig.title}
#{toolConfig.siteId}
#{toolConfig.containingPage.title}
#{toolConfig.containingPage.containingSite.createdBy}
#{toolConfig.containingPage.containingSite.title}
#{toolConfig.containingPage.containingSite.modifiedBy}
#{toolConfig.containingPage.containingSite.description}
#{toolConfig.containingPage.containingSite.createdTime}
#{toolConfig.containingPage.containingSite.type}
#{toolConfig.containingPage.containingSite.modifiedTime}
#{toolConfig.containingPage.containingSite.skin}
#{toolConfig.containingPage.containingSite.shortDescription}
#{toolConfig.containingPage.containingSite.joinable}
#{toolConfig.containingPage.containingSite.published}
#{toolConfig.containingPage.containingSite.pubView}
Page 62
Developing Tools
Page 63
Tool Development
•
•
•
•
•
•
The MVC Pattern and JSF
Creating New Tools
UI Design using Faces
Service Injection
Application Context
Using the Style Guide
Page 64
Tools Glue Things Together
JavaServer Faces
GUI Element
Faces-config.xml
<xml>
<faces>
</xml>
Sakai Tool Class
Application Service Class
Action Method
Controller
Design
Pattern
View
Design
Pattern
Model
Design
Pattern
App Logic
Page 65
Creating a New Tool
•
•
•
•
Describe the UI using JSF pages.
Create an Application Service.
Implement the Application Services.
Create a Tool Class which uses the
application service via injection.
• Create Maven project files to compile and
deploy.
• Register the tool with the Component
Manager
Page 66
The Tool Class
• Written as a JavaBean so that
JavaServer Faces can access it. It is the
model part of the MVC pattern.
• Application and common services are
injected as needed.
• Handles initializations and data defaults.
• Implements JSF response methods
(events).
Page 67
Designing a UI
• Wire frames and layouts should be used to
get a feel for views needed and flow in the
application.
• Standard Sakai elements are defined to
ensure consistent look and feel
• Standard Sakai layouts are provided for
standard UI containers (boxes, toolbars,
forms, etc.).
Separate UI
Design
Pattern
Page 68
JSF is Used to Describe the UI
<sakai:view_container title="#{msgs.sample_title}">
<sakai:tool_bar> <sakai:tool_bar_item/> </sakai:tool_bar>
<sakai:instruction_message
value="#{msgs.sample_one_instructions}" />
<sakai:group_box
title="#{msgs.sample_one_groupbox}">
<h:inputText
value="#{MyTool.userName}" />
<sakai:date_input
value="#{MyTool.date}" />
<sakai:button_bar>
<sakai:button_bar_item
action="#{MyTool.processActionDoIt}
value="#{msgs.sample_one_cmd_go}" />
</sakai:button_bar>
Page 69
Backing Beans Handle Action
<h:inputText
value="#{MyTool.userName}" />
MyTool.userName() {
}
<sakai:date_input
value="#{MyTool.date}" />
MyTool.date() {
}
<sakai:button_bar>
<sakai:button_bar_item
action="#{MyTool.processActionDoIt}
value="#{msgs.sample_one_cmd_go}" />
</sakai:button_bar>
MyTool.processActionDoIt() {
}
Page 70
Service Injection
• Sakai uses a service injection pattern to
resolve dependencies at runtime.
• This is a kind of Inversion of Control (IoP).
• The Spring Framework handles
initialization of manager objects and
injects dependent services.
• This is all done in XML configuration files.
• Allows version dependencies.
Page 71
Application Context
Page 72
The Sakai Style Guide
• Includes illustrations of Sakai GUI
elements and widgets.
• JSF tags are described with options noted.
• Use considerations and best practice.
• Accessibility and uPortal guidelines.
• A draft version of the Sakai Style Guide
will be released during or following the
SEPP conference. See Rob Lowden’s
presentation.
Page 73
Tool Development Example
Page 74
Overview of Tool Development
•
•
•
•
•
•
Sample Methodology
Design the UI (mockups, wireframe)
Write the JSF descriptions
Write the application interface and service
Write and configure the tool
Porting tools
Page 75
A Development Methodology
Wireframes
Id Panels
and Modes
Make
Services
Make
Backing Beans
Develop
UI with JSF
Click Thru
Mockup
Developed by Ben Brophy and
the MIT Gradebook team.
Tool
Integration
Page 76
The Presentation Tool
• Upload a set of slides and make them
available as a presentation that can be
shown to one or more viewers with simple
controls.
• Currently implemented using a
Presentation service based on direct file
access.
• Being integrated with Sakai Legacy
services (Content API, etc).
• Use the “presentation” CVS root.
Page 77
Presentation Views
• The tool has four basic presentation
states:
Each of these state
diagram nodes become
a JSF view.
Page 78
Main Page
These are presentations
available to be shown
Buttons provide the
transition to other faces.
Presentations are
managed by an
application service
Uses the
Sakai Style
Guide Elements
Shows are run time
objects that are deleted
once complete.
Page 79
Presentation Controls
Only a single controller of a
presentation is allowed.
Three controls are provided
at this time: go to next, go to
previous, and end the
presentation. The current
slide is shown for reference.
Page 80
The Viewer Page
Any number of people may
view the presentation. The
interactive option is to exit the
viewer. Current slide is
synchronized via a file.
Viewer refreshes every 20
seconds (settable).
Page 81
JavaServer Faces
• Tool pages are described by JavaServer
Faces tags using a JSP file as a container.
• Each page is a JSF view.
• Sakai supports the standard JSF tags.
• Eventually, Sakai will have a full set of tags
which represent the Sakai GUI elements, to
be documented in the Sakai Style Guide.
• This set is partially implemented and under
development.
Page 82
JSF Navigation
• JSF Views are described in JSP files.
• Navigation from one view to the next is
handled by returning the name of the next
view. Return null to stay with current view.
• The transition from main.jsp to show.jsp is
handled by returning “show” out of
processActionShow().
Page 83
Faces-config.xml
<faces-config>
<application>
<message-bundle>org.sakaiproject.tool.mytool.bundle.Messages</message-bundle>
<locale-config><default-locale>en</default-locale></locale-config>
</application>
<managed-bean>
<description>Presentation Tool Bean</description>
<managed-bean-name>PresentationTool</managed-bean-name>
<managed-bean-class>org.sakaiproject.tool.mytool.PresentationTool</managed-bean-class>
<managed-bean-scope>tool</managed-bean-scope>
<managed-property>
<description>Service Dependency: Presentation Service</description>
<property-name>prMgr</property-name>
<value>
#{Components["org.sakaiproject.service.presentation.PresentationManager"]}
</value>
</managed-property>
</managed-bean>
</faces-config>
This is how the Presentation Service is
injected into the Presentation Tool. This
is a reference to the Sakai Component
Manager.
Page 84
<sakai:group_box title="#{msgs.pt_showing_groupbox}">
<h:form>
<sakai:tool_bar>
<sakai:tool_bar_item
action="#{PresentationTool.processActionJoin}"
value="#{msgs.pt_join_button}" />
</sakai:tool_bar>
<sakai:view_content>
main.jsp
<h:messages showSummary="true" showDetail="true" />
This is the “showing” box
on main page. The list of
presentations is similar,
but more complex.
<%-- the list of presentations --%>
<sakai:flat_list value="#{PresentationTool.prMgr.shows}" var="show">
<h:column> <%-- Check box column. --%>
<f:facet name="header">
<h:outputText value=""/>
</f:facet>
<h:selectBooleanCheckbox value="#{show.presentation.selected}"/>
</h:column>
<h:column> <%-- The title column. --%>
<f:facet name="header">
<h:outputText value="#{msgs.pt_col_head_title}" />
</f:facet>
<h:outputText value="#{show.presentation.title}"/>
</h:column>
</sakai:flat_list>
<sakai:button_bar>
<sakai:tool_bar_item
action="#{PresentationTool.processActionJoin}"
value="#{msgs.pt_join_button}" />
</sakai:button_bar>
</sakai:view_content>
</h:form>
</sakai:group_box>
Page 85
How JSF Looks Rendered
<sakai:group_box title="#{msgs.pt_showing_groupbox}">
<sakai:tool_bar> <sakai:tool_bar_item/> </sakai:tool_bar>
<sakai:flat_list
value="#{PresentationTool.prMgr.shows}"
var="show">
<h:column>
<f:facet name="header">
<h:outputText value="#{msgs.pt_col_head_title}" />
</f:facet>
<h:outputText value="#{show.presentation.title}"/>
</h:column>
<h:column><f:facet name="header">
<h:outputText value=""/>
</f:facet>
<h:selectBooleanCheckbox
value="#{show.presentation.selected}"/>
</h:column>
<sakai:button_bar>
<sakai:tool_bar_item
action="#{PresentationTool.processActionJoin}"
value="#{msgs.pt_join_button}" />
</sakai:button_bar>
Page 86
Messages.Properties
pt_new_button=New
pt_delete_button=Delete
pt_show_button=Show
pt_col_head_title=Title
pt_col_head_author=Author
pt_title_main=Presentation Tool
These are the messages
used on the Main view of the
presentation tool. Property
names are conventions to
make it easier to keep things
straight,
pt_presentation_groupbox=Presentations
The messages.properties file defines text resources that
can be inserted into JSF renderings, accessed by backing
beans, etc. Internationalization support is provided by
having alternative versions of this file with country code
extensions.
Page 87
Writing the Application Service
• Design the Application Service
– Think about reuse at this stage.
– Good object design will benefit all.
• Implement it as a POJO managed bean.
• Access is provided via a Manager class.
• Other services can be defined as
dependencies and injected by the Spring
container.
Page 88
Presentation Service - Interface
package org.sakaiproject.service.presentation;
public interface PresentationManager {
IdManager getIdManager();
void setIdManager (IdManager im);
Allows the IdManager to be injected.
public Show getShow (Id id);
This List is displayed as available
public List getShows();
shows.
public Show getCurrent ();
public void setCurrent (Show show);
public Show createShow (Presentation presentation);
public void deleteShow (Id id);
This List is displayed as available
public Presentation getPresentation (Id id);
presentations.
public List getPresentations();
public Presentation createPresentation(List slides, String title, String author);
public void deletePresentation (Id presentationId);
public Slide createSlide(String url, String name, String type);
public void load();
public void save();
Initialization is done automatically.
public void updateShowFile(Show show);
public Slide readShowFile(Show show); }
Page 89
Presentation Service Manager
public class PrManager implements org.sakaiproject.service.presentation.PresentationManager {
protected IdManager idManager = null;
private List presentations = new Vector();
private List shows = new Vector();
public List getPresentations() {
return this.presentations;
}
public Presentation createPresentation(List slides, String title, String author) {
Id id = null;
try { id = this.idManager.createId(); } catch (Throwable t) {return null;}
Presentation pres = (Presentation) new PrPresentation(id, slides, title, author);
this.presentations.add (pres);
return pres;
}
public void deletePresentation(Id id) {
Presentation pres = this.getPresentation (id);
this.presentations.remove(pres);
}
....
}
Page 90
Tool Implementation
• Tool classes typically have a set of
properties (data elements).
• Each property has get and set methods,
so that Spring can manage it as a bean.
• The tool is registered as a bean.
• The tool has JSF event handler methods.
Page 91
Tool Data Elements
public class PresentationTool
{
/**
Service Dependency: Presentation Service. */
protected PresentationManager prMgr = null;
….
}
The Presentation Manager is the main access point in the
Presentation Tool. Most of the faces code access information
via this object.
Page 92
Tool Access Methods
public class PresentationTool
{
…
public PresentationManager getPrMgr () {
return this.prMgr;
}
public void setPrMgr (PresentationManager mgr) {
this.prMgr = mgr;
}
….
}
Since the tool is a managed bean, both set and get methods
must be provided that correspond to the data element.
Page 93
Tool Event Handlers
public class PresentationTool {
public String processActionShow() {
Show currentShow = null;
List prs = this.prMgr.getPresentations();
for (int i=0; i<prs.size(); i++) { // Scan for selected presentation.
Presentation pres = (Presentation) prs.get(i);
if (pres.getSelected() == true) {
Returning the name of
currentShow = prMgr.createShow (pres);
this.shows.add (currentShow);
the next view is how
this.prMgr.setCurrent (currentShow);
transfer to the view
pres.setSelected(false);
happens.
}
}
if (currentShow == null) return “main”; // Nothing selected.
this.slide = currentShow.getCurrent();
// Set the current slide.
return "show"; // Transfer to the show page (the controller).
}
}
Page 94
Servlet Definition
• Each Sakai tool is defined as a Tomcat
servlet. In Sakai, servlets can access
code in other servlets, which not the case
for most web applications.
• This is handled by the Sakai Dispatcher
and the FacesServlet along with the Sakai
Component Manager.
• This also forces code into specific spots
for delivery (shared/lib, repository, etc.).
Page 95
Tool Web.xml
<web-app>
<display-name>sakai-present-tool</display-name>
<description>Sakai Presentation Tool</description>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup> 2 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
This is an edited version of the tool
web.xml file showing how the Faces
servlet is mapped.
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Page 96
Registering a Service
• Registering a service requires that the interface
being shared/lib and the component be included
in the local repository.
• The component.xml file is used to define how
dependent services are injected into this service.
• To make the service visible to other services or
tools, it must be registered with the Sakai
Component Manager.
• This is done in the web.xml file of the
component.
Page 97
Components.xml
<bean id="org.sakaiproject.service.presentation.PresentationManager"
class="org.sakaiproject.component.presentation.PrManager"
init-method="init"
singleton="true">
<property name="idManager"><ref bean="org.osid.id.IdManager"/></property>
<property name="hosting">
<ref bean="org.sakaiproject.service.legacy.content.ContentHostingService"/>
</property>
</bean>
Defines an identifier for the Presentation service and what class it is
associated with. IdManager is included as a dependency.
Page 98
Component web.xml
<web-app>
<display-name>sakai-present-component</display-name>
<description>Sakai Presentation Service Implementation</description>
<servlet>
<servlet-name>components</servlet-name>
<servlet-class>org.sakaiproject.component.ComponentsServlet</servlet-class>
<init-param>
<param-name>components-file</param-name>
<param-value>components.xml</param-value>
This is where the
</init-param>
is registered with
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>components</servlet-name>
<url-pattern>/components/*</url-pattern>
</servlet-mapping>
component
the Sakai
Component Manager. A URL
mapping is provided for
debugging (list components).
<welcome-file-list><welcome-file>index.html</welcome-file></welcome-file-list>
</web-app>
Page 99
Deployment
Page 100
Deployment and Development
•
•
•
•
•
•
•
Directory Structure
Deployment
Eclipse and Maven
The CVS Repository
Bug reporting and tracking
UI Review
Porting Existing Tools
Page 101
Structure of a Sakai Module
• A Sakai module is a collection of code
chunks that will be deployed to various
places in the Tomcat environment.
• Each module has an application service
API, application service implementation,
and a tool implementation.
/module name
/service
/component
/tool
Page 102
/
Module Directory Structure
/service
/component
project.xml
/tool
maven.xml
/src
Each of the three directories
under the module root has
pretty much the same
structure. Not all files are
present in all directories,
though.
/bundle
properties
/java
code
/webapp
web.xml
index.html
components.xml
/WEB-INF
faces-config.xml
/tool-name
JSF pages
Page 103
Configuration Files
• Component.xml
– Service components to be injected.
• Web.xml
– Servlet definitions
• Faces-config.xml
– JSF configuration (also injection)
• Messages.properties
– Display messages, etc.
Page 104
Deployment
• Deployment is the process of moving code
and resources into the Tomcat (etc)
environment which enables the tool to be
included in a particular Sakai environment.
• Software is broken down into three parts
forming a module:
– APIs (interface)
– Service Components
– Tool
Page 105
Code Deployment
Interface
Code
Tomcat
Shared/lib
Component
Code
Tomcat
webapps
Tool
Code
Local
Repository
Page 106
Creating a Module from Scratch
• Create a module directory structure similar
to other Sakai modules.
• Use other configuration files as templates.
• Design and write the application service
interface.
• Implement the application service
• Design UI and describe in JSF pages.
• Write the tool to handle JSF events ….
Etc.
Page 107
Working with Maven
• Maven is a powerful software configuration and
management tool.
• Project files describe software dependencies
which are resolved against project goals.
• Each module has its own project.xml file.
• The deploy module has a special project.
• http://maven.apache.org/start/download.html
Page 108
The Maven Project File
• The maven documentation describes
how to set up dependencies. Use other
modules as a project file template.
• If you stray from the Sakai templates,
you are on your own! Be careful of
version agreement.
• Maven will generate error messages if it
fails and indicate “Build Failed” if not
successful.
Page 109
Eclipse Support
• Eclipse provides several plug-ins which
can simplify the development process:
– base XML editing
– JSF layout
– Servlet definitions and editing
– Maven project editing
• Eclipse is strongly recommended as the
best IDE for developing Sakai tools.
• myEclipse is even better since it provides
additional tools and better XML support.
Page 110
The Sakai CVS Repository
• Sakai has created a public CVS repository
– cvs.sakaiproject.org
• Top level branches for:
– Sakai Framework
– Sakai Assessment and Assignment Manager
• Public read only access
• Project leaders will have commit access
Page 111
UI and QA Review
• Sakai is setting up a UI Review team to
review submitted UI designs, prototypes,
and completed code.
• Similarly, a Sakai QA team is being set up
to test code and ensure that it meet Sakai
quality standards.
• Contact Mark Norton for now, more
information later.
Page 112
Bug Reporting
• Sakai has settled on using JIRA as it’s bug
reporting and tracking system.
• Report problems at bugs.sakaiproject.org
• If you are developing tools, you may want
to register as a developer. Send mail to
[email protected].
• Registering means fixing bugs reported
against your code.
Page 113
Debugging Techniques
• Use JUnit testing.
• Attaching to Tomcat
– You can set Tomcat up to listen on a debug
port and then connect to it from Eclipse.
• Problems with injection
– Injection problems will generate entries in
tomcat console and log files.
– Make sure of configuration files and
constructors.
Page 114
Porting Tools to Sakai
• Use existing page snapshots to design
JSF
• Separate out presentation from application
logic.
• Pull application services out into stand
alone services.
• Re-code to use existing services.
• Use similar tool implementations to help
with configuration files (etc).
Page 115
Development Projects
• Project coordination via SEPP work
groups.
• Write up a proposal containing who, what,
and by when and send to me.
• Projects can be managed and developed
by a single institution, or set up as a
collaborative effort.
Page 116
How Code is Released
• Currently, Indiana is controlling the 1.5
release.
• Later, a release manager will be in charge
of what goes into a particular release.
• Submissions should be vetted by the
Sakai QA and UI review teams.
Page 117
Portability
Page 118
Portability Considerations
• Sakai is an integration framework which
allows tools to be combined with services
using a set of guiding principles (TPP)
• Sakai tools are intended to be portable to
other Sakai sites.
• Non-Sakai tools can be brought into the
Sakai environment with limited integration.
Page 119
Porting Applications
• Tools can be developed to be portable
with other frameworks
– Use OSIDs and Web Services
• Or tools can be ported and integrated
into Sakai
– Follow the guidelines for porting a tool.
– Use Sakai APIs and TPP.
– Test final functionality against the original.
Page 120
Interoperability Considerations
• Use industry interoperability standards
where available:
– IMS specifications, SCORM profile
– IEEE and ISO standards
– W3C, IETF, GRID, etc.
• Services should include the concept of
import and export using these interchange
standards.
Page 121
Sneak Preview!
Page 122
Sakai 1.5
•
•
•
•
•
•
•
SAMigo
Grade book (maybe)
OSP
Presentation Tool
Framework improvements
More common services
Gap satisfaction
More information on the
future of Sakai releases
will be reported during the
SEPP Conference starting
tomorrow.
Page 123
Sakai 2.0 - Spring 2005
• Significant replacement of legacy tools
– TPP Compliant, using OKI and Sakai APIs
– New and improved tools based on Sakai-wide
requirements process
– Each partner institution will focus on a set of
tools to develop
• SEPP partners will be involved in the new tool
development based on ability and commitment.
Page 124
The Sakai 2 Framework
Browser
Apache &
Tomcat
response and request
Other
Portals
uPortal
JavaServer Faces
rendering
Tool
Component
Manager
Spring
injection
injection
ORM
Hibernate
Application
Services
Common
Services
Page 125
Sakai and OKI
• OKI has produced a series of APIs to support
learning management system portability:
– Enterprise Integration
– Tool Portability
• The OKI APIs allow for flexible out-of-band
agreements
• The Sakai APIs are designed to be closely
aligned with the OSIDs.
• Sakai will continue to work closely with OKI and
make recommendations for changes to the
OSIDs.
Page 126
IMS Tool Portability SIG
• Sakai has approached IMS to develop a tool
portability specification.
• A charter proposal has been written and
approved by the IMS Technical Board.
• This spec will allows tools to be ported between
environments by identifying certain “core”
services: AuthN, AuthZ, User/Group, and
Repository.
• If your organization is a member of IMS, please
consider participating in this effort.
Page 127
Things You Can Do
Page 128
Call to Action
•
•
•
•
•
•
•
Participate in the discussion groups
Develop in-house Sakai expertise
Install and review Sakai 1.0 (etc)
Develop or port tools to Sakai
Contribute requirements
Share lessons learned
Be an active voice in how SEPP is run
Page 129
Read SEPP Communications
• Update Message
– A weekly electronic newsletter
– Latest news
– References to papers and documentation
– Reports from discussion groups
• White Papers
• Reports on Events
• SEPP Conference
Page 130
Participate in
SEPP Discussion Groups
•
•
•
•
•
•
•
Requirements – UC Berkeley
Migration – Columbia
Cross Language Support – U. Washington
User Interface – Dartmouth
Content & Authoring – U. Wisconsin
Libraries - Columbia
Developers – Mark Norton
Page 131
Development Discussion Groups
• The “Sakai Devel” group is now the default
place to ask questions, report results, etc.
• This is a public group open to all.
• The SEPP group will evolve into SEPP
development coordination, development
support, and other issues.
Page 132
Sakai Tool Development Skills
•
•
•
•
•
•
Java Beans (dependency insertion)
Understanding of Servlets
Interface design and implementation
OKI OSIDs and Sakai APIs
Maven deployment techniques
JavaServer Faces and Sakai GUI
elements
• Hibernate is useful if developing new APIs
Page 133
Resources
• Mark J. Norton
– [email protected]
– 781-275-4070
• http://sakaiproject.org/
• http://collab.sakaiproject.org/
– sakai-user worksite
– sakai-devel worksite
• http://cvs.sakaiproject.org/
Page 134
Questions?
Page 135