Sun Java System Portal Server 7.1 Developer's Guide

Chapter 14 Extending the GenericPortlet Abstract Class

This chapter contains the following sections:

Introduction to Extending the GenericPortlet Abstract Class

This chapter includes instructions for extending the GenericPortlet abstract class. It includes instructions to create a sample portlet named PrefPortlet. In the view mode, this portlet displays a salutation. In the edit mode of PrefPortlet, the user can change that salutation. The modified salutation is saved into the preference to be used for subsequent requests to the portlet.

Developing the Class File

This section includes:

GenericPortlet Class

This section includes:

Methods to Override

When extending from the GenericPortlet abstract class, the following methods should be overridden:

public void init(PortletConfig config)

The container calls this method once when the portlet object is created.

protected void doView(RenderRequest req, RenderResponse resp)

The render method calls this method when the portlet is in VIEW mode. The GenericPortlet class’ default implementation only throws an exception.

protected void doEdit(RenderRequest req, RenderResponse resp)

The render method calls this method when the portlet is in EDIT mode. The GenericPortlet class’ default implementation only throws an exception.

protected void doHelp(RenderRequest req, RenderResponse resp)

The render method calls this method when the portlet is in HELP mode. The GenericPortlet class’ default implementation only throws an exception.

public void processAction(ActionRequest req, ActionResponse resp)

The GenericPortlet class includes a default implementation that only throws an exception.

public void destroy()

The container calls this method on the portlet when the portlet is being taken out of service.

Render Request Processing

The request from the client is encapsulated in a RenderRequest object. The portlet uses this object to access information about the request that was received from the client by the Portal Server. Typically, the current portlet mode and request parameters included in the incoming request is the information that is accessed. The portlet’s response is encapsulated in a RenderResponse object. Portlet use this object to set the content type of the response and send their portlet content to the portlet container.

Each request object is valid only within the scope of a particular processAction() or render() method call.

Action Request Processing

Action URL requests from the client are encapsulated in an ActionRequest object. The portlet uses ActionRequest objects to gain access to the details of the incoming HTTP request from the client. The portlet’s response to the action request is encapsulated in the ActionResponse object. The portlet uses this object to set the new portlet mode (typically the VIEW mode) and send information to the subsequent render request after action request has been proceessed.

Portlet Preferences

The portlet specification mandates that portlet container provide persistent store for portlet preferences. Portlets can only access their preferences during requests (render or action). Portlet preferences are encapsulated by the PortletPreferences interface.

Portlets can update their preferences within the processing of the processAction() method. An exception is thrown if the portlet attempts to update preferences during a render request.

User preferences are stored and accessed through a PortletPreferences object. A handle to this object can be obtained by using both RenderRequest.getPreferences() and ActionRequest.getPreferences(), depending from which method the attempt to access the preferences is made. An individual preferences is called using getValue() or getValues(), for single string value or multiple string values respectively. The methods setValue() and setValues() modifies the preference, but no changes are stored in the datastore until the method store() is called. All user preferences must be defined in the portlet deployment descriptor.

Preferences defined at the organization will affect the user’s preference only if the user’s preference has not been defined and only until the user modifies the individual preference. Once preferences have been modified, it will retain its value, even if blank, until the reset() method is called on the preference.

LDAP attributes can only be accessed through the portlet implementation of a user info Map. All attributes needed within the portlet must be defined in the portlet deployment descriptor. The attribute map of all such defined attributes can be retrieved using either ActionRequest.getAttribute(PortletRequest.USER_INFO) or RenderRequest.getAttribute(PortletRequest.USER_INFO). Each attribute can then be retrieved using Map.get("Attribute Name").

Only user attributes defined in the deployment descriptor can be read. The user info map returned is unmodifiable.

Example Portlet Class File

Following example contains the class file for the sample PrefPortlet.


Example 14–1 PrefPortlet.java File


package examples;

import javax.portlet.GenericPortlet;
import javax.portlet.ActionRequest;
import javax.portlet.RenderRequest;
import javax.portlet.ActionResponse;
import javax.portlet.RenderResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletURL;
import javax.portlet.PortletMode;
import javax.portlet.PortletPreferences;
import javax.portlet.WindowState;
import java.io.IOException;
import java.io.PrintWriter;

public class PrefPortlet extends GenericPortlet {
    public void processAction(ActionRequest request, 
		ActionResponse response) 
		throws PortletException {
        // process the salutation set by the user 
			in the edit mode.
        String salutation = request.getParameter("SALUTATION");
        try {
            PortletPreferences pref = request.getPreferences();
            pref.setValue("salutation", salutation);
            pref.store();
        } catch (Exception e) {
            throw new PortletException(e.getMessage());
        }
        // return the user back to the view mode and normal state
        response.setPortletMode(PortletMode.VIEW);
        response.setWindowState(WindowState.NORMAL);
    }

    public void doView(RenderRequest request,RenderResponse response) 
		throws PortletException,IOException {
        // displays the salutation stored in the preference.
        PortletPreferences pref = request.getPreferences();
        String salutation = pref.getValue("salutation","");
        response.setContentType(request.getResponseContentType());
        PrintWriter writer = response.getWriter();
        writer.write("Hello " + salutation);
    }

    public void doEdit(RenderRequest request,RenderResponse response)
		throws PortletException,IOException {
        PortletURL actionURL = response.createActionURL();
        response.setContentType(request.getResponseContentType());
        PrintWriter writer = response.getWriter();
        writer.print("<form method=\"post\" action=\"" 
			+ actionURL.toString());
        writer.println("\">");
			writer.println("<center><p>Salutation: <input type=
			\"text\" name=\"salutation\"></p>");
			writer.println("<input type=\"submit\" value=\"Submit\">");
			writer.println("</form>");
    }

    public void doHelp(RenderRequest request, RenderResponse response) 
		throws PortletException {
        response.setContentType(request.getResponseContentType());
        try {
            response.setContentType(request.getResponseContentType());
            PrintWriter writer = response.getWriter();
            writer.write("Pref Portlet Help<p><p>");
        } catch (IOException e) {
            throw new PortletException("PrefPortlet.doHelp exception", e);
        }
    }
}

Compiling the Portlet

The portlet API is contained within a single JAR file. When compiling a portlet, include the classpath to the JAR file in order for the compilation to succeed. Ensure that PortalServer-base/lib/portlet.jar is in your classpath when compiling the portlet. For example, to compile, type:

javac -classpath PortalServer-base/lib/portlet.jar PrefPortlet.java

Note –

This compiled class file must be included in the WAR file that will be deployed on the Portal Server using the psadmin deploy sub command.


Creating a Portlet Web Application

Assemble the portlet class file and the XML fragments into a portlet web application. A portlet web application must be packaged as a web application archive (WAR) file.

The portlets contained within the WAR file are described using the deployment descriptor. The portlet deployment descriptor must be in the portlet.xml file. The structure of the portlet.xml file is defined by the portlet.xsd file located in the PortalServer-base/dtd directory. The portlet.xml file must be placed into the same location as the web.xml file.


Note –

The Portal Server software includes its own portlet deployment descriptor in the sun-portlet.xml file. This file includes information about how the portlet container within the Portal Server software should manage the deployed portlets.


ProcedureTo create a portlet web application

  1. Create a complete portlet.xml file that includes the declaration for all the portlets.

    Creating a Portlet Web Application contains the portlet.xml file that includes the declaration for the sample portlet. The portlet.xml file includes name, class, and cache information. Since the sample portlet also uses preferences, the preference setting is also included in the portlet.xml file. Also PrefPortlet supports the EDIT as well as HELP mode; so the supported modes are specified in the portlet.xml file.

    portlet.xml File for the PrefPortlet


    <?xml version="1.0" encoding="UTF-8"?>
    <portlet-app xmlns="http://java.sun.com/xml/ns/portlet
    /portlet-app_1_0.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:portlet="http://java.sun.com/xml/ns/portlet"
    xsi:schemaLocation="http://java.sun.com/xml/ns/portlet
    /portlet-app_1_0.xsd /opt/SUNWps/dtd/portlet.xsd" version="1.0">
        <portlet>
            <portlet-name>PrefPortlet</portlet-name>
            <portlet-class>examples.PrefPortlet</portlet-class>
            <expiration-cache>0</expiration-cache>
            <supports>
                <mime-type>text/html</mime-type>
                <portlet-mode>EDIT</portlet-mode>
                <portlet-mode>HELP</portlet-mode>
            </supports>
            <portlet-info>
                <title>PrefPortlet</title>
                <keywords>Hello, world, test</keywords>
            </portlet-info>
            <portlet-preferences>
                <preference>
                    <name>name</name>
                    <value>World</value>
                </preference>
            </portlet-preferences>
        </portlet>
    </portlet-app>
  2. Create the web.xml file. A web application also requires a web.xml file.

    If you have servlets for your portlet web application, then the servlet definition can be incorporated in the web.xml file.

    web.xml File for PrefPortlet


    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!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>
        <display-name>Portlet Examples</display-name>
    </web-app>
  3. Package everything into a WAR file.

    For the sample portlets, create an examples directory where all the files of the WAR will be placed. Then within the examples directory, create the WEB-INF directory. All the portlet files will be placed into the WEB-INF directory. For example, your directory hierarchy may look like this:


    examples/WEB-INF/
    		/web.xml
    		/portlet.xml
    		/classes/examples/PrefPortlet.class
  4. Create the WAR file. That is, change directories to examples and type the following command:


    jar -cvf examples.war *

Deploying the Application

The Portal Server software includes a deployment tool which will take your WAR file and deploy it into the portal server. Before deploying the WAR file, determine where to place the portlets inside the organization.

With the following command, the sample portlets can be deployed into the organization.

psadmin deploy-portlet -u uid -f passwordfile
 -g|-d distinguishedName -p portal1 examples.war

Note that the Portal Server deploys portlet applications as separate web applications within the web container. Portlet preferences are stored in the display profile with the portlet channel definition. The display profile is updated with a new provider for each portlet contained within the portlet web application. For more information on the psadmin deploy-portlet sub command, see Command Line Reference.

Creating Channels from the Deployed Portlets

Once the portlet is deployed, the portal server is aware of the portlet defined in the application. You can start to create channels based on the portlet. To create channels, see the Portal Server administration console online help for more information.

Debugging the Portlet

A logging mechanism is provided in the PortletContext, accessible from GenericPortlet.getPortletContext() method. The PortletContext.log() method will print a time-stamped message to the web container log and also to the portal log. There are two places to find the logs for the portlet:

WebServer-base/Instance/logs/errors

Includes PortletContext.log() messages

PortalServer-base/portals/Portal-ID/logs/Instance/portal.0.0.log

Includes PortletContext.log() messages. These messages are logged at the log level INFO.