Tuesday, December 24, 2013

Liferay Spring Portlet


Environment:   Liferay Portal 6.2 CE+ Tomcat Server 7.x + MySQL 5.1

Objective:

Create Spring Portlet in Liferay.

Download Liferay Spring portlet from following location

You can find source and war file



Portlet Screen:





Procedure for deploy portlet:

You can use war file and directly place in your portal deploy folder and test or you can also use source to deploy portlet.

Once portlet is deployed successfully you can see the portlet in sample category name as LiferaySpring

Spring portlet MVC is inherited from spring MVC so we can use spring portlet MVC to create portlets and we can deploy spring portlet in JSR 168 and JSR 286 standards portals.

Liferay have out box portlet support for Spring Portlets. We can also use Spring Portlet MVC to create portlet and can deploy into liferay portal.

Spring have annotation support so that we can develop portlet using annotation.

Here I am using spring annotation with Spring Portlet MVC in liferay environment.

Liferay portal already have all spring frame work jar files and hibernate jar file we can use same jar file in portlet or we can use latest spring jars in portlet.

If we use the jars which are in liferay portal then application size will be become smaller.

If we use our own jar files then portlet size will become more and if we deploy more portlets then each portlet context may have same spring and hibernate jars.

Note:

If we use portlet in only liferay environment then better we will use liferay portal spring jars.

If we want use spring portlet in other portals then we will use independent spring jars which are specific to portlet context.

To add liferay portal spring jar files for portet then we have to use following property in liferay-plugin-package.properties as follows

portal-dependency-jars=\
  aopalliance.jar,\
  commons-logging.jar,\
  commons-io.jar,\
  jstl-api.jar,\
  jstl-impl.jar,\
  log4j.jar,\
  slf4j-api.jar,\
  spring-aop.jar,\
  spring-asm.jar,\
  spring-beans.jar,\
  spring-context.jar,\
  spring-context-support.jar,\
  spring-core.jar,\
  spring-expression.jar,\
  spring-web.jar,\
  spring-web-portlet.jar,\
  spring-web-servlet.jar

When we use spring portlet in liferay we have following options

We can use spring portlet MVC +Liferay service Builder.
Spring portlet MVC+ Spring DAO implementation with Hibernate.

Note:

In the following example I have used pure Spring Portlet MVC with Spring DAO implementation using Hibernate.

The following are the important Annotation which we have used in liferay spring portlet

Spring Frame Work Annotations


@RenderMapping
@ActionMapping
@Controller
@RequestMapping
@Service
@Transactional
@Repository
@Autowired

The following  is reference link to know more about annotations




Hibernate JPA annotation

@Id
@Column
@Entity
@Table
@GeneratedValue

The following  is reference link to know more about annotations



In the Example the following things we have used

Spring Portlet MVC
Spring Portlet DAO implementation using Hibernate
Hibernate annotation and Sprig annotation
Java Persistence API

Required Steps to create Spring Portlet in Liferay

Note:

Here we will create liferay MVC portlet then will convert to spring portlet.
  1. Create Liferay MVC portlet using Liferay IDE in Eclipse
  2. Configure View Render Servlet in web.xml
  3. Configure Context Loader Listener in web.xml
  4. Create Application Context XML file and configure in web.xml
  5. Configure View Resolvers to identify the views in the application context xml file
  6. Configure Data Source in Application Context XML file
  7. Configure Hibernate Session Factory application context xml file
  8. Load DAO and Service classes using Annotation Driven.
  9. Configure Spring Dispatcher Portlet class in Portlet.xml file.
  10. Configure Requires Name Spaced Parameters to false in liferay-portlet.xml
  11. Create portleName-portlet.xml file and configure in portlet.xml file
  12. Configure portlet handler in PortletName-portlet.xml
  13. Develop controller for portlet
  14. Create view using JSP Page

Create Spring MVC portlet using Liferay IDE in Eclipse

Here we will create liferay MVC portlet then will convert to spring portlet.
Setup liferay portlet environment and create Simple Liferay MVC portlet using liferay IDE. We are going to use this portlet to make spring portlet.

Configure View Render Servlet in web.xml

Configure view render servlet in portlet web.xml file this servlet use to render content. This is central servlet which is usfed for liferay.

The following configuration have to done in web.xml

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

Configure Context Loader Listener in web.xml

Now we need configure context loader listener in web.xml file. This will initiate loading all configurations with respect to portlet when portlet context is ready.

The following is configuration in web.xml


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


Create Application Context XML file and configure in web.xml

Now we need to create one application context xml file in portlet WEB-INF directory. From this we will load all spring beans.

Name can be anything but we need to configure this file information in web.xml file as contextConfigLocation context parameter.

By default Context Loader Lister looking for xml file name with applicationContext.xml if we change the name then we have to specifies as contextConfigLocation context parameter.

Assume our file name portletApplicationContext.xml

Then the following is configuration in web.xml file

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

Configure View Resolvers to identify the views in the Application Context XML file

Once we create the application context file then we need to configure view resolver bean to identify the views in application

The following is configuration in application context xml file (portletApplicationContext.xml)

<bean id="viewResolver" 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>

Configure Data Source in Application Context XML file

Now we need to configure data source to the portlet.  

The following data source configuration in application context xml files (portletApplicationContext.xml)

<context:property-placeholder location="/WEB-INF/spring.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                        <property name="driverClassName">
                                    <value>${jdbc.driverClassName}</value>
                        </property>
                        <property name="url">
                                    <value>${jdbc.url}</value>
                        </property>
                        <property name="username">
                                    <value>${jdbc.username}</value>
                        </property>
                        <property name="password">
                                    <value>${jdbc.password}</value>
                        </property>
</bean>

Note: 

To get the properties from properties file we need configure the properties file location with following XML tag.

<context:property-placeholder location="/WEB-INF/spring.properties" />

Configure Hibernate Session Factory application context xml file

Once data source is configure then we need configure hibernate session factory and we need  to pass data source to session factory and some of hibernate properties we need to configure.

Here we need to mention POJO classes information to map relation database data to persistence objects with packagesToScan property.

The following is session Factory configuration in application context xml files (portletApplicationContext.xml)

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
                        <property name="dataSource" ref="dataSource" />
                        <property name="packagesToScan">
                                    <list>
                                                <value>com.meera.liferay.spring.domain</value>
                                    </list>
                        </property>
                        <property name="hibernateProperties">
                                    <props>
                                                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                                                <prop key="hibernate.show_sql">false</prop>
                                                <prop key="hibernate.hbm2ddl.auto">update</prop>
                                    </props>
                        </property>
</bean>

Load DAO and Service classes using Annotation Driven

Now we need to load all DAO classes and Service classes in portlet context to interact with database in controllers.

The following is the annotation which will load all beans using annotation

<context:annotation-config />
<context:component-scan base-package="com.meera.liferay.spring.dao" />
<context:component-scan base-package="com.meera.liferay.spring.service" />
<tx:annotation-driven />


 Configure Spring Dispatcher Portlet class in Portlet.xml file.
.
We need specify the Spring Dispatcher portlet in portlet.xml file. This class handles the spring portlet lifecycle in liferay portal.

The following is configuration for portlet.xml file


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


Configure Requires Name Spaced Parameters to false in liferay-portlet.xml
Now need to do require Name spaced parameters to false then only form data is mapped in Action Request and Render Request. And also form data will be binding to model object or command object.

The following is configuration we need to do in liferay-portlet.xml file


<requires-namespaced-parameters>false</requires-namespaced-parameters>
                       

Create portleName-portlet.xml file and configure in portlet.xml file

Now we have done all configurations for portlet context. Now we need to create one xml file which has only portlet related configurations.

We need create one XML file like portletName-portlet.xml file in portlet WEB-INF directory.

Dispatcher portlet class is always looking for prtlerName-portlet.xml file to load portlet related beans.

If we change the name then we have to mention as contextConfigLocation init parameter to Dispatcher portlet class.

The following is configuration in portlet.xml file

<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>/WEB-INF/LiferaySpring-portlet.xml</value>
</init-param>

Configure portlet handler in PortletName-portlet.xml

Handlers are nothing but controllers we need to configure portlet handle so that it will invoke by portlet urls.

We have different handler available in Portlet MVC we are configuring portlet mode handler which will invoke the controller based on portlet mode present in URLs.

The following is configuration in portletName-portlet.xml (LiferaySpring-portlet.xml)

<context:annotation-config />
<tx:annotation-driven />
<context:component-scan base-package="com.meera.liferay.spring.controller" />
<bean id="portletModeHandlerMapping"
class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
<property name="portletModeMap">
<map>
<entry key="view">
<ref bean="contactController" />
</entry>
</map>
</property>

Note:

 We need to add annotation support to load controllers from annotations.


Develop controller for portlet

We have done all configurations. Now we need to implement controller to handle tasks for portlet. In controller each method is invoked by Request Parameter mapping. 

We have used different annotation to implement controller and we injected services using Autowired annotation to interact with database.

The following is example for controller

@Controller("contactController")
@RequestMapping("VIEW")
public class ContactController    {

       @Autowired
       private ContactService contactService;
      
       @RenderMapping
       public String listContacts(Map<String, Object> map) {
              map.put("contact", new Contact());
              map.put("contactList", contactService.listContact());
              return "contact";
       }
      
       @ActionMapping(params = "action=add")
       public void addContact(ActionRequest actionRequest,ActionResponse actionResponse, Model model,@ModelAttribute("contact") Contact contact, BindingResult result) throws IOException,
                     PortletException {
              System.out.println("result"+ParamUtil.getString(actionRequest,"firstname"));
              System.out.println("contact"+contact.getFirstname());
              contactService.addContact(contact);
              //return "contact";
             
       }
      
       @ActionMapping(params = "action=delete")
       public void deleteContact(@RequestParam("contactId") Integer contactId,ActionRequest actionRequest,ActionResponse actionResponse, Model model) throws IOException,
                     PortletException {
              System.out.println("resul344444444444444t");
              contactService.removeContact(contactId);
              //return "contact";
             
       }

}


Create view using JSP Page.

Now we will develop view using JSP page. In JSP we have used spring form tags which have capability to populate request data into model object or command object. This can be done by spring form model attribute or command attributes for form tag. In the JSP we also used portlet URL to invoke controller and JSTL tags.

The following is example code in JSP


<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<h2>Contact Manager</h2>
<portlet:actionURL var="addContactURL">
<portlet:param name="action" value="add"></portlet:param>
</portlet:actionURL>
<portlet:actionURL var="deleteContactURL">
<portlet:param name="action" value="delete"></portlet:param>
</portlet:actionURL>
<form:form name="contact" modelAttribute="contact" method="post" action="${addContactURL}" >
<table>
<tr>
<td><form:label path="firstname"><spring:message code="label.firstname"/></form:label></td>
<td><form:input path="firstname" /></td>
</tr>
<tr>
<td><form:label path="lastname"><spring:message code="label.lastname"/></form:label></td>
<td><form:input path="lastname" /></td>
</tr>
<tr>
<td><form:label path="email"><spring:message code="label.email"/></form:label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><form:label path="telephone"><spring:message code="label.telephone"/></form:label></td>
<td><form:input path="telephone" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="<spring:message code="label.addcontact"/>"/>
</td>
</tr>
</table>     
</form:form> 
<h3>Contacts</h3>
<c:if  test="${!empty contactList}">
<table class="data">
<tr>
       <th>Name</th>
       <th>Email</th>
       <th>Telephone</th>
       <th>#</th>
</tr>
<c:forEach items="${contactList}" var="contact">
       <tr>
              <td>${contact.lastname}, ${contact.firstname} </td>
              <td>${contact.email}</td>
              <td>${contact.telephone}</td>
              <td><a href="${deleteContactURL}&contactId=${contact.id}">delete</a></td>
       </tr>
</c:forEach>
</table>
</c:if>

Important points
  • When we develop spring portlet we can all spring jars which are available in liferay portal or we can manually add all latest spring jar files.
  • In the portlet we did all service layer implementation using Hibernate and Java persistence API we can also use liferay service builder for spring portlet so that we can reduce our work to create service layer.
  • We can use spring tag libraries and liferay tag libraries in portlet.
  • If we add more liferay support to spring portlet then it will tightly coupled with liferay portal. If we use independent spring MVC portlet support then we can also use this portlet in other environment with minimal configurations.

Note:

When we deploy this portlet in other version liferay we may get some issues.

Related Articles


Reference Links


Author

Meera Prince

Popular Posts

Recent Posts

Recent Posts Widget