Saturday 2 April 2016

Developing a JSR 286 Portlet using Spring MVC

As step-by-step approach to develop a portlet using Spring MVC using RAD and deploy in WebSphere portal 8.5


Spring is a very popular framework and it provides lots of features and functionalities, organized in modular fashion. In addition to supporting conventional (servlet-based) Web development, Spring also supports JSR-286 Portlet development. The Portlet MVC framework is a mirror image of the Web MVC framework, and also uses the same underlying view abstractions and integration technology.

Just like any other MVC framework , Spring MVC consists of 3 things. 

1) M-model 
2) V-view 
3) C-Controller. 

Following is the core architecture of Spring (Web) MVC framework.




The Front Controller (Dispatcher Portlet) works as Controller. The front controller takes the incoming request and dispatches to the specific handler (Controller) which has been designed to cater that particular type of request.

The handler(Controller) processes the request and sends the response back to the front controlloer with the help of Model.

The front controller then determines the particular View withe the help of View Resolver and finally send the response back to the client.

 Now let's create a Spring MVC portlet for example. I will use using Rational Application Developer (RAD) for creating the portlet.

Step 1: Open your RAD or Eclipse and create a new portlet project



Step 2: Now modify the type of the portlet and make it a JSR 286 empty portlet




 This will  create the structure of the web project and it will look like this.




Step 3: Now add the spring library and other related jars in our project. Download the following spring  jars from here. Add the jars in the /WEB-INF/lib folder of the project.




Step 4: The next step will be adding the entry of View Renderer servlet in web deployment descriptor. This step is very important. Spring portlet is an extension of the Spring Web MVC and Spring provides support of all its functionalities in portlet context with the help of this renderer servlet. This vervlet works as a bridge between Spring Web MVC and Portlet MVC.

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

Also, add the following entry of Context Loader Listener. This will tie the Application Context to the life cycle of Servlet Context and automate the creation of Application Context. 

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

Step 5: Open the portlet deployment descriptor (portlet.xml) and give entry of the Dispatcher portlet. As described above, the Dispatcher Portlet will serve as the Front Controller and will be responsible to dispatch the request to the contoler specified to hadle that particular type of request.

<portlet >
   ... 
   <portlet-class> org.springframework.web.portlet.DispatcherPortlet</portlet-class>
   ...
</portlet>

There is another entry that you can provide here in portlet.xml is "contextConfigLocation" in case if you want to have a custom name or location of the application context file. If you do not provide any specific location Spring will look for the Application Context file inside "/WEB-INF" by default. 

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value><<location of you Application Context file>> </param-value>
</context-param>

 Step 6: Create a file called ApplicationContext inside "/WEB-INF" and add the entry of ViewResolver there. In Spring framework, DispatcherPortlet will take the help of ViewResolver to choose the view( JSP in our case).So we need to configure view (through View Resolver) in Spring application context file. Add following entry in context file
  
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="cache" value="false" />
<property name="viewClass"
value="org.springframework.web.servlet.view.InternalResourceView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

Step 7 : Now we will create another context file and place it inside WEB-INF folder. The naming convention of the context needs to be <<portletName>> - portlet.xml. S0, in our case it will be "MyFirstSpringMVCPortlet-portlet.xml". This is a context file we will maintain to place all portlet specific configuration parameters. 





Inside the config file register your controllers and DefaultAnnotationHandlerMapping. The DefaultAnnotationHandlerMapping maps request to class and/or methods that are annotated with @RequestMapping.

<bean id="viewController" class="com.springmvc.poc.portlet.controller.ViewController"></bean>
<bean id="editController" class="com.springmvc.poc.portlet.controller.EditController"></bean>
<bean id="helpController" class="com.springmvc.poc.portlet.controller.HelpController"></bean>


<bean class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>

You may find it confusing why we need to maintain 2 different config files (Application Context and MyFirstSpringMVCPortlet-portlet.xml). Actually this is not mandatory. I am just following a good practice by separating the application specific configuration with portlet specific configuration.

Step 8: Now we need to create the controller class in the same package as registered in the context file.

@Controller("viewController")
@RequestMapping(value = "VIEW")
public class ViewController {

@RequestMapping
protected ModelAndView handleRenderRequestInternal(RenderRequest request,
RenderResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();

modelAndView.setViewName("view");

return modelAndView;
}

}

The @Controller is used to denote that this is our controller. Value will be same as class name. Second annotation is @RequestMapping(“VIEW”) which tell to DispatcherPortlet  that this controller will support VIEW mode. Similarly dirrerent controllers has to be added for other modes (EDIT, HELP etc,).

The @RenderMapping annotation denotes the default render method. It means whenever we place this portlet, it will render this method. To handle render request, actions request and event request, separate methods need to be added with annotation @RenderMapping(params = "view=<<view Name>>"), @ActionMapping(value = "<<value>>") and @EventMapping(value = "<<value>>") respectively.

In our example the method returns a ModeAndView onject. The ModelAndView object tries to resolve the view name (view.jsp) inthe pathe we have specified in the our view resolver enetry in the previous step. We have specified the prefix as "/WEB-INF/jsp/" and suffix as ".jsp". So, the DispatcherPortlet with the help of ViewResolver, will try to find "/WEB-INF/jsp/view.jsp" and will try to render it. 


Step 9: Finally, we need to create the jsp in the same location so that it can be rendered.


and will write a small text in the jsp to display after a successful rendering of the portlet.

<%@page session="false" contentType="text/html"
pageEncoding="ISO-8859-1"
import="java.util.*,javax.portlet.*,com.freedommortgage.portlet.loandetailsheaderportlet.controller.*,com.freedommortgage.portlet.loandetailsheaderportlet.model.*"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<fmt:setBundle
basename="com.freedommortgage.portlet.loandetailsheaderportlet.nl.FMC_LoanDetailsHeaderPortletResource" />
<portlet:defineObjects />

<h3>MyFirstSpringMVCPortlet rendered successfully<h3>

Step 10: Now we are all set to deploy and test our Spring MVC portlet. Once deployed and added to a portal page, it will render display the jsp.




3 comments:

  1. Very well written. Nice step-by-step explanation, even for newbies to follow.

    ReplyDelete
  2. Very nice... But two thing
    Portlet different config is not sure bcoz u r calling different controller based on portlet mode whereas u can handle this mode related think in custom controller.
    Second plz mention how using diff action par we can call diff method of same controller... This is most useful feature of spring portlet...
    Otherwise very thorough and well written.

    ReplyDelete
  3. Very nice... But two thing
    Portlet different config is not sure bcoz u r calling different controller based on portlet mode whereas u can handle this mode related think in custom controller.
    Second plz mention how using diff action par we can call diff method of same controller... This is most useful feature of spring portlet...
    Otherwise very thorough and well written.

    ReplyDelete