Liferay 7 Portlet Tutorial – Part2

This tutorial  is an extension to Liferay 7 Portlet Tutorial. In this tutorial, we will implement basic leave system application with service builder and liferay components.


  • Liferay Eclipse Neon IDE 3.1.0 M1   :   Click here to download
  • Liferay CE Portal  tomcat GA3 :
  • Service Builder

Prerequisite Tutorials: Access the below tutorials if you beginner:

Liferay7 development setup

Liferay 7 development setup tutorial is to setup Liferay 7 development environment in local machine and access this tutorial to setup Liferay Eclipse IDE and tomcat in your local.


Liferay 7 Portlet Tutorial

Liferay 7 Portlet Tutorial tutorial is for beginners and help to learn some of OSGI annotations related to Liferay MVC Portlet.

liferay7 service builder tutorial


Liferay 7 Leave System Tutorial:

  • Liferay Plugin SDK follows plugin directory where one can plugin can hold multiple portlets and web resources. One Plugin can not use as dependency into another, but in OSGI context, one module can be added dependency into another by exporting packages.
  • We will create two modules
    • leave-web   :  This module holds web mvc resources and imports business logic from leave-core
    • leave-core  :  This module holds service builder generated resources and exports business layer
  • create new Leave Web Module in eclipse :  File -> New -> Liferay Module Project ands select project template as “mvc-portlet”New Portlet Module

    • Give the Portlet Controller and package details:Lifeary 7 CRUD Portlet
    • edit the bnd.bnd and update the symbolic name as below:
      • Bundle-Name: leave-web
        Bundle-SymbolicName: org.javasavvy.leave.web
        Bundle-Version: 1.0.0
    • Create New Leave Core Module as same and select Project Template as “Service Builder”Leave Core
  • Edit the bnd.bnd file in leave-core module as below:
    • Bundle-Name: leave-core-service
      Bundle-SymbolicName: org.javasavvy.leave.core.service
  • update Bundle-SymbolicName bnd.bnd file in leave-core-api:
    • Bundle-Name: org.javasavvy.leave.core.api
      Bundle-SymbolicName: org.javasavvy.leave.core.api
  • update Bundle-SymbolicName in  bnd.bnd file in leave-core-service as below:
    • Bundle-SymbolicName: org.javasavvy.leave.core.service
  • Edit Service.xml file and update the package-path to  some meaningful package name and name space also.
    1. <?xml version="1.0"?>
      <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 7.0.0//EN" 
      <service-builder package-path="org.javasavvy.leave">
       <entity local-service="true" name="Leave" remote-service="false" uuid="true">
       <!-- PK fields -->
       <column name="leaveId" primary="true" type="long" />
       <!-- Group instance -->
       <column name="groupId" type="long" />
       <column name="companyId" type="long" />
       <column name="userId" type="long" />
       <column name="userName" type="String" />
       <column name="createDate" type="Date" />
       <column name="modifiedDate" type="Date" />
       <column name="leaveName" type="String" />
       <column name="startDate" type="Date" />
       <column name="endDate" type="Date" />
       <order by="asc">
       <order-column name="createDate" />
       <!-- Finder methods -->
       <finder name="userId" return-type="Collection">
       <finder-column name="userId" />
       <!-- References -->
       <reference entity="AssetEntry" package-path="com.liferay.portlet.asset" />
       <reference entity="AssetTag" package-path="com.liferay.portlet.asset" />
  • Now run the gradle task : buildService in leave-core gradle task side panel and update the export packages on leave-core modue as below:Export Packages
  • The Project structure is :
  • leave-web Liferay 7 Portlet Tutorial
  • leave-core:
    • leave-core-api
    • leave-core-servicesLeave Service Builder Strcure
  • Edit LeaveLocalService Impl and re-run the gradle buildServiceLeave Local Service
  • Now edit build.gradle file in leave-web to add the leave-core-api and leave-core-service module,so update as below and refresh gradle dependencies by right clicking project(Right on Project – Gradle -> Refresh Gradle Project)
    1. dependencies {
       compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "2.0.0"
       compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "2.0.0"
       compileOnly group: "com.liferay.portal", name: "", version: "2.0.0"
       compileOnly group: "com.liferay.portal", name: "com.liferay.portal.impl", version: "2.0.0"
       compileOnly group: "com.liferay", name: "com.liferay.frontend.taglib", version: "2.0.0"
       compileOnly group: "javax.portlet", name: "portlet-api", version: "2.0"
       compileOnly group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
       compileOnly group: "jstl", name: "jstl", version: "1.2"
       compileOnly group: "org.osgi", name: "org.osgi.compendium", version: "5.0.0"
       compileOnly project(":modules:leave-core:leave-core-api")
       compileOnly project(":modules:leave-core:leave-core-service")
  • Edit the  Leave Portlet class and add as we are going to use MVC Commands.
    1. @Component(
       immediate = true,
       property = {
       "javax.portlet.display-name=Leave Application",
       service = Portlet.class
      public class LeavePortlet extends MVCPortlet {
  • view jsp:   liferay introduced liferay-frontend tag lib with lexicon markup view and add attribute markupview=”lexicon” to get lexicon look and feel for admin pages.
     <%@page import="com.liferay.portal.util.PortalImpl"%>
    <%@page import="com.liferay.portal.kernel.portlet.PortletURLFactoryUtil"%>
    <%@page import="javax.portlet.PortletURL"%>
    <%@ include file="../init.jsp" %>
     PortletURL leaveItrUrl = renderResponse.createRenderURL();
    leaveItrUrl.setParameter("mvcPath", "/leave/view.jsp");
    <portlet:renderURL var="addLeaveJSP">
     <portlet:param name="mvcPath" value="/leave/addLeave.jsp"/>
     userId="<%= themeDisplay.getRealUserId() %>"
     userName="<%= themeDisplay.getRealUser().getFullName() %>"
    <div class="container-fluid-1280 main-content-body">
    <liferay-ui:search-container emptyResultsMessage="no-leaves-found" iteratorURL="<%=leaveItrUrl %>" >
     <liferay-ui:search-container-results results="<%= LeaveLocalServiceUtil.getLeaves(searchContainer.getStart(),
     searchContainer.getEnd()) %>" >
     <liferay-ui:search-container-row className="org.javasavvy.leave.model.Leave" modelVar="leave" keyProperty="leaveId" > 
         <portlet:renderURL var="rowURL"> 
              <portlet:param name="backURL" value="<%=currentURL %>" /> 
              <portlet:param name="leaveId" value="${leave.leaveId}" /> 
              <portlet:param name="mvcPath" value="/leave/leaveInfo.jsp"/>
        <liferay-ui:search-container-column-user userId="${leave.userId}" showDetails="false" name="User" />
             <liferay-ui:search-container-column-text property="userName" name="User Name" href="${rowURL}"/> 
             <liferay-ui:search-container-column-text property="leaveName" name="Leave Name" href="${rowURL}"/> 
             <liferay-ui:search-container-column-date property="startDate" name="Start Date"/>
             <liferay-ui:search-container-column-date property="endDate" name="End Date"/>
         <liferay-ui:search-iterator />
    <liferay-frontend:add-menu >
     <liferay-frontend:add-menu-item title='<%= LanguageUtil.get(request,
     "add-leave") %>' url="<%=addLeaveJSP%>" />
  • Edit JSP:  we used mvcActionCommand so it editLeave action will be handled in EditLeaveActionCommand class
    1. <%@ include file="../init.jsp" %>
      Add Leave
      <liferay-portlet:actionURL name="leave_editLeave" var="editLeave">
       <portlet:param name="mvcActionCommand" value="leave_editLeave" />
      <aui:form action="<%= editLeave %>" cssClass="container-fluid-1280" method="post" name="fm">
       <aui:fieldset markupView="lexicon">
       <aui:input name="name" ></aui:input>
       <liferay-ui:input-date name="startDate" monthValue="02" yearValue="2017"></liferay-ui:input-date>
       <liferay-ui:input-date name="endDate" monthValue="02" yearValue="2017"></liferay-ui:input-date>
       <aui:button type="submit"></aui:button>


  • EditLeaveAction Command is:
    • In this class we are not going to use LeaveLocalServiceUtil, we will use LeaveLocalService and use @Reference(unbind =”-“)  for dynamic lookup.
    • @Component(
       property = {
       service = MVCActionCommand.class
      public class EditLeaveActionCommand extends BaseMVCActionCommand {
        private LeaveLocalService leaveService;
        @Reference(unbind = "-")
       protected void setLeaveService(LeaveLocalService leaveService) {
          this.leaveService = leaveService;
       protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse) 
       throws Exception {
           SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
           String name = ParamUtil.getString(actionRequest, "name");
           Date startDate= ParamUtil.getDate(actionRequest, "startDate",sdf );
           Date endDate = ParamUtil.getDate(actionRequest, "endDate", sdf);
          ThemeDisplay themeDisplay = (ThemeDisplay) actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
          long groupId = themeDisplay.getScopeGroupId();
         Leave leave = leaveService.addLeave(name, themeDisplay.getRealUserId(), groupId,
                                  themeDisplay.getCompanyId(), startDate, endDate);
  • init.jsp is:
    • <%@ taglib uri="" prefix="c" %>
      <%@ taglib uri="" prefix="portlet" %>
      <%@ taglib uri="" prefix="aui" %>
      <%@ taglib uri="" prefix="liferay-frontend" %>
      <%@ taglib uri="" prefix="liferay-portlet" %>
      <%@ taglib uri="" prefix="liferay-security" %>
      <%@ taglib uri="" prefix="liferay-theme" %>
      <%@ taglib uri="" prefix="liferay-ui" %>
      <%@ taglib uri="" prefix="liferay-util" %>
      <%@ page import="org.javasavvy.leave.service.LeaveLocalServiceUtil" %>
      <%@page import="com.liferay.portal.kernel.language.LanguageUtil" %>
      <liferay-frontend:defineObjects />
      <liferay-theme:defineObjects />
      <portlet:defineObjects />


+ Icon is provided through liferay-frontend tag

Liferay 7 CRUD Tutorial

Hope this helps.. let me know if you face any issues

7 thoughts on “Liferay 7 Portlet Tutorial – Part2”
  1. I want to return results as objects. Means I write one file with getters and setters and I add result in finderimpl to those getters and setters. In jsp how can I display those values. Any clues?

    1. In LocalServiceImpl, create method that uses FinderImpl/PersistenImpl to pull the results. Use LocalServiceUtil in JSP pages to get the resutl list. LocalServiceUtil uses service tracker object to load the LocalService from OSGI Service Registry and you no need to specify dependency injection via @Referanc. but In Controller classes, Use @Reference annotation to bind the LocalService object.
      My recommendation is, Use MVCPortlet commands where it will split Logic for each action,view and resourcea and to bind the object reference to request. and use JSP’s as view’s rather writing up logic.
      Click here to access that tutorial :

  2. Can you please post an example by modifying search results with search filters?

    FinderImpl results as objects not as entity because, sql query is combination with 2 or more tables. Now how can I append those list in jsp if the list is not returning as entity ? I didn’t understand how to use @Reference.

  3. This tutorial’s content is not enough to work around can u please share it downloadable or showing every class in Content

  4. Hi I want to perform above task in default user_table any suggestion on that.
    I need to perform edit fuctionality on that as well…
    Please suggest.

Leave a Reply

Your email address will not be published. Required fields are marked *