Introduction to Spring Portlets

Spring Portlet is a framework released from Spring community for easier development of Java Portlets. In this article, we will learn about programming Portlets using Spring Portlets framework which is a layer built on top of Java Portlet Specification (JSR 168). This article also covers some details about Java Portlet Specification. It provides in-depth details about the various components involved in Spring Portlet framework like Controllers, Handler Mappings, View Resolvers etc. Finally, it concludes with a sample which illustrates developing Portlet applications using Spring’s Portlet approach. Before delving into this article, the reader is expected to have a fair bit of knowledge on Core Spring framework and Spring MVC. For more information on this, please refer and read Introduction to Spring Web MVC.

also read:

Java Portlets

Portlets are web components similar to Servlets managed by Portlet Container (similar to Web Container which manages Servlets). Portlets are components used in the UI layer for displaying the content fetched from different data sources to the end user. Portlets can generate dynamic content or static content. Typically, a web portal (or a portal application) is one comprising of multiple Portlets that retrieves dynamic or static content from various data sources. It is the responsibility of the portal to aggregate the content retrieved from various Portlets to make a display suitable to the end user.

Portlet APIs

Similar to Servlet interface, there is Portlet interface which will be extended directly or indirectly by all the Java Portlets. The life-cycle of a Portlet (such as creation, request processing and destruction) is completely managed by Portlet Container. When the Portlet Container creates an instance of a Portlet, it will call the init() method defined in the Portlet interface. The client portal which initiates the request can fall under two flavors. They are

  • Action Request
  • View Request

When the request type is Action, then the Portlet Container will call the processAction() method. On the other hand, when the request is of type View, the Container will call render() method defined on the Portlet interface.

Portlet Modes

The specification supports three standard Portlet modes, although it is possible to define custom Portlet modes as well. The standard modes are

  • View Mode
  • Help Mode
  • Edit Mode

In the View Mode, the portal is expected to retrieve the contents from different Portlets without any user interaction and the specification mandates to support this mode. In Help mode, the Portlet is expected to provide context sensitive information about the Portlet. In Edit mode, the Portlets are expected to fetch the content based on user preferences. The help and the edit mode are optional according to the specification. Note that, there is a class GenericPortlet which already defines the template methods doView(), doHelp() and doEdit() for supporting view, help and edit modes.

Spring Portlets Architecture

The concepts and components of Spring Portlets resemble the very same as Spring Web MVC, the framework used for developing Web Applications using Spring. We will study and understand the following components before going into a sample application.

Dispatcher Portlet

Similar to DispatcherServlet in Spring Web MVC, we have DispatcherPortlet which acts as the front controller for receiving the client requests. This front controller plays a key role as it drives the entire Portlet framework by wiring the other components.

<portlet>
    <portlet-name>test</portlet-name>
    <display-name>Test Service</display-name>
    <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
    <portlet-info>
        <title>Test Service</title>
    </portlet-info>
</portlet>

Every instance of Dispatcher Portlet maintains its own application context. For example, in the above sample, the dispatcher Portlet will look for a file name by test-portlet.xml in the folder /WEB-INF directory and if it present, will try to load all the bean definitions from that file.

Handler Mappings

Handler Mapping are components which are used to map incoming Portlet requests from the client to appropriate handlers. Spring provides a number of built-in handler mapping components with the most familiar being the PortletModeHandlerMapping which maps the Portlet modes (like view, edit, help etc) directly to handlers. For example, consider the following code snippet,

<bean>
    <property name="portletModeMap">
            <map>
                 <entry key="view" value-ref="anyViewHandler"/>
                 <entry key="edit" value-ref="anyEditHandler"/>
                 <entry key="help" value-ref="anyHelpHandler"/>
            </map>
    </property>
</bean><map> </map> 
 

Controllers

Controllers are components which are called for performing any operation, they will be called from the Dispatcher Portlet after it does mapping for the Portlet requests. There are many built-in controllers like AbstractCommandController, SimpleFormController, AbstractWizardFormController and they all implement the Controller interface that defines the following methods

  • handleRenderRequest(RenderRequest, RenderResponse)
  • handleActionRequest(ActionRequest, ActionResponse)

Remember that a Portlet can act in two modes, one is the view mode in which case the method handleRenderRequest() where the response content will be rendered to the client and the other is the action mode where the method handleActionRequest() will be invoked.

View Resolvers

Controllers are never coupled with the views and one can note that in the implementation of a controller, the controller will specify only the name of the view. The name of the view is so abstract, hence View Resolver components come into place for resolving the actual view based on the view name. For example, the following bean definition will try to resolve the view names mentioned in controllers are JSP views.

<bean id="jspViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

Design

In this sample application, we will design Portlets for displaying the list of the movies running this week and also for displaying the live cricket score-cards. Note that the implementation will never hit an external service for getting the information instead it will hard-code the necessary details within the java code itself.

Interface Design

We will start with the interface design for retrieving the list of the movies and the list of the score-cards.
MovieService.java

package net.javabeat.articles.spring.portlets.sample.movie;

import java.util.Set;

public interface MovieService {

    Set getAllMoviesForThisWeek();

}

The above movie service defines a method for getting the list of movies running that are running for the current week. Similarly,
the following score-card service provides the live score cards.

ScoreCardService.java

package net.javabeat.articles.spring.portlets.sample.scorecard;

import java.util.Set;

public interface ScoreCardService {

    Set getLiveScoreCards();

}

Note that the service interfaces are dependant on the model objects Movie and ScoreCard. We will see the declaration of these model objects in the next section

Model objects

Given below is the declaration of the model objects Movie and ScoreCard. The Movie objects contains the properties like the movie id and the name of the movie along with appropriate getters and setters.
Movie.java

package net.javabeat.articles.spring.portlets.sample.movie;

public class Movie {

    private String id;
    private String name;

    public Movie(String id, String name){
        this.id = id;
        this.name = name;
    }

    public String getId(){
        return id;
    }

    public void setId(String id){
        this.id = id;
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

Similarly, the score-card model objects contains the name of the two teams along with the scores at the current moment.
ScoreCard.java

package net.javabeat.articles.spring.portlets.sample.scorecard;

public class ScoreCard {

    private String teamOneName;
    private String teamOneScore;
    private String teamTwoName;
    private String teamTwoScore;

    public ScoreCard(String teamOneName, String teamOneScore, String teamTwoName, String teamTwoScore){
        this.teamOneName = teamOneName;
        this.teamOneScore = teamOneScore;
        this.teamTwoName = teamTwoName;
        this.teamTwoScore = teamTwoScore;
    }

    public String getTeamOneName() {
        return teamOneName;
    }

    public void setTeamOneName(String teamOneName) {
        this.teamOneName = teamOneName;
    }

    public String getTeamOneScore() {
        return teamOneScore;
    }

    public void setTeamOneScore(String teamOneScore) {
        this.teamOneScore = teamOneScore;
    }

    public String getTeamTwoName() {
        return teamTwoName;
    }

    public void setTeamTwoName(String teamTwoName) {
        this.teamTwoName = teamTwoName;
    }

    public String getTeamTwoScore() {
        return teamTwoScore;
    }

    public void setTeamTwoScore(String teamTwoScore) {
        this.teamTwoScore = teamTwoScore;
    }
}

Service implementations

For the implementations of the MovieService and the ScoreCardService, we are not going to hit the some external API or web-service for getting the details. Instead we are going to maintain some kind of hard-coded data within the implementation code to achieve this.
MovieServiceImpl.java

package net.javabeat.articles.spring.portlets.sample.movie;

import java.util.LinkedHashSet;
import java.util.Set;

public class MovieServiceImpl implements MovieService{

    private static Set allMovies = new LinkedHashSet();

    public Set getAllMoviesForThisWeek() {

        if (allMovies.size() == 0){
            initMovies();
        }
        return allMovies;
    }

    private static void initMovies(){
        allMovies.add(new Movie("TKK", "The Karate Kid"));
        allMovies.add(new Movie("SFA", "Shrek Forever After"));
        allMovies.add(new Movie("TS3", "Toy Story 3"));
    }
}

Similarly, have a look at the implementation of the ScoreCard service implementation.
ScoreCardServiceImpl.java

package net.javabeat.articles.spring.portlets.sample.scorecard;

import java.util.LinkedHashSet;
import java.util.Set;

public class ScoreCardServiceImpl implements ScoreCardService {

    private static Set liveScoreCards = new LinkedHashSet();

    public Set getLiveScoreCards() {
        if (liveScoreCards.size() == 0){
            initScoreCards();
        }
        return liveScoreCards;
    }

    private static void initScoreCards(){
        liveScoreCards.add(new ScoreCard("India", "320/5", "Pakistan", "210/8"));
        liveScoreCards.add(new ScoreCard("SouthAfrica", "296/3", "West Indies", "246/6"));
        liveScoreCards.add(new ScoreCard("Bangladesh", "196/9", "Srilanka", "199/4"));
    }
}

Controller Components

Till now, the components that we have written doesn’t have any dependency with the Spring APIs or with any of the J2EE components. Now we are going to write the Controller components which will depend on the Spring Portlet APIs. Have a look at the following MovieController component.
MovieController.java

package net.javabeat.articles.spring.portlets.sample.movie;

import java.util.Set;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.mvc.AbstractController;

public class MovieController extends AbstractController{

    private MovieService movieService;

    public void setMovieService(MovieService movieService) {
        this.movieService = movieService;
    }

    @Override
    public ModelAndView handleRenderRequestInternal(RenderRequest request, RenderResponse response){

        Set movies = movieService.getAllMoviesForThisWeek();
        ModelAndView mv = new ModelAndView("moviesView", "movies", movies);
        return mv;
    }
}

Note the declaration of the MovieController class, it extends from Spring Portlet’s AbstractController component. The MovieController component is dependant on MovieService component. Later on, we will walk through on establishing dependency between MovieController and MovieService components. Have a note of the signature of the template method handleRenderRequestInternal(). This method will be called by the framework for rendering the response to the client. For rendering the response to the client, we need the view and the model that will be displayed on the view. Spring encapsulates this behaviour with the help of ModelAndView objects. Note that we fetch the model through the method getAllMoviesForThisWeek() defined on MovieService object. Finally we construct and return a ModelAndView object with the name of the view, the name of the model and the model object itself. Note that at this point, we have only defined the name of the view. Later on in this article, we will see how this view is getting resolved to a real view object.
Similarly, have a look at the declaration on the ScoreCardController component. Note that this controller is dependant on ScoreCardService component that does the job of fetching the model from the method getLiveScoreCards() defined on ScoreCardService.
ScoreCardController.java

package net.javabeat.articles.spring.portlets.sample.scorecard;

import java.util.Set;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.mvc.AbstractController;

public class ScoreCardController extends AbstractController {

    private ScoreCardService scoreCardService;

    public void setScoreCardService(ScoreCardService scoreCardService) {
        this.scoreCardService = scoreCardService;
    }

    @Override
    public ModelAndView handleRenderRequestInternal(RenderRequest request, RenderResponse response){

        Set liveScoreCards = scoreCardService.getLiveScoreCards();
        ModelAndView mv = new ModelAndView("liveScoreCardsView", "liveScoreCards", liveScoreCards);
        return mv;
    }
}

Web Application Deployment Descriptor

For making use of Spring’s Portlet framework, we have to provide a hook in web.xml mentioning the web server (or the web container) to go through a different flow. Given below is the complete listing for the file web.xml.
web.xml

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

    <display-name>Demo Portal</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <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>

We have added a context listener for loading the spring application context. The name of the listener is ContextLoaderListener and it will try to load the application context with the file name taken from the parameter contextConfigLocation. Note that we have provided the application context’s file name as applicationContext.xml. In the later section, we will see the content and the description of the file. For the time-being, assume that the bean definitions defined in the application context will be loaded.
Spring Web MVC uses HttpServletRequest for handling the request and HttpServletResponse for rendering the response and also for supporting multiple view technologies. However, Spring Portlet framework deals with RenderRequest and RenderResponse for handling request and response. In order to support the existing view technologies supported by Spring’s Web MVC we have to declare the ViewRendererServlet in which case the DispatcherServlet will map the RenderRequest/RenderResponse APIs to HttpServletRequest/HttpServletResponse APIs with the help of ViewRendererServlet.

Application Deployment Descriptor

Note that the context loader listener defined in web.xml will try to load the bean definitions from the context file applicationContext.xml. Given below is the listing for the file applicationContext.xml
applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <bean id = "movieService" class = "net.javabeat.articles.spring.portlets.sample.movie.MovieServiceImpl">
    </bean>

    <bean id = "scoreCardService" class = "net.javabeat.articles.spring.portlets.sample.scorecard.ScoreCardServiceImpl">
    </bean>

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

In the above file, we have the declaration for movie service and score-card service. Remember that in the beginning of the sample, we have designed the movie and the score-card services. The configuration file also contains the definition for the view resolver class for resolving the view names to a particular view technology like JSP, JSTL, Velocity etc.

Views

In the above section, we have seen that the view names moviesView and liveScoreCardsView will be mapped to moviesView.jsp and liveScoreCardsView.jsp present in /WEB-INF/jsp folder. Here is the listing of both the files.
moviesView.jsp

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<table border ="2">
    <tr>
        <th>Id</th>
        <th>Name</th>
    </tr>
    <c:forEach items = "${movies}" var = "movie">
        <tr>
            <td>${movie.id}</td>
            <td>${movie.name}</td>
        </tr>
    </c:forEach>
</table>

Note that the above JSP with the help of JSTL iterates over the model object by the name movies (this name we set in the MovieController while creating the ModelAndView object) to create the HTML fragment. Have the look at the following listing for liveScoreCardsView.jsp that does the job of iterating over the model object liveScoreCards for generating the HTML fragment.
liveScoreCardsView.jsp

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

<table border ="2">

    <tr>
        <th>Scores</th>
    </tr>

    <c:forEach items = "${liveScoreCards}" var = "liveScoreCard">
        <tr>
           <td>${liveScoreCard.teamOneName} (${liveScoreCard.teamOneScore}) Vs ${liveScoreCard.teamTwoName} (${liveScoreCard.teamTwoScore})</td>
        </tr>
    </c:forEach>

</table>

Portlet Descriptor

Now, we will see how to configure the Portlet configuration file so that the Portlet components can be loaded and processed by the framework. Have a look at the following portlet.xml file,
portlet.xml

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

    <portlet>
        <portlet-name>movie</portlet-name>
        <display-name>Movie Service</display-name>
        <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>VIEW</portlet-mode>
        </supports>
        <portlet-info>
            <title>Movie Service</title>
        </portlet-info>
    </portlet>

    <portlet>
        <portlet-name>scorecard</portlet-name>
        <display-name>Live Score-Card Service</display-name>
        <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>VIEW</portlet-mode>
        </supports>
        <portlet-info>
            <title>Live Score-Card Service</title>
        </portlet-info>
    </portlet>

</portlet-app>

This file should reside in WEB-INF/ folder. In the above file, we have defined two Portlets – the movie Portlet and the score-card Portlet. Note that we have defined the Portlet class as DispatcherServlet for both the portlets. This makes the DispatcherPortlet to look for a configuration files with the name movie-portlet.xml and scorecard-portlet.xml in the /WEB-INF folder. We will look into the contents of both these files in the next section.

Portlet Configuration files

In general, the Portlet configuration files will contain the definition of controller objects as well the mapping modes that defines the mapping of the client requests to the handler components. Have a look at the following listing,
movie-portlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <bean id = "movieController" class = "net.javabeat.articles.spring.portlets.sample.movie.MovieController">
        <property name = "movieService" ref = "movieService"/>
    </bean>

    <bean id = "portletModeHandlerMapping" class = "org.springframework.web.portlet.handler.PortletModeHandlerMapping">
        <property name = "portletModeMap">
            <map>
                <entry key = "view" value-ref = "movieController"/>
            </map>
        </property>
    </bean>

</beans>

The above code has the definition of the movie controller which in turns has reference to the movie service component. Note that we have already declared the the movie service in the applicationContext.xml file. Beans declared in this applicationContext.xml are visible throughout all other configurations. We have made use of the built-in mapping mode PortletModelHandlerMapping for directly mapping the mode of the Portlet to appropriate handlers. In this case we have mapped the Portlet view mode to the handler movie controller. Same logic goes into the scorecard Portlet which is defined below.
scorecard-portlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <bean id = "scoreCardController" class = "net.javabeat.articles.spring.portlets.sample.scorecard.ScoreCardController">
        <property name = "scoreCardService" ref = "scoreCardService"/>
    </bean>

    <bean id = "portletModeHandlerMapping" class = "org.springframework.web.portlet.handler.PortletModeHandlerMapping">
        <property name = "portletModeMap">
            <map>
                <entry key = "view" value-ref = "scoreCardController"/>
            </map>
        </property>
    </bean>

</beans>

Deploying the application

The above sample application has to be packaged as a regular web application with the standard directory layout. Now this application has to be deployed in a portal container or a portal server which is compliant to the JSR 168. For example, Pluto Portal ContainerApache – Pluto (from Apache) provides a easy way for deploying portal applications. For example, when deploying Portlet application in Pluto, it is mandatory to define a Pluto invoker Servlet for each Portlet defined in portlet.xml as follows,

<servlet>
    <servlet-name>weather</servlet-name>
    <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class>
    <init-param>
        <param-name>portlet-name</param-name>
        <param-value>movie</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name> movie</servlet-name>
    <url-pattern>/PlutoInvoker/ movie</url-pattern>
</servlet-mapping>

You have to read the documentation available in the Portlet container for deploying the application as the deployment process generally varies between Portal containers.

also read:

Conclusion

In this article, we covered the basics of Portlet development using Spring’s Portlet framework. The article had a walkthrough of the various components in detail explaining about the interaction between them. An important point to remember here is that, even though there are multiple configuration files for wiring-in the components in the Portlet API, separation of components will be of much help while developing larger applications.

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Comments

  1. Hi Krishna
    Im using Liferay with Spring and i have a few doubts related to the integration configuration.

    –> why each portlet has to be defined as a servlet in web.xml? what is the use of doing it so?

    –> when the container reads portlet.xml ? i mean when we deploy the application contextloaderlistener will come in picture and it will instatiate the spring container but how portlet.xml is recognized. will that servletcontainer or portlet container?

    –> do we have both the servlet container and portlet container ?
    if so how these were interacting we have portlet loaded into portlet container and servlets loaded into servlet container then how the interaction takes place.

    please give me some idea or some reference where i can get these stuff im actually ,not able put all these things arranged.

    hope u put me in some right path.

    Thanks in advance

    Surender

  2. Ramesh Sreera says:

    Very good tutorial, simple and intuitive to understand.

Trackbacks

  1. […] Introduction to Spring Portlets […]

Speak Your Mind

*

Close
Please support the site
By clicking any of these buttons you help our site to get better