Java Portlet Example Tutorial

Filed Under: Portal and Portlets

In the presented introduction about Apache Pluto, we’ve mainly discussed the most simple Portlet application that you may have. The business scenarios are more complicated then normal and they require a full knowledge about the Portlet, Portlet Life cycle and how could provide a compliant enhanced Portlet that complying with the latest standards presented at the Portlet field.

Portlet Tutorial

This tutorial will help you getting this practice applied, while it should take you through the following subjects:

Little Bit More About GenericPortlet

As we’ve stated in the proposed introduction, our developed Portlet was extended a GenericPortlet class as it’s abstract class. According to Portlet Javadoc, GenericPortlet class provides the default implementation for the Portlet interface (Which will be discussed later on here). It provides an abstract class to be sub-classed to create Portlets.

A subclass of GenericPortlet should either use one of the following annotations: @ProcessAction, @ProcessEvent and @RenderMode or override at least one method of the following:

  • processAction: to handle action requests (will be discussed later on in this tutorial).
  • doView: to handle render requests when the Portlet is in the View mode.
  • doEdit: to handle render requests when the Portlet is in the Edit mode.
  • doHelp: to handle render requests when the Portlet is in the Help mode.
  • init and destroy: to manage resources that are held for the life of the Servlet.

Normally, no need to override the render or the doDispatch methods, as the render method handles render requests, setting the title of the Portlet in the response and invoking the doDispatch.

In turn of the doDispatch method, the request is dispatched to one of the doView, doEdit or doHelp method depending on the Portlet mode indicated in the request. The major issue that you might find it so important, is that the Portlet is running in a multi threaded manner, so be careful when it comes to handle shared resources. Shared resources may take different forms; it’s include in-memory data such as instance or class variables, external resources like a files, database connections and network connections.

In the proposed sample that you’ve looked for at the introduction, we’ve overridden the doView method for getting message displayed. We do, some modifications against the sample itself, so you should notice the following:

  • We’ve eliminated the overriding of doView method, as we used @RenderMode annotation to annotate a new method called inspectRenderMode.
  • We’ve updated the pom.xml file, so no need to get your generated WAR every time and copy it into your Tomcat’s webapp deployment folder. That’s done by using an integration-test phase that asks Ant to make that in behind of you.

package com.journaldev.portlet;

import java.io.IOException;

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

public class HelloWorldPortlet extends GenericPortlet {
	@RenderMode(name="View")
	public void inspectRenderMode(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {
		response.getWriter().print(
				"Jounral Dev Provides you Hello World Portlet Using Annotations !");
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>HelloWorldPortlet</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>HelloWorldPortlet Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<properties>
		<deployFolder>D:/Apache Pluto/pluto-2.0.3/webapps</deployFolder>
	</properties>
	<dependencies>
		<!-- Java Portlet Specification V2.0 -->
		<dependency>
			<groupId>org.apache.portals</groupId>
			<artifactId>portlet-api_2.0_spec</artifactId>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<!-- bind 'pluto2:assemble' goal to 'process-resources' lifecycle -->
			<!-- This plugin will read your portlet.xml and web.xml and injects required
				lines -->
			<plugin>
				<groupId>org.apache.portals.pluto</groupId>
				<artifactId>maven-pluto-plugin</artifactId>
				<version>2.1.0-M3</version>
				<executions>
					<execution>
						<phase>generate-resources</phase>
						<goals>
							<goal>assemble</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<!-- configure maven-war-plugin to use updated web.xml -->
			<!-- This plugin will make sure your WAR will contain the updated web.xml -->
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.1.1</version>
				<configuration>
					<webXml>${project.build.directory}/pluto-resources/web.xml</webXml>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-antrun-plugin</artifactId>
				<executions>
					<execution>
						<phase>integration-test</phase>
						<configuration>
							<tasks>
								<!-- Use this to build and deploy the testsuite war. PORTLET_DEPLOY_DIR
									is an environmental variable pointing to the hot-deploy directory of your
									portal. You can also use -Ddeploy.dir=<path to deployment dir> on the command
									line when invoking maven: mvn -Ddeploy.dir=/pluto-1.1.4/webapps integration-test -->
								<property environment="env" />
								<property name="deploy.dir" value="${env.PORTLET_DEPLOY_DIR}" />
								<copy file="target/${pom.build.finalName}.war" tofile="${deployFolder}/${pom.build.finalName}.war" />
							</tasks>
						</configuration>
						<goals>
							<goal>run</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Here’s detailed explanation for the code listed above:

  • JSR-286 has introduced the using of annotations for controlling things were controlled normally through overriding GenericPortlet methods. We’ve used @renderMode instead of overriding doView method done like before.
  • We’ve added antrun plugin to replace the old way of deploying that we were used. Now, what’s really you want to do is to execute mvn clean integration-test package to get your WAR copied and deployed directly underneath of your Tomcat’s webapp folder. This procedure will be used henceforward.

Defining View Mode Using Portlet Specification

Finally, if you have a special kind of business that you would like to provide such a type of integration, you may make a subclass of GenericPortlet and let your developers extend it.

Little Bit More About PortletRequest & PortletResponse

The PortletRequest interface in the Portlet API represents the common functionality in an ActionRequest and RenderRequest, where both of them are actually subclass of PortletRequest.

The PortletRequest provides all needed information about the user’s request (e.g request’s parameters), user’s session, Portal, Portlet application and different information about the Portlet itself.

The Portlet container passes all Portlet request and response objects to the Portlet whenever the Portlet get requested.

In the other side, the Portlet sends a response object back to the Portal after every request. Usually, the response object contains the content fragment of the Portlet, any requested Portlet modes or window states and several other pieces of information that get discussed later.

Actually, the Portlet developers haven’t worked with actual instances of PortletRequest and PortletResponse. However, the developers will work with RenderRequest, ActionRequest, RenderResponse and ActionResponse.

You may be asking about the difference between RenderRequest, RenderResponse and ActionRequest, ActionResponse and why they are categorized like that. Following figure shows you the main differences shortly before getting all detailed clarifications in the next coming sections.

Type Description Who’s Created It
RenderRequest The RenderRequest represents the request sent to the Portlet to handle a render. The Portlet container creates a RenderRequest object and passes it as argument to the Portlet’s render() method.
RenderResponse The RenderResponse defines an object to assist a Portlet in sending a response to the Portal. The Portlet container creates a RenderResponse object and passes it as argument to the Portlet’s render() method.
ActionRequest The ActionRequest represents the request sent to the Portlet to handle an action. The Portlet container creates an ActionRequest object and passes it as argument to the Portlet’s processAction() method.
ActionResponse The ActionResponse represents the response for the response to an action request. The Portlet container creates an ActionResponse object and passes it as argument to the Portlet’s processAction() method.

As you’ve noticed in the figure shown, Portlet specification defines two different types of request/response, render’s request/response and action’s request/response are mainly the only objects you may revolve around at each time you got into a Portlet development mission.

Such that distinction is very helpful when it comes to deal with the Portlet business, as a Portlet may be rendered at every time the contained Portal page is refreshed, while the action is getting executed at a certain specific time the user has asked for.  To make clear, following sample shows you the difference in between calling render() and processAction().


package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloWorldPortlet extends GenericPortlet {
	private static int renderCount = 0;
	private static int actionCount = 0;

	public void doView(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {

		synchronized(this){
			renderCount++;
		}

		response.getWriter().print("<form action="+response.createActionURL()+">"
				+ "<p>Render has executed "+renderCount+"</p>"
				+ "<p>Render has executed "+actionCount+"</p>"
				+ "<input type='submit'/>"
				+ "</form>");
	}

	public void processAction(ActionRequest actionRequest, ActionResponse actionResponse){
		synchronized(this){
			actionCount++;
		}
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}

Java Portlet Example - Render And Action Counting

Here’s detailed clarifications for code listed above:

  • You may notice that the render counter will be incremented by one at every time you’ve got the Portal page rendered. GenericPortlet render method has delegated the control into doView that’s overrode at the HelloWorldPortlet.
  • Action counter won’t be incremented until you’ve clicked on the submit action. GenericPortlet processAction method has delegated the control into processAction method that’s overrode at the HelloWorldPortlet.
  • We’ve implemented both of render and action using the Portlet specification 1.0 as no annotation has been used.
  • As being render method had called at every time you’ve got your Portal page refreshed, it’s very clear that’s why render isn’t the proper location to put any business logic you may require. If we’ve assumed that we have a business logic like mail sending putting there, so the mail would be sending at every time the Portal page getting refreshed.

Enhancing Portlet

Portlet capabilities aren’t stopped here as we’re going to make some improvements to demonstrate other sides of these capabilities. Usually, the Portlet doesn’t render a plain HTML, it’s contained other resources like JavaScript, images and StyleSheets.

Also, the view mode isn’t the only mode that you lets the end user contact with, EDIT and HELP modes are also supported by the Portlets. Mainly, you may provide an EDIT mode for a kind of configuration, meanwhile, the HELP mode is a good place to provide a helpful information about the Portlet itself.

Beside that, providing Portlet Title isn’t so complex mission, as you can provide the default value using the portlet-info XML tag, you can also change the Title programmatically.

Change The Portlet Title

Generally, Portlet specification has introduced the portlet-info XML tag to allow developers specifying these information related to the Portlet’s title, short-title and keywords that may be used for categorization purpose.

You have three different scenarios that can you have to let the Portlet get its title, you may be using the most simplest way; define the title at the portlet.xml file within portlet-info or using a resource bundle for getting internationalization descriptive title or providing the title programmatically. Following example shows you how can you leverage two additional scenarios to make sure the desired title is set as we’ve had the first scenario previously.


package com.journaldev.portlet;

import java.util.Locale;
import java.util.ResourceBundle;

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

public class TitleChangedPortlet extends GenericPortlet{
	public void doView(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("My Name Is:"+this.getPortletName());
	}

	public java.lang.String getTitle(RenderRequest request) {
		// Check whether the name of the portlet is programmaticTitleChangePortlet
		if(this.getPortletName().equals("ProgrammaticTitleChangePortlet")){
			// If it's like that, just get the defined bundle
			ResourceBundle bundle = this.getPortletConfig().getResourceBundle(new Locale("en"));
			// Retrun the string that's corresponded for anyTitle property
			return (String)bundle.getObject("anyTitle");
		}
		// else return the default, either that's defined in the portlet.xml or that's defined in the bundle
		return super.getTitle(request);
	}
}

package com.journaldev.portlet;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class HelloWorldPortlet extends GenericPortlet {
	private static int renderCount = 0;
	private static int actionCount = 0;

	public void doView(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {

		synchronized(this){
			renderCount++;
		}

		response.getWriter().print("<form action="+response.createActionURL()+">"
				+ "<p>Render has executed "+renderCount+"</p>"
				+ "<p>Action has executed "+actionCount+"</p>"
				+ "<input type='submit'/>"
				+ "</form>");
	}

	public void processAction(ActionRequest actionRequest, ActionResponse actionResponse){
		synchronized(this){
			actionCount++;
		}
	}

    public void init( PortletConfig config ) throws PortletException {
        super.init( config );
    }
}

portlet.xml


<?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>Write here a short description about your portlet.</description>
		<portlet-name>HelloWorldPortlet</portlet-name>
		<display-name>HelloWorldPortlet Portlet</display-name>

		<portlet-class>com.journaldev.portlet.HelloWorldPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<portlet-info>
			<title>Title Is Set Using Simplest Way Portlet-Info XML Tag</title>
			<short-title>Hello World</short-title>
			<keywords>Hello,pluto</keywords>
		</portlet-info>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title using Resource Bundle</description>
		<portlet-name>ResourceBundleTitleChangePortlet</portlet-name>
		<display-name>ResourceBundleTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title programmatically</description>
		<portlet-name>ProgrammaticTitleChangePortlet</portlet-name>
		<display-name>ProgrammaticTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>		

	</portlet>	

</portlet-app>

message.properties


javax.portlet.title=Title Is Set By Resource Bundle
anyTitle=Title Is Set Programmatically

Portlet Example Tutorial - Different Way To Set The Titles

Here’s detailed explanation for code shown above:

  • It’s possible to use the same Portlet with different names. We’ve used TitleChangedPortlet twice; once under ResourceBundleTitleChangePortlet name and second with ProgrammaticTitleChangePortlet.
  • HelloWorldPortlet uses the title that’s defined within the portlet.xml file.
  • ResourceBundleTitleChangePortlet uses the title that’s defined inside resource bundle. As you’ve noticed you must use the well-known constants as they must be compliant with Portlet specification to be considered. Following below the constants for the Portlet level resource bundle:
Constant Description
javax.portlet.title The,title that should be displayed in the titlebar of,this portlet. Only one title per locale is allowed. Note,that this title may be overrided by the portal or,programmatically by the portlet.
javax.portlet.short-title A short,version of the title that may be used for,devices with limited display,capabilities. Only one,short title per locale is allowed.
javax.portlet.keywords Keywords,describing the functionality of the portlet.,Portals that allow users to search for portlets based,on keywords may use these keywords. Multiple,keywords per locale are allowed, but must be,separated by commas ‘,’.
javax.portlet.description Description,of the portlet.
javax.portlet.display-name Name,under which this portlet is displayed at,deployment time or to tools. The display name need,not be unique.
javax.portlet.app.custom-portletmode.<,name>.decoration-name Decoration,name for the portlet managed custom,portlet mode .
  • Typically, you should define your resources within the same package as your Portlet to make sure every Portlet has used its relevant messages.
  • ProgrammaticTitleChangePortlet uses the title that’s changed programmatically. Even that we can provide a static text, but we’ve provide another use of bundle messages.
  • In case you need to provide the title programmatically, you must do override for the getTitle() method that’s already inherited from the GenericPortlet.
  • If you’re used resource bundle for getting Portlet’s accompanies text defined, you must make sure that you have your resource files (e.g message.properties) located into your class path as you’ve defined it in the portlet.xml.
  • Another way to change the title programmatically, you can invoke setTitle() against renderResponse object inside any delegated method (i.e doView, doEdit and doHelp).

Portlet URLs

As we knew, the Portlet isn’t a standalone resource like Servlet that can be accessed through a well defined URL (i.e http://servername:port/web-context/servlet-mapping). The Portlet can be accessed only via using a Portal page, as it’s reside there.

However, a Portlet can create a URL that targets itself in the Portlet container (i.e by clicking a link or submitting a form) the result is a new client request to the Portal targeted to the Portlet as we already did when submitting HelloWorldPortlet above.

Anyway, these URL’s are called portlet URLs. In that, a Portlet URL will reference the instance of the portlet in the Portal page (In case you have two different Portlets referenced the same Portlet class, they will have different Portlet URLs).

Creation of these URLs is a Portlet container responsibility as it’s also parsed the Portlet URL into parameters for the Portlet request. The Portlet creates PortletURL objects that represent Portlet URLs. The Portlet itself can use one of two methods on the RenderResponse class to create these PortletURL objects:

  • createActionURL(): Is used to make action URLs for HTML forms or links. These actions URLs are useful for processing actions (i.e Portlet’s state modifications) on the Portlet (i.e calling of processAction() overrode method against your Portlet).
  • createRenderURL(): Is used to make render URLs for any tasks that doesn’t contain Portlet’s state modifications.

Even that you can add Portlet URLs into your content with no parameters, but you can also set your parameters on a Portlet URLs by invoking setParameter(name, value) against your PortletURL object that’s returned once you invoked createActionURL() or createRenderURL().

More clarifications and samples would be delivered in the next coming tutorial that’s aimed to cover all technical specifics for accompanies render’s request/response and action’s request/response and how’s the parameter can be set and consumed after then.

doEdit & doHelp Methods

Practically, we’ve not used doEdit method for any type of normal rendition, it’s mainly used for specifying the Portlet’s states for controlling Portlte’s behavior at normal rendition invocation that’s done using doView.

At the same time, some Portlets have provided so complicated business, the user may need some sort of help to get the Portlet working properly and for that purpose the doHelp is given.

Defining the Portlet’s modes isn’t so complex mission, all what you need for is to use portlet-mode within supports Tag for specifying which modes the Portlet has supported. Following example shows you the way that in which you are able of seeing Edit & Help modes.


package com.journaldev.portlet;

import java.util.Locale;
import java.util.ResourceBundle;

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

public class TitleChangedPortlet extends GenericPortlet{

	public void doView(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("My Name Is:"+this.getPortletName());
	}

	public void doEdit(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("Edit Mode On Portlet Name :"+this.getPortletName());
	}

	public void doHelp(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException {
		response.getWriter().println("Help Mode On Portlet Name :"+this.getPortletName());
	}

	public java.lang.String getTitle(RenderRequest request) {
		// Check whether the name of the portlet is programmaticTitleChangePortlet
		if(this.getPortletName().equals("ProgrammaticTitleChangePortlet")){
			// If it's like that, just get the defined bundle
			ResourceBundle bundle = this.getPortletConfig().getResourceBundle(new Locale("en"));
			// Retrun the string that's corresponded for anyTitle property
			return (String)bundle.getObject("anyTitle");
		}
		// else return the default, either that's defined in the portlet.xml or that's defined in the bundle
		return super.getTitle(request);
	}
}

portlet.xml


<?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>Write here a short description about your portlet.</description>
		<portlet-name>HelloWorldPortlet</portlet-name>
		<display-name>HelloWorldPortlet Portlet</display-name>

		<portlet-class>com.journaldev.portlet.HelloWorldPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>

		<portlet-info>
			<title>Title Is Set Using Simplest Way Portlet-Info XML Tag</title>
			<short-title>Hello World</short-title>
			<keywords>Hello,pluto</keywords>
		</portlet-info>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title using Resource Bundle</description>
		<portlet-name>ResourceBundleTitleChangePortlet</portlet-name>
		<display-name>ResourceBundleTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
			<portlet-mode>EDIT</portlet-mode>
			<portlet-mode>HELP</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>

	</portlet>

	<portlet>
		<description>It's a Portlet that's setting title programmatically</description>
		<portlet-name>ProgrammaticTitleChangePortlet</portlet-name>
		<display-name>ProgrammaticTitleChangePortlet</display-name>

		<portlet-class>com.journaldev.portlet.TitleChangedPortlet</portlet-class>

		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
			<portlet-mode>EDIT</portlet-mode>
			<portlet-mode>HELP</portlet-mode>
		</supports>

		<supported-locale>en</supported-locale>

		<resource-bundle>message</resource-bundle>		

	</portlet>	

</portlet-app>

Portlet example Modes

Here’s detailed explanation for code listed above:

  • You must define the modes that you want to make your Portlet support for.
  • HelloWorldPortlet does support View mode as it’s Portlet with no Edit or Help.
  • Other two Portlets have defined all of modes are available.
  • Portal provides you the mode user interface for toggling between modes that are supported by the Portlet.

Summary

Portlet specification provide vast amount of APIs that you have to learn to be Portlet developer. This tutorial aimed to provide you additional details about GenericPortlet, PortletRequest, PortletResponse and others. Contribute us by commenting below and find downloaded source code.

Comments

  1. Raju says:

    Really very useful information …Thanks a lot

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages