Lyndsey has posted 139 posts at DZone. View Full User Profile

Hello World Portlet using Spring 3.0 Portlet MVC—Part I

02.23.2010
| 131170 views |
  • submit to reddit

This article is taken from the book Portlets in Action from Manning Publications. It’s part of a three-part series that creates a portlet example using the Spring 3.0 Portlet MVC. For the table of contents, the author forum, and other resources, go to http://manning.com/sarin/.

This is the first article in the three-part series, in which we look at developing portlets using the Spring 3.0 Portlet MVC framework. Part 1 of this series shows how you can create a simple Hello World portlet using the Spring 3.0 Portlet MVC framework and deploy it on a Liferay 5.2.3 portal server. This article assumes that you’re aware of the basics of the Spring framework.

This article uses the following software to develop the Hello World portlet:

Let’s begin with importing the accompanying HelloWorld Eclipse project, which contains all the necessary files for our Hello World portlet.

Project Structure
The project structure described in this section is generic in nature and can be used for developing portlets for any portal server. Once you import the HelloWorld project into your Eclipse IDE, you’ll find the following directories in it:

  • src—Contains the source code of the project, which includes portlet and utility classes.
  • build—Contains the WAR file that’s generated when the project is built using ANT.
  • css—Contains CSS files for the project, useful if you’re not using the look and feel provided by the portal server.
  • images—Contains the images used by the portlets in the project.
  • js—Contains the JavaScript files used by the portlet. Portlets may also make use of JavaScript libraries such as DWR, DOJO, and jQuery, which are normally packaged in a JAR file and accessed directly from the JAR file by portlets. In most cases, portlets consist of multiple pages of information, and the JavaScript may be required in some of these pages for such purposes as creating HTML widgets on the fly and using AJAX.
  • lib—Contains JAR files that are required during build time but don’t need to be packaged with the generated WAR file, for instance, JUnit and portlet JAR files. The JUnit JAR file is required to run unit tests at build time, and the portlet JAR file is required for compiling the portlet classes.
  • WEB-INF/jsp—Contains the JSP files used in the project. We’ll be using JSP as the view technology, but it’s possible to use other view technologies such as Velocity and Facelets to create portlet pages.
  • WEB-INF/lib—Contains JAR files that are required by the portlets at build time and at runtime.


Now that we know our project structure, let’s look at the JAR files that we need for developing/deploying the Hello World portlet.

Add necessary JAR files
To create Hello World portlet using Spring Portlet MVC, you can either download the latest release of Spring, which contains the JAR files you’ll need to build and deploy your portlet, or you can use the JAR files that come with the HelloWorld project.

The following JAR files must be present in the WEB-INF/lib directory of the project:

  • org.springframework.asm-3.0.0-RELEASE
  • org.springframework.beans-3.0.0-RELEASE (add this file to your project’s build path)
  • org.springframework.context-3.0.0-RELEASE (add this file to your project’s build path)
  • org.springframework.core-3.0.0-RELEASE
  • org.springframework.expression-3.0.0-RELEASE
  • org.springframework.web-3.0.0-RELEASE (add this file to your project’s build path)
  • org.springframework.web.portlet-3.0.0-RELEASE (add this file to your project’s build path)
  • org.springframework.web.servlet-3.0.0-RELEASE


Add portlet.jar from TOMCAT_HOME\common\lib\ext to the project’s lib directory (not WEB-INF/lib), where TOMCAT_HOME refers to the Tomcat directory inside your Liferay installation.

Let’s now look at the configuration files and classes that you’ll need to create the Hello World portlet using the Spring 3.0 Portlet MVC framework.

Controller/handler class
In Spring Portlet MVC, the controller/handler class (and not the portlet class) contains the actual request-handling logic for the portlet. Listing 1 shows the HelloWorldController class.

Listing 1 HelloWorldController class

public class HelloWorldController implements Controller{                 #1
public void handleActionRequest(ActionRequest request,
ActionResponse response)throws Exception {
}
public ModelAndView handleRenderRequest
(RenderRequest request, RenderResponse response)
throws Exception {
Map<String, Object> model =
new HashMap<String, Object>();
model.put("helloWorldMessage", "Hello World");
return new ModelAndView("helloWorld", model); #2
}
}

#1 Handler implements Controller interface
#2 handleRenderRequest returns ModelAndView

The HelloWorldController handler implements the org.springframework.web.portlet.mvc.Controller interface, which defines two methods:

  • handleActionRequest—Same as the portlet’s action method
  • handleRenderRequest—Same as the portlet’s render method


The handleRenderRequest method of HelloWorldController returns ModelAndView, which contains the model data and view information.

In portlets, a render method usually creates content by dispatching a render request to a JSP page (or any other view technology), and the data that needs to be rendered by the JSP page is passed as request attributes. The ModelAndView object holds the model data (the data to be rendered) and view information (the JSP page) that are used by the Spring Portlet MVC framework to dispatch the render request to the view and pass the model data. Because the Spring Portlet MVC framework takes care of dispatching the request and passing the data to the JSP page, we’re not using PortletRequestDispatcher in the handleRenderRequest method.

The ModelAndView object in the HelloWorldController class contains a model (the model variable in the handleRenderRequest method in listing 1) as a Map object and view name (the helloWorld string parameter of the ModelAndView constructor in listing 1) as a String object. The “Hello World” message that we want to show using the JSP page is passed as a model attribute with the name helloWorldMessage.

JSP page

The helloWorld.jsp page in our example portlet shows the “Hello World” message:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html" isELIgnored="false" %>
<c:out value="${helloWorldMessage}"/>

In listing 1 we put a helloWorldMessage model attribute with the value Hello World. The Spring Portlet MVC framework converts model attributes (such as the helloWorldMessage attribute) to request attributes so that the JSP page can easily access the model attributes.

In this JSP page, the <c:out value="${helloWorldMessage}"/> code writes the “Hello World” message to the response stream because the helloWorldMessage request attribute contains Hello World as its value.

Portlet deployment descriptor
If you’re using the Spring Portlet MVC framework to create your portlet, then you usually won’t create a custom portlet class. Instead, you’ll reuse the DispatcherPortlet class of the Spring Portlet MVC. The DispatcherPortlet class extends the GenericPortlet class and is responsible for dispatching portlet requests to the appropriate handler/controller. Listing 2 shows the portlet.xml file for the Hello World portlet example.

Listing 2 portlet.xml

<portlet>
<portlet-name>helloWorld</portlet-name>
<portlet-class>
org.springframework.web.portlet.DispatcherPortlet #1
</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<resource-bundle>content.Language-ext</resource-bundle>
<portlet-info> #2
<title>Hello World</title>
</portlet-info>
</portlet>

#1 Spring Portlet MVC’s DispatcherPortlet class
#2 <portlet-info> element for portlet title

Cueballs in code and text

At #1, the DispatcherPortlet class of the Spring Portlet MVC framework is specified as the portlet class. At #2, we use the <portlet-info> element to specify the portlet title.

Web application context

In any Spring framework application, the core of the application is the application context, which defines objects (that form part of the application) and their interdependencies. An application context is represented as an XML file, which defines application objects as beans.

Listing 3 shows the beans defined in the application context XML file for the Hello World portlet. The name of the web application context file must be <portlet_name>-portlet.xml, where <portlet_name> is the name of the portlet, as defined by the <portlet-name> element in the portlet.xml file. This file must reside in the WEB-INF folder of your project.

Listing 3 helloWorld-portlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans … >
<bean id="helloWorldController" #1
class="code.listing.HelloWorldController"/>

<bean id="portletModeHandlerMapping" #2
class="org.springframework.web.portlet.handler.
[CA] PortletModeHandlerMapping">

<property name="portletModeMap">
<map>
<entry key="view"> #3
<ref bean="helloWorldController" /> #3
</entry> #3
</map>
</property>
</bean>

<bean id="viewResolver" #4
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

#1 Controller/handler definition
#2 Portlet mode to handler mapping
#3 VIEW mode mapped to HelloWorldController
#4 View resolver

At #1, we define the HelloWorldController handler. At #2, the PortletModeHandlerMapping bean maps the current portlet mode to the handler/controller responsible for handling requests in that mode. At #3, the VIEW portlet mode of the Hello World portlet is mapped to HelloWorldController, which means any request (render or action) sent by the portlet in the VIEW mode will be handled by HelloWorldController. At #4, the InternalResourceViewResolver special bean is used to map view names (used in your Java code) to the actual view (which could be a servlet or a JSP). It uses the viewClass property to define the class responsible for generating the view. If you’re using JSPs that contain JSTL, then you should specify the value of the viewClass property as JstlView. The prefix property value is prepended, and the suffix property value is appended to the view name to create a URL referring to the actual view. In the Hello World portlet example,the helloWorld view name is returned by the handleRenderRequest method of HelloWorldController (refer to listing 2), which is resolved to an actual view by InternalResourceViewResolver by prepending /WEB-INF/jsp/ and appending .jsp to the helloWorld view name. This makes the URL to the actual view /WEB-INF/jsp/helloWorld.jsp.

Root web application context XML
Root web application context XML refers to the web application context XML associated with the portlet application. A web application context XML file for a portlet contains portlet-specific beans, whereas the root web application context XML file contains beans that are common to the portlets in the portlet application. A bean defined in the root web application context XML can be overridden by the portlet-specific application context XML by defining a bean with the same bean ID.

The name of the root web application context XML file must be applicationContext.xml. Because we aren’t creating any beans at the portlet application level, we’ll create an empty root web application context XML file, as shown in listing 5.

Listing 5 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans ....>
</beans>

Now we’ll look at the web application deployment descriptor for our portlet application.

Web application deployment descriptor
In the web application deployment descriptor we define the ViewRendererServlet of Spring, which is responsible for rendering our JSP pages. The InternalResourceViewResolver bean (refer to listing 3) resolves a view name to an actual view, and the rendering of view is done by the ViewRendererServlet servlet. ViewRendererServlet acts as a bridge between the portlet and the view. Listing 6 shows the ViewRendererServlet configuration in the web.xml file.

Listing 6 web.xml

<web-app ....>
<servlet>
<servlet-name>ViewRendererServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.ViewRendererServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
</web-app>

Next, we’ll create the resource bundle for our portlet. 

Resource bundle
The Language-ext.properties file is the resource bundle used by the Hello World portlet. The properties defined in the Language-ext.properties file include the following:

category.helloWorld=Spring Portlet
javax.portlet.title=My Hello World portlet

The significance of properties defined in Language-ext.properties file is as follows:

  • category.helloWorld—Specifies the name of the category under which the portlet is displayed by Liferay.
  • javax.portlet.title—Specifies the title of the portlet. The property name must be javax.portlet.title for the portlet container to consider it as the portlet title.
Add a portlet to a Liferay category using liferay-display.xml
The liferay-display.xml file allows you to specify the category under which you want the portlet to be displayed. The contents of the liferay-display.xml file are shown here:
<display>
<category name="categoryhelloWorld">
<portlet id="helloWorld" />
</category>
</display>
The important elements of liferay-display.xml file are these:
  • <category>—The name attribute refers to a key in the Liferay-ext.properties file that identifies the category under which the portlet needs to be displayed.
  • <portlet>—The id attribute must be the name of a portlet, defined by the <portlet-name> element in the portlet.xml file.
Configure Liferay-specific features using liferay-portlet.xml
The liferay-portlet.xml file allows configuring Liferay-specific features for the portlet. The liferay-portlet.xml file in our case contains a liferay-portlet-app element as follows:
<liferay-portlet-app>
<portlet>
<portlet-name>helloWorld</portlet-name>
<instanceable>true</instanceable>
</portlet>
</liferay-portlet-app>
The important elements of liferay-portlet.xml file are as follows:
  • <portlet-name>—The name of the portlet as defined by <portlet-name> element in the portlet.xml file.
  • <instanceable>—If true, you can have the same portlet appearing on a portal page more than once. The default value is false.
This completes the creation of the necessary files for the HelloWorld project. We’re now ready to build the HelloWorld project using Ant.

Building and deploying your portlet on Liferay
The first thing you need to do before building the HelloWorld project is to change the liferay.portal.home property of the build.properties file to point to the Liferay 5.2.3 installation directory.

To build the project in Eclipse IDE, right-click the build.xml file, choose Run As > Ant Build, and select the build target from the list of available targets, as shown in figure 1.


Figure 1 Ant targets defined in build.xml. The build target is selected by default. The compile and clean targets can also be executed separately, if the purpose is only to compile or clean the project.

The Ant build tool takes the following actions when the build target is executed:

  • Removes the generated WAR file from the build directory. This is achieved by executing the clean target.
  • Compiles the Java source to the WEB-INF/classes directory, creates a content directory, and copies the Language-ext.properties file to it. This is achieved by executing the compile target.
  • Creates the WAR file in the build directory and copies the generated WAR file to LIFERAY_HOME/deploy (which is Liferay’s hot deploy directory). This is achieved by executing the build target. LIFERAY_HOME refers to the Liferay installation directory.
  • If your Liferay portal server is already running, then running the build target will result in hot deployment of Hello World portlet. If the server isn’t running, then the portlet is deployed when the server is started. At deployment time, the information from liferay-display.xml is used to register the portlet with the Liferay portal server. 
Add the Hellow World portlet
When a portlet is deployed on Liferay, it’s available to the user when the user selects the Add Application option from the dock. To add the Hello World portlet, take the following steps:
  • Log in to the Liferay portal server. 
  • Select the Add Application option from the dock (refer to figure 2).  



Figure 2 The Add Application option allows authenticated users to add portlets to a portal page. A user can add portlets to a portal page only if the user has permission to do so. By default, a user can add or remove portlets from the portal page created by the user.

Add the Hello World portlet to your home page, as shown in figure 3.





Figure 3 My Hello World portlet under the category Spring Portlet; My Hello World portlet on the portal page

In figure 3, you see that the new category Spring Portlet was added to the list of available categories. The title, which was assigned to the Hello World portlet, is shown under the category. The Hello World portlet when added to the portal page shows the message “Hello World.”

How it works
Figure 4 summarizes what’s happening in the Hello World example portlet that we created in this article. We know that DispatcherPortlet is the most important class of the Spring Portlet MVC because it extends the GenericPortlet class and acts as the portlet class for our Spring Portlet MVC–based portlets. So what does DispatcherPortlet does? If you have prior experience working with the Struts framework, then you can closely relate the DispatcherPortlet to the RequestProcessor class in the Struts framework. The DispatcherPortlet is at the heart of the Spring Portlet MVC framework, and like RequestProcessor of the Struts framework, it’s responsible for coordinating all the request-handling activities on receipt of a portlet request.

 

 

 

Figure 4 Request processing in the Spring Portlet MVC. DispatcherPortlet acts as the front controller of the application. DispatcherPortlet finds the handler mapped to the request using HandlerMapping. The result of execution of a handler, ModelAndView, is used to resolve the actual view to be rendered and dispatch the request to ViewRendererServlet for rendering.

Cueballs in figure

When a portlet request is received by the DispatcherPortlet class (which is our portlet class) at #1, it first attempts to find an appropriate handler for the request. The HandlerMapping type bean of the Spring Portlet MVC helps find an appropriate handler. Depending on how you want to select a handler/controller based on the portlet request, you’ll select an appropriate HandlerMapping bean. The Hello World portlet example used the PortletModeHandlerMapping bean (which implements the HandlerMapping interface), which selects an appropriate handler/controller based on the current portlet mode at #2. In the Hello World portlet, PortletModeHandlerMapping maps the VIEW portlet mode to HelloWorldController (refer to listing 3); therefore HelloWorldController is the handler for our render request received at #1 by DispatcherPortlet.

Once the handler is selected for request processing, the next step is to invoke the appropriate method of the handler to do the request processing. In listing 1, the handleRenderRequest method of the handler is responsible for handling render requests, and the handleActionRequest method handles action requests. The request received at #1 is a render request; therefore the request is handled by the handleRenderRequest method of HelloWorldController at #3. The handleRenderRequest method of HelloWorldController returns a ModelAndView object.

The next step is to use the view information in the ModelAndView object to obtain a reference to the actual view, which is a JSP page in the case of the Hello World portlet. The ViewResolver type bean of the Spring Portlet MVC helps with view resolution, that is, finding the actual view corresponding to a logical view name. The Hello World portlet uses the InternalResourceViewResolver bean (which implements the ViewResolver interface) to resolve the view name to the actual JSP page, at #4. Once the actual view is resolved by a ViewResolver, the Spring Portlet MVC framework sends the reference to the view and the model data to the ViewRenderServlet servlet (refer to listing 6) for rendering the view at #5.

Conclusion
In this article we created a simple Hello World portlet using the Spring 3.0 Portlet MVC framework. In Part 2, “Spring 3.0 Portlet MVC annotations,” we’ll look at how we can create a multipage portlet using Spring Portlet MVC annotations.

Click here for the source code for this article.

 

 

 

 

 

 

AttachmentSize
Portlet1.png32.73 KB
Portlet2.png8.01 KB
Portlet3.png19.62 KB
Portlet4.png4.98 KB
Portlet5.png68.27 KB
Published at DZone with permission of its author, Lyndsey Clevesy.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ashish Sarin replied on Fri, 2010/03/05 - 12:38pm

You can download additional source code from Google Code project for Portlets in Action book from http://code.google.com/p/portletsinaction/downloads/list
It contains Spring Portlet MVC examples in ch7_Controllers, ch7_HandlerMappings and ch7_BookCatalog eclipse projects.
regards
Ashish Sarin
Author: Portlets in Action

Aamir Iqbal replied on Mon, 2010/03/08 - 9:10am

A very helpful Article / Tutorial. I apprecite this effort. Please keep it up to share such kinds of articles.

 

regards,

Amir Iqbal

Puneet Monga replied on Tue, 2010/04/13 - 9:31am

Any instructions on installation of liferay portal and reach to "Add application" option would have definitely helped.

Ashish Sarin replied on Sun, 2010/04/18 - 1:32am in response to: Puneet Monga

You can get detailed information on installing and using Liferay portal from the FREE chapter 1 of the book, here: http://www.manning.com/sarin/

regards
ashish

Srinivas Rao replied on Tue, 2010/06/22 - 11:01am

Hi Asish, when it is your book "Portlet in Action " available in the indian market. -Regards, Srinivas

Sunil Chandrashekar replied on Tue, 2010/10/26 - 2:00pm

I am new to the portal development field. This is a very helpful tutorial. I apprecite this effort. However, I wanted to know what type of project do I to choose in eclipse IDE when I create a brand new portlet?

Gundu Kuchee replied on Thu, 2010/12/23 - 5:07pm

i am new to portal development and this article is very helpful . i have a spring application already working in weblogic server version 10gR3 , I know spring3 has portlet support , but i wanted to know if i can deploy the spring mvc portlet application in weblogic server version 10gR3 ? is it a mandate i need a portal server or can it be done in weblogic server version 10gR3 ?

Hamid Khanjani replied on Wed, 2011/05/11 - 12:38am

thank you it is helpful

Sudeep Kumar replied on Tue, 2011/10/04 - 12:57am

Hi,

Thanks for this example.

But I'm having a quick question. In web.xml (pls refer listing 6) there is an entry:

    <servlet-mapping>
        <servlet-name>ViewRendererServlet</servlet-name>
        <url-pattern>/WEB-INF/servlet/view</url-pattern>
    </servlet-mapping>

 

where does the url-pattern "WEB-INF/servlet/view"  points to? I don't have any servlet at specified path.

If any kind of servlet needs to be created the please provide code as well. Thanks in advance!!!

Cary Li replied on Thu, 2011/10/20 - 10:31pm

that's so great, very helpful, thanks!

Avax Nguyen replied on Thu, 2012/02/02 - 5:57am

So helpful, thanks for your great effort.

Carla Brian replied on Sun, 2012/07/01 - 6:00pm

These tips are really helpful. Thanks for this. This is my first time knowing this application. - Joe Aldeguer

Surender Biyyala replied on Mon, 2012/09/03 - 8:57am

Hi 

I gone through some of the blogs which specify that a portlet needs to be configured as a servlet .

but in this example bookcatalog is not configured as servlet in web.xml.

even spring specification says that. please refer to

http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch13s02.html

 

please provide the clarification .

 

Thanks

Surender 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.