One difficulty in developing Portlets are the lack of tutorial guides. And when you find a tutorial it generally is very specific to one portal. This article will demonstrate the steps needed to create a very basic Portlet using uPortal. However, the steps in this guide that are specific to uPortal will be kept to a minimum. The process will be very similar on other portals (especially most open source portal servers).

Basic Directory Structure

To begin with it's important to understand the core of the Java Portlet API (JSR 168). This is the javax.portlet.Portlet interface. Implementing this interface is the only Java code you must write to create a new Portlet (I am excluding using any kind of framework like Struts or Spring Portlet MVC from this discussion). Once you have a class that implements the Portlet interface the other minimum requirements for your application are a portlet.xml and web.xml files. These files (and your Portlet .class file) must be in a specific location according to the Servlet and Portlet specs. Once you have these files in the right place, you simply create a war file by zipping them up. The following shows a simple application layout. If you've done Servlet programming the layout should be familiar.


WEB-INF/
WEB-INF/web.xml
WEB-INF/portlet.xml
WEB-INF/classes/
WEB-INF/classes/net/
WEB-INF/classes/net/unicon/
WEB-INF/classes/net/unicon/portlet/
WEB-INF/classes/net/unicon/portlet/HelloPortlet.class

web.xml

Your web.xml file is required by the Servlet standard, but can otherwise be a simple file only declaring the <web-app> tag. Here's the minimum you can, and often will, use:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
                         "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
   
</web-app>

portlet.xml

The portlet.xml is not as short, but is still fairly easy. I highly recommend using an editor capable of XML validation. I use Eclipse with the Web Tools Platform set of plugins. For a new Portlet application you can probably copy this example and customize it for your own use. You will typically need to change the <portlet-class> element to match the Java class you wrote. To be a little more aggressive you might want to update the other description and name type elements.


<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
             version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
                                 http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">

        <portlet>
                <description xml:lang="en">A Hello World Portlet</description>
                <portlet-name>HelloPortlet</portlet-name>
                <display-name xml:lang="en">Hello World</display-name>
                <portlet-class>net.unicon.portlet.HelloPortlet</portlet-class>
                <expiration-cache>-1</expiration-cache>
                <supports>
                        <mime-type>text/html</mime-type>
                        <portlet-mode>view</portlet-mode>
                </supports>
                <supported-locale>en</supported-locale>
                <portlet-info>
                        <title>Hello World</title>
                        <short-title>Hello</short-title>eb
                        <keywords>portlet, hello, world</keywords>
                </portlet-info>
        </portlet>
</portlet-app>

<expiration-cache> is technically an optional element, but I encourage you to include it. uPortal will not work with a Portlet that does not include this element.

HelloPortlet.java

The final piece to this puzzle is the Portlet Java code. Here is an extremely simple version. This version extends the convenience class javax.portlet.GenericPortlet. GenericPortlet provides simple implementations of all the javax.portlet.Portlet methods, allowing you to override and implement only the methods where you absolutely need to. In my example, I've provided a simple implementation of the render method.


package net.unicon.portlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloPortlet extends GenericPortlet {

    public void render(RenderRequest request, RenderResponse response)
        throws PortletException, IOException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("Hello World!");
        out.flush();
    }
}

Compile and Build

To compile your Portlet Java code you will need to get the portlet-api-1.0.jar file from the uPortal lib/ directory or you can try to download it from some place like the ibiblio repository. After compiling, simply create a war file using the JDK jar utility following the directory structure outlined above. This process can also be automated with ant or maven.


$ jar cvf hello.war WEB-INF
added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/net/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/net/unicon/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/net/unicon/portlet/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/net/unicon/portlet/HelloPortlet.class(in = 944) (out= 510)(deflated 45%)
adding: WEB-INF/lib/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/web.xml(in = 345) (out= 224)(deflated 35%)
adding: WEB-INF/portlet.xml(in = 1227) (out= 429)(deflated 65%)

Deploy

After this point the steps are specific to the portal you are using. In uPortal you must deploy the portlet web application using a uPortal ant target. As of uPortal 2.5.3 this action must be performed from the root of the uPortal source directory.


uPortal_2-5-3_GA$ ant deployPortletApp -DportletApp=/home/holdorph/hello.war
Buildfile: build.xml

prepare:

compile:

deployPortletApp:
     [echo] Invoking Portlet Application Deployment Tool
     [java] Deploying 'hello' ... Finished!
     [java] Preparing web archive 'hello' ... Finished!

BUILD SUCCESSFUL
Total time: 5 seconds

Publish

After the Portlet is deployed, it is necessary to restart the application server (e.g., Tomcat). When the application server is ready, logon to uPortal as an administrator. Go to Channel Manager and Publish a New Channel. During the Channel Manager publishing process it is necessary to select several values. The only value unique to Portlets in this process is the Portlet Definition ID. This value comes from the web application name concatenated with the value of the <portlet-name> element from the portlet.xml file. Using the above example, I would take the hello from hello.war and HelloPortlet from the portlet.xml file. The following is a screenshot of the final Channel Manager review screen that summarizes all the values I used to publish my Portlet.

Subscribe

The final step is to subscribe to the Portlet. Go into preferences and add the portlet to your layout. If you didn't make a mistake along the way, you should see something like the following.

Summary

Now this is obviously a trivial example. It's important to understand the basics before you begin using the other features of the Portlet API or any kind of framework. Even if you use a framework, you can not eliminate the need to have a web.xml, portlet.xml and some class that implements the javax.portlet.Portlet interface. Be sure to check out my blog. In the near future, I plan to post a new Google Portlet that is only slightly more complicated then this Hello World example. The Google Portlet I plan on showing uses PortletPreferences and a JSP.

---- Cris J H

AttachmentSize
Hello_World_Portlet_Tutorial.zip111.48 KB