After we configure a well-structred Maven layout for our Liferay project, we will create a simple Spring MVC portlet. You may ask, “Why use Spring MVC and not extend one of the Liferay implementations (e.g. LiferayPortlet or MVCPortlet)?” It’s easy – why restrict your portlet to only run on Liferay? It does not make sense. A portlet should be developed in a way that it can run on any portlet container, not just one. So Spring MVC is a reasonable choice.
Now lets start.

CREATING A NEW PORTLET PROJECT

As already mentioned in my previous blog, let us start by creating a new portlet project:

    mvn archetype:generate
	-DgroupId=com.isostech.liferay.sample
	-DartifactId=sample-portlet
	-Dversion=1.0-SNAPSHOT
	-DarchetypeGroupId=com.liferay.maven.archetypes
	-DarchetypeArtifactId=liferay-portlet-archetype
	-DinteractiveMode=false

Now we can apply the changes to the pom.xml to simplify it. We will end up with a pom.xml file as follows:

<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>
	<parent>
	    <groupId>com.isostech.liferay.sample</groupId>
	    <artifactId>sample-parent</artifactId>
	    <version>1.0-SNAPSHOT</version>
        </parent>
	<groupId>com.isostech.liferay.sample</groupId>
	<artifactId>sample-portlet</artifactId>
	<packaging>war</packaging>
	<name>sample-portlet Portlet</name>
	<build>
	    <plugins>
	        <plugin>
	            <groupId>com.liferay.maven.plugins</groupId>
	            <artifactId>liferay-maven-plugin</artifactId>
	            <configuration>
	                <pluginType>portlet</pluginType>
	            </configuration>
	        </plugin>
	    </plugins>
	</build>
<dependencies>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>portal-service</artifactId>
</dependency>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>util-bridges</artifactId>
</dependency>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>util-taglib</artifactId>
</dependency>
<dependency>
<groupId>com.liferay.portal</groupId>
<artifactId>util-java</artifactId>
</dependency>
<dependency>
<groupId>javax.portlet</groupId>
<artifactId>portlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</dependency>
</dependencies>
    </project>

CLEANING UP THE PROJECT

After the project has been created and we have cleaned up the pom.xml file, let’s take a look what was created and what else we have to clean up. First you will notice that the view.jsp file shows the following error message: “Can not find the tag library descriptor for “http://java.sun.com/portlet_2_0”. To fix the issue first copy the TLD files into the newly created folder WEB-INF/tld. After that we should update the web.xml file and add the proper taglib definition.

	<jsp-config>
	   <taglib>
	     <taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>
	     <taglib-location>/WEB-INF/tld/liferay-portlet.tld</taglib-location>
	   </taglib>
	</jsp-config>

The other files that were generate are portlet.xml, liferay-portlet.xml, and liferay-display.xml.

CREATING AN EMPTY PORTLET CLASS AND CHANGING THE CONFIGURATION FILES

To use to he spring-portlet-mvc feature we have to add some additional dependencies. We will add them to the parent project so that we will have them available to all future development. The dependencies that we should add are:

	<!-- Spring Framework Dependencies -->
	<dependency>
	   <groupId>org.springframework</groupId>
	   <artifactId>spring-beans</artifactId>
	   <version>${springframework.version}</version>
	</dependency>
	<dependency>
	   <groupId>org.springframework</groupId>
	   <artifactId>spring-context</artifactId>
	   <version>${springframework.version}</version>
	</dependency>
	<dependency>
	   <groupId>org.springframework</groupId>
	   <artifactId>spring-webmvc-portlet</artifactId>
	   <version>${springframework.version}</version>
	</dependency>
	<dependency>
	   <groupId>org.springframework.ws</groupId>
	   <artifactId>spring-ws-core</artifactId>
	   <version>${springframework.ws.version}</version>
	</dependency>
	<dependency>
	   <groupId>org.springframework.ws</groupId>
	   <artifactId>spring-ws-core-tiger</artifactId>
	   <version>${springframework.ws.version}</version>
	</dependency>
	<dependency>
	   <groupId>org.springframework</groupId>
	   <artifactId>spring-expression</artifactId>
	   <version>${springframework.version}</version>
	</dependency>
	<!-- Apache Commons Dependencies -->
	<dependency>
	   <groupId>commons-lang</groupId>
	   <artifactId>commons-lang</artifactId>
	   <version>2.6</version>
	</dependency>
	<dependency>
	   <groupId>commons-io</groupId>
	   <artifactId>commons-io</artifactId>
	   <version>2.1</version>
	</dependency>
	<dependency
	   <groupId>commons-net</groupId>
	   <artifactId>commons-net</artifactId>
	   <version>3.0.1</version>
	</dependency>
	<dependency>
	   <groupId>org.hibernate</groupId>
	   <artifactId>hibernate-validator</artifactId>
	   <version>4.0.0.GA</version>
	</dependency>
	<dependency>
	   <groupId>org.slf4j</groupId>
	   <artifactId>slf4j-log4j12</artifactId>
	   <version>1.5.6</version>
	</dependency>

The portlet implementation will be very simple. For more information about how to create complex Spring MVC portlets I recommend the book “Portlets in Action” by Asish Sarin.

package com.isostech.portlet;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.portlet.bind.annotation.RenderMapping;
@Controller(value="sample")
@RequestMapping(value="VIEW")
public class SamplePortlet {
    @RenderMapping
    public String showForm(RenderRequest request, RenderResponse response) throws Exception {
        return "view";
    }
}

The only thing left is to wire everything up. Lets start with the web.xml. Here we have to add the ViewRenderServlet.

<servlet>
    <servlet-name>view-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>view-servlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>5</session-timeout>
</session-config>

Next we have to define the portlet in the portlet.xml file. You will see that instead of using the portlet implementation itself the DispatcherServlet is used. That goes very much in sync with the standard implementation of any Spring MVC web application. You’ll also notice the special context configuration file. I like to define a specific file for each portlet.

    <?xml version="1.0"?>
    <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>sample-portlet</portlet-name>
	  <portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
	  <init-param>
	   <name>contextConfigLocation</name>
	   <value>classpath:/portlets/contexts/sample-portlet.xml</value>
	  </init-param>
	  <supports>
	   <mime-type>text/html</mime-type>
	   <portlet-mode>view</portlet-mode>
	  </supports>
	  <portlet-info>
	   <title>sample-portlet</title>
	   <short-title>sample-portlet</short-title>
	   <keywords>sample-portlet</keywords>
	  </portlet-info>
	  <security-role-ref>
	   <role-name>administrator</role-name>
	  </security-role-ref>
	  <security-role-ref>
	   <role-name>guest</role-name>
	  </security-role-ref>
	  <security-role-ref>
	   <role-name>power-user</role-name>
	  </security-role-ref>
	  <security-role-ref>
	   <role-name>user</role-name>
	  </security-role-ref>
	</portlet>
    </portlet-app>

The last configuration is the sample-portlet.xml file itself. In this exercise I use the bean definition for the controller, but you can also just wire up the component-scan. Again, you don’t have to follow the sample here, but I prefer to separate the views (jsp files) for each portlet into their own folders, in this case “_SamplePorlet”.

        <?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:context="http://www.springframework.org/schema/context"
            xmlns:util="http://www.springframework.org/schema/util"
            xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.1.xsd
                http://www.springframework.org/schema/util
                http://www.springframework.org/schema/util/spring-util-3.1.xsd
                ">
        <bean id="sample" class="com.isostech.portlet.SamplePortlet">
        </bean>
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
            <property name="prefix" value="/_SamplePortlet/" />
            <property name="suffix" value=".jsp" />
        </bean>
    </beans>

The only thing that is left to do is implement the view.jsp file. In our case we will just use a simple “Hello World”. The liferay-portlet.xml and liferay-display.xml files have to be adjusted to the correct portlet id. After these changes, just run the Maven comment “mvn clean install liferay:deploy -Ptomcat” and the portlet will build and deploy to you local liferay instance.

CONCLUSION

There is no need to restrict yourself to a Liferay specific implementation of a portlet. I highly recommend using the standard Spring Portlet MVC components that allow clean and portable development of portlets. If you want to dig deeper into the features of Spring Portlet MVC please read the “Portlets in Action” book. As usual you can find the complete sample code at https://github.com/thbehlau/sample-liferay.git