Integration to the Sakai's platform

Integration of a GWT Rich Client Tool to the Sakai's platform

We want to talk about some of the concerns that we had about the integration of a GWT Rich Client tool to the Sakai's platform and how they have been addressed.

Exploring Differents Solutions

Firstly, we needed to prove the feasibility of the integration of a tool based on GWT with the Sakai's platform.

Hopefully, Sakai is based for the most part on a services architecture using the Spring Framework and the integration of GWT to Spring has already been done by others George Georgovassilis .

An important issue was : How to reach Spring services from the RPC servlet?

Anyway, Spring is well known for its integration capabilities, but we have to find the best way.

Three possibilities were explored :

  • Centralized approach:

Using the ApplicationContext with one main Backing Bean able to reach other Spring services

  • Not centralized approach:

We directly call each Bean Identifier of the Spring service we need (as necessary) from the RPC Servlet.

  • Spring service mapping:

We also looked at the Open Source GWTSpringController library of George Georgovassilis.

It was working fine, but we found blocking situation with the actual Sakai. The library did not use the same Spring version (2.5). So using different class loader we were unable to share the same Spring context with Sakai.

Centralized approach finally adopted

After experimental work, the Centralized approach involving a main Backing Bean and the Spring applicationContext was finally adopted.

With the help of people from Sakai Québec (CRIM), we did the integration of GWT and Sakai. What we did is pretty similar to the suggestion of Luis Filipe Lobo in the Sakai dev Forum, using servlet extension of GWT servlet, Sakai listener and tool registering into Sakai.

Diagram of the integration

Let us consider, in order to fix the ideas, a figure of the centralized approach.

You can see the Main Backing Bean from which we access to other Spring services is allowed.

To successfully register this Main Backing Bean, you have to define an applicationContext.xml file and include a ContextLoaderListener into your Webapp configuration file web.xml

 

 

The roles of the Java Servlets

Java Servlets running on the Sakai's server are used for:

  • RPC communication with the GWT client (GWT RPC Servlet)

Each GWT Servlet is a standard Java Servlet that extends the GWT RemoteServiceServlet class

The OsylEditorGwtServiceImpl.java file resides into the folder server (i.e. /osyl-tool/tool/src/java/org/sakaiquebec/opensyllabus/server/) of the opensyllabus-tool project.

Extract from OsylEditorGwtServiceImpl.java
...
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.sakaiquebec.opensyllabus.client.rpc.OsylEditorGwtService;
...
import org.sakaiquebec.opensyllabus.server.OsylBackingBean;
import org.springframework.web.context.WebApplicationContext;
...
import org.sakaiproject.tool.api.Tool;
...
public class OsylEditorGwtServiceImpl extends RemoteServiceServlet implements
	OsylEditorGwtService {
...
    private OsylBackingBean osylServices;
    private ServletContext servletContext = null;
    private WebApplicationContext webAppContext = null;
...
    public OsylEditorGwtServiceImpl() {
	;
    } // must have
...
    public void init() {
	servletContext = getServletContext();
	webAppContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
	// Spring bean injection
	if (webAppContext != null) {
	    osylServices = (OsylBackingBean) webAppContext.getBean("backingBean");
	}
...
}
  • Indirect Spring services access
  • Security management
  • Extra request information access
Spring Application Context File


So, we have to define a Spring Application Context using the applicationContext.xml file which resides into the folder WEB-INF (i.e. /osyl-tool/tool/src/webapp/WEB-INF/) of the opensyllabus-tool project.

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
	"http://www.springframework.org/dtd/spring-beans.dtd">
<!-- This file generated by Sakai App Builder -AZ -->
<beans>
	<!-- list the backing beans here -->
	<bean id="backingBean"
			class="org.sakaiquebec.opensyllabus.server.OsylBackingBean"
			init-method="init">
		<property name="osylResourceService"
			ref="org.sakaiquebec.opensyllabus.api.OsylResourceService" />
		<property name="osylSecurityService" 
			ref="org.sakaiquebec.opensyllabus.api.OsylSecurityService" />
		<property name="osylConfigService" 
			ref="org.sakaiquebec.opensyllabus.api.OsylConfigService" />
	</bean>
</beans>

Sakai's tool registration & configuration

  • Tool registration is done by providing the tool xml file

In order to define a tool in Sakai you have to register it by providing an XML definition of your tool.

That is, sakai.opensyllabus.tool.xml file into the folder tools (i.e. /osyl-tool/tool/src/webapp/tools/) of the opensyllabus-tool project.

sakai.opensyllabus.tool.xml
<?xml version="1.0"?>
<registration>
	<tool
		id="sakai.opensyllabus.tool"
		title="OpenSyllabus"
		description="Sakai OpenSyllabus Tool">
		<category name="course" />
		<category name="project" />
		<keyword name="GWT,syllabus" />
	</tool>
</registration>
  • Tool configuration is done using the web.xml file

The Web application configuration file web.xml resides into the folder WEB-INF (i.e. /osyl-tool/tool/src/webapp/WEB-INF/) of the opensyllabus-tool project.


In addition, we have to include a ToolListener and a ContextLoaderListener into the web.xml

Extract from web.xml
...
   <listener>
      <listener-class>org.sakaiproject.util.ToolListener</listener-class>
   </listener>
   <listener>
      <listener-class>org.sakaiproject.util.ContextLoaderListener</listener-class>
   </listener>
...

Thereafter, there are also other information related to configuration (Sakai filters, servlet definitions, etc) contained into the web.xml configuration file.

Here is a full web.xml sample file :

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>sakai-opensyllabus-tool</display-name>
	<description>sakai-opensyllabus-tool</description>

	<filter>
		<filter-name>sakai.request</filter-name>
		<filter-class>org.sakaiproject.util.RequestFilter</filter-class>
		<init-param>
			<param-name>tool.placement</param-name>
			<param-value>false</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>sakai.request</filter-name>
		<servlet-name>sakai.opensyllabus.tool</servlet-name>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
	</filter-mapping>

	<servlet>
		<servlet-name>sakai.opensyllabus.tool</servlet-name>
		<servlet-class>uk.ac.cam.caret.sakai.WebappToolServlet</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>

	<servlet>
		<servlet-name>sakai.opensyllabus.editor</servlet-name>
		<servlet-class>org.sakaiquebec.opensyllabus.server.OsylEditorGwtServiceImpl</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>sakai.opensyllabus.editor</servlet-name>
		<url-pattern>/OsylGwtService</url-pattern>
	</servlet-mapping>

	<listener>
		<listener-class>org.sakaiproject.util.ToolListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.sakaiproject.util.ContextLoaderListener</listener-class>
	</listener>
</web-app>

The roles of the JSP entry page

Now, we will see what are the roles of the JSP entry page (index.jsp) which resides in the folder webapp (i.e. /osyl-tool/tool/src/webapp/) of the opensyllabus-tool project.

  • First it gives access to the GWT compiled JavaScript.

Here is a sample of the script tag you have to put into your index.jsp page to give access to the GWT compiled JS.

Extract from index.jsp
<!-- This script loads our GWT compiled module.        -->
<!-- Any GWT meta tags must be added before this line. -->
<script language='javascript'
        src='<%=request.getContextPath() %>/org.sakaiquebec.opensyllabus.OsylEditorEntryPoint

             /org.sakaiquebec.opensyllabus.OsylEditorEntryPoint.nocache.js'>
</script>
  • With JSP scriptlet (directly coded in the index.jsp) you can use specific logic to choose between different compiled GWT applications
  • Provides the CSS Link
Extract from index.jsp
<link rel="stylesheet" type="text/css" href="osylcoconfigs/default/skin/osylcore.css" />
  • Initializes some META to set the language (I18N)?

For instance, you can initialize the locale to use for the GWT interface.
In the sample code below, we show an access to the Sakai user preference language (via the ResourceLoader) and the setting of the locale GWT property.

Extract from index.jsp
...
<%@ page import="org.sakaiproject.util.ResourceLoader"%>
...
<%
   ResourceLoader rb = new ResourceLoader();
   Locale sessionLocale = rb.getLocale();
   String locale = sessionLocale.toString();
   ...
%>
<html>
   <head>
      <meta name="gwt:property" content="locale=<%=locale%>">
       ...
  • Controls the tool display size

With the index.jsp page, you can also control the tool display size by using some special Sakai provided attributes. (Please, search in the Sakai's documentation to get more information about the "sakai.html.body.onload" attribute).

Extract from index.jsp
...
 <html>
   <head>
    ...
    <!-- Headers from Sakai                        -->
       <%= request.getAttribute("sakai.html.head") %>
       <script> // Size of the JS application
          function myLoad() {
             setTimeout("<%=request.getAttribute("sakai.html.body.onload") %>", 500);
          }
       </script>
   </head>
   <body onload="myLoad()">
   </body>
</html>
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.