PortalTools - IT Mill Toolkit Portal Integration

Introduction – Scope and Purpose

Since version 5.2.0, portal integration is a part of the IT Mill Toolkit core package.

This article will show how to use IT Mill Toolkit to make Portlet applications, as defined by JSR-168. Specifically, we will deploy a Portlet to Liferay, though it should be trivial to deploy on other Portlet Containers as well.

It is assumed that the reader has (at least basic) knowledge of Java, Portlet and Servlet technologies, and to some extent IT Mill Toolkit applications (the main ideas can be understood without knowledge in the latter.)

The purpose is to show a simple method to make a RIA/ajax IT Mill Toolkit application work in a Portlet environment. We will not be going into details about Portlet programming, or IT Mill Toolkit programming, and the code provided should be viewed as a starting point to expand upon.

Limitations

Although many IT Mill Toolkit portlets can be shown on one page, they must all use the same Widgetset. You can get around this limitation by creating one widgetset that contains all the components for all applications.

QuickStart

To quickly deploy and try some IT Mill Toolkit portlets:

First get a Liferay bundle, install (unzip), and run (bin\startup.bat or bin/startup.sh)

Then deploy IT Mill Toolkit.war in Liferay by copying it to:

  • XP: C:\Documents and Settings\<user name>\liferay\deploy\
  • Vista: C:\Users\<user name>\liferay\deploy\
  • Linux: /home/<user name>/liferay/deploy/
  • Mac OS X: /Users/<user name>/liferay/deploy/

Then choose "Add applications" - a number of applications will show up in the "IT Mill Toolkit" -category.

The Method

The implementation consists of two main parts; an IT Mill Toolkit application and a portlet.

The portlet provides the actual portal integration; it communicates with the Portlet Container, and renders the initial UI code that "kickstarts" the ajax communication with the IT Mill Toolkit application, which is running as a servlet. The portlet also provides the servlet with portlet-specific functionality and data that might be needed, such as window state and user information.

The IT Mill Toolkit application does not necessarily need to be modified at all for this to work; however, in order to use portlet-specific data, it must communicate with the portlet. The servlet and portlet communicates via the user session, a method that requires the portlet and servlet to run in the same context. In practice, both servlet and portlet are packaged in the same WAR, which is then deployed as one web application.

Note that it is possible to access the servlet directly, bypassing the portlet, so the servlet should check this (e.g. portlet found in session, valid user logged in) if necessary.

Details

We'll be using the PortletDemo -application as an example - it can be found in the IT Mill Toolkit demo -package.

The portlet is implemented in the ApplicationPortlet class, it communicates with the PortletDemo -application via the PortletContext:

        if (getContext() instanceof PortletApplicationContext) {
            // Listen for portlet events
            PortletApplicationContext ctx = (PortletApplicationContext) getContext();
            ctx.addPortletListener(this, new DemoPortletListener());
        } else {
            // not running as a portlet
        }

The PortletListener will receive two types of 'events':

        public void handleActionRequest(ActionRequest request,ActionResponse response) {
           // handle portlet actio
        }

        public void handleRenderRequest(RenderRequest request, RenderResponse response) {
           // handle portlet render request; NOTE: you can not write to the response
        }

You 'connect' the ApplicationPortlet by specifying the "application" init-param in portlet.xml:

        <portlet>
                <portlet-name>PortletDemoPortlet</portlet-name>
                <display-name>IT Mill Toolkit PortletDemo</display-name>
                <portlet-class>com.itmill.toolkit.terminal.gwt.server.ApplicationPortlet</portlet-class>
                <init-param>
                        <name>application</name>
                        <value>PortletDemo</value>
                </init-param>               
                <supports>
                        <mime-type>text/html</mime-type>
                        <portlet-mode>view</portlet-mode>
                        <portlet-mode>edit</portlet-mode>
                        <portlet-mode>help</portlet-mode>
                </supports>
                <portlet-info>
                        <title>PortletDemo</title>
                        <short-title>PortletDemo</short-title>
                </portlet-info>
        </portlet>

Note that the value for the "application" init-param is the servlet mapping (url), not the servlet name.

For Liferay use, you'll need to set up liferay-portlet.xml and liferay-display.xml with matching information:

<liferay-portlet-app>
        <portlet>
                <portlet-name>PortletDemoPortlet</portlet-name>
                <instanceable>true</instanceable>       
                <ajaxable>false</ajaxable>
        </portlet>
[...]
<display>
        <category name="IT Mill Toolkit">
                <portlet id="PortletDemoPortlet" />
[...]

NOTE: An undocumented feature in Liferay makes it impossble to use the same name for the servlet and the portlet, hence the PortletDemo (application) maps to the PortletDemoPortlet (portlet).

Notes

Some other important configuration issues to remember:

If you deploy by copying the war to Liferays deploy directory, the war must be named according to the display-name in web.xml (e.g. <display-name>IT Mill Toolkit</display-name> --> IT Mill Toolkit.war)

When deploying to Liferay, the WAR can not contain liferay jars that you might have used during develpoment, e.g portal-kernel.jar nad portal-service.jar.

The portlet-name in portlet.xml and liferay-portlet.xml must be the same, and must match the id in liferay-display.xml liferay-display.xml.

The security-role-ref and role-mapping in portlet.xml and liferay-portlet.xml are not strictly necessary, but map general portlet roles to Liferay roles; refer to portal documentation for specifics.

Don't forget the portlet-info section in portlet.xml - Liferay tends to display "null" as name for the portlet if it's missing.

References