Liferay7 service builder tutorial

Liferay7 service builder tutorial is quick start guide for developers to create business layer in Liferay 7.  In Older versions of Liferay, Service Builder is used to implement business layer and business modal is designed in service.xml. In Liferay 7 there is not that much changes in  service.xml file and the below are changes in Liferay 7 Service builder;

  • There is no service.jar  generation in Liferay 7
  • Create a module of type “Service Builder” and two sub modules are created.
    • api     –  This module holds all service builder interfaces such as sevice, modal
    • service –  This module holds all implementation logic
  • other modules will use the service builder via gradle dependency
  • com.liferay.portal.spring.extender is used to hold common spring config files
    • base-spring.xml
    • cluster-spring.xml
    • hibernate-spring.xml
    • infrastrucure-spring.xml
  • service modules holds only module-hbm.xml and portal-modal-hints.xml files only.

For beginners to learn more on Service builder then click here to access complete Liferay 6 Service Builder Tutorial

For Advanced developers for complete CRUD operations, follow the below tutorial:

Liferay 7 Leave System Portlet Tutorial – Part2

Liferay 7 Portlet Tutorial – part2 is extension to Liferay 7 Portlet Tutorial. In this tutorial, we will implement leave system requirement. Click on READ MORE to access the tutoril.

Liferay 7 Service Builder Tutorial:

 

In Liferay 6.2,  Web resources(JSP,JS,CSS), Portlet Controller and Business logic(Service Builder) all goes into same portlet plugin, but in  Liferay7,  Web MVC  goes in one module and Service Builder goes into another module. Service builder module will be reused in another web modules.  In this tutorial,we will create two project modules

    1. Product – This is mvcPortlet template module that  holds UI and controller code

    2. Product-Services  – This is Service builder template module that holds Service builder code

  • Create a new service builder module in liferay7: Click  on File->New->Liferay module project

    Liferay7 service builder tutorial

    Liferay7 service builder tutorial

  • Select Project Template as “serviceBuilder” and provide package name

    liferay 7 service builder

    liferay 7 service builder

  • It will generate two modules as shown in below liferay7 service builder folders
  • Liferay Service builder generates module called “product-services”. It again will contain “product-services-api” and “product-services-service” sub modules.
  • service.xml file also will be created in product-services-service folder with sample entity “Foo”.
  • Remove the entity Foo and add Product
  • Now run the service builder from Gradle Tasks  – buildService. You can also run from project explorer : Right click on Product-Service->Liferay->Gradle->build-service. It will generate the all service and implementation layer code.

    gradle build service builder

    gradle build service builder

  • product-services-api contains service interfaces and wrapper services like in Liferay6
    • contains modal interfaces – Product.java
    • service layer interface and LocalServiceUtil.java
    • persistence layer interface classes and Utilities classes
    • common exception classes
  • product-services-service contains service implementation layers jar like in liferay 6 service builder.
    • Modal Implementation layers – ProductImpl.java
    • Service Implementation class – ProductLocalServiceImpl.java and ProductServiceImpl
    • Persistence Implementation classes
  • Now Service builder is generated and how to add service builder dependency in another module?
    • Now our UI code is in product moduel that requires “product-services” as dependency
    • open the build.gradle file in product module
    • add below gradle depency
      • 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: "javax.portlet", name: "portlet-api", version: "2.0"
         compileOnly group: "javax.servlet", name: "servlet-api", version: "2.5"
         compileOnly group: "jstl", name: "jstl", version: "1.2"
         compileOnly group: "org.osgi", name: "org.osgi.compendium", version: "5.0.0"
         compileOnly project(":modules:product-services:product-services-api")
        }
  • How to Access Service builder API in controller and JSP?
    • It is as simple as you use it Liferay6. OSGI container will take care of adding providing dependencies.  forget about “@Reference(unbind=”-“)” and Serive Tracker that mentioned in Liferay7
  • view.jsp in product module will be:
    • <%@page import="org.javasavvy.product.service.ProductLocalServiceUtil"%>
      <%@page import="org.javasavvy.product.model.Product"%>
      <%@page import="java.util.List"%>
      <%@ include file="init.jsp" %>
      <p>
       <b><liferay-ui:message key="product_Prodcut.caption"/></b>
      </p>
      <div class="container">
       <b>Add Product</b>
      <portlet:actionURL name="addProduct" var="addProdUrl">
      </portlet:actionURL>
      <aui:form action="<%=addProdUrl %>">
       <aui:input name="name" type="text" style="width: 50%;" />
       <aui:button type="submit" value="submit"/>
      </aui:form>
      </div>
      <%
       List<Product> prList = ProductLocalServiceUtil.getProducts(-1, -1);
      %>
      <h4>List of Products</h4>
      <c:choose>
       <c:when test="<%=prList!=null && prList.size()>0 %>">
       <table>
       <thead>
       <th><td>Name</td></th>
       </thead>
       <tbody>
       <c:forEach items="<%=prList%>" var="product">
       <tr><td>${product.name }</td></tr>
       </c:forEach>
       </tbody> </table>
       </c:when>
       <c:otherwise>
       Empty Products
       </c:otherwise>
      </c:choose>
      
      
  • ProductPortlet.java -> we added addProduct() action method to save product entity
  • package org.javasavvy.product.portlet;
    
    import com.liferay.counter.kernel.service.CounterLocalServiceUtil;
    import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
    import com.liferay.portal.kernel.theme.ThemeDisplay;
    import com.liferay.portal.kernel.util.ParamUtil;
    import com.liferay.portal.kernel.util.WebKeys;
    
    import java.io.IOException;
    import java.util.Date;
    
    import javax.portlet.ActionRequest;
    import javax.portlet.ActionResponse;
    import javax.portlet.Portlet;
    import javax.portlet.PortletException;
    import javax.portlet.RenderRequest;
    import javax.portlet.RenderResponse;
    
    import org.javasavvy.product.model.Product;
    import org.javasavvy.product.service.ProductLocalServiceUtil;
    import org.osgi.service.component.annotations.Component;
    
    @Component(
     immediate = true,
     property = {
     "com.liferay.portlet.display-category=category.sample",
     "com.liferay.portlet.instanceable=true",
     "javax.portlet.display-name=product Portlet",
     "javax.portlet.init-param.template-path=/",
     "javax.portlet.init-param.view-template=/view.jsp",
     "javax.portlet.resource-bundle=content.Language",
     "javax.portlet.security-role-ref=power-user,user"
     },
     service = Portlet.class
    )
    public class ProdcutPortlet extends MVCPortlet {
     
      
     @Override
     public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
     throws IOException, PortletException {
     // TODO Auto-generated method stub
     super.doView(renderRequest, renderResponse);
     }
      
     public void addProduct(ActionRequest actionRequest,ActionResponse response){
      
     ThemeDisplay themeDisplay = (ThemeDisplay) actionRequest.getAttribute(WebKeys.THEME_DISPLAY);
       String name = ParamUtil.getString(actionRequest, "name");
     System.out.println("Product called"+name);
      Product pr = ProductLocalServiceUtil.createProduct(CounterLocalServiceUtil.increment());
     pr.setName(name);
     pr.setCreateDate(new Date());
     pr.setCompanyId(themeDisplay.getCompanyId());
      pr = ProductLocalServiceUtil.addProduct(pr);
     
     }
    }
  • Explanation:
    • ProductLocalService interface can be used via @Reference , but will use ProductLocalServiceUtil for now to easy the development.
    • ProductLocalServiceUtil is class in product-services-api and that uses ServiceTracker internally to load ProductLocalService with below code.
    • ProductLocalServiceUtil calls _serviceTracker.gerService() to load the  service.
      • private static ServiceTracker<ProductLocalService, ProductLocalService> _serviceTracker =
         ServiceTrackerFactory.open(ProductLocalService.class);
  • Now execute gradle task build and deploy from gradle tasks pane.
  • add some value and successs..view-list

Click here download sample liferay7 service builder code along with portlet.(https://github.com/jayaram509/Liferay7/tree/master/liferay-ce-workspace/modules)

11 Comments

  1. Vinay

    Hello Sir, I am facing issue in service builder. In gogo shell its showing “Installed”. when i am trying to start that, its giving exception like this.

    org.osgi.framework.BundleException: Could not resolve module: inventory.services-service [579]
    Unresolved requirement: Import-Package: com.liferay.util.dao.orm; version=”[7.0.0,8.0.0)”

    How to make it “Active”…??

    Reply
    1. Jayaram Pokuri (Post author)

      Hi Vinay,

      Did you add inventory-service as dependency in gradle? If your module is not from liferay templates then use @Referance to load dependent services at runtime.

      Reply
      1. Vinay

        Yes sir. I have given dependency reference in build.gradle of module. But after i wrote some custom-sql, finder… its became “installed” in gogo shell. I didn’t understand that @Reference to load dependent services at runtime. Can you share some example for that?

        Reply
  2. User

    Can you tell me, how to map default service.xml and new service.xml. In detail, I want to map User with UserMembership table as User_UserMembership. After running buildService, when I try to run build it throws some errors in generated files

    Error:

    userPersistence.addUserMemberships(userId, userMemberships);
    ^
    symbol: method addUserMemberships(long,List)
    location: variable userPersistence of type UserPersistence
    D:\Liferay_7_Tomcat\Workspace\Serality\modules\membershipmanagement-service-builder\membershipmanagement-service-builder-service\src\main\java\membershipmanagement\service\builder\service\base\UserMembershipLocalServiceBaseImpl.java:354: error: cannot find symbol
    userPersistence.clearUserMemberships(userId);

    Reply
  3. Deepthi

    How can we map two entities, in which one entity is in core service.xml and other one is our custom service.xml. For Ex. User Vs membership. How can we generate user_membership table.

    Reply
    1. Jayaram Pokuri (Post author)

      Hi Deepthi,

      Liferay does not support entity relationships at all,which means there is no foreign key relation. You need to manage at Business Layer it self.
      If your application requires entity relations then go for custom DAO layer with Hibernate.

      Reply
      1. Deepthi

        Thank you Jayaram. Can you please send me the sample DAO file, its structure and steps to generate entity relationship mappings. So that it will be helpful for me.

        Reply
        1. Varun Kumar

          Hi Deepthi

          Can you please send me the sample DAO file, its structure and steps to generate entity relationship mappings. So that it will be helpful for me.

          Reply
  4. shrikanth

    Hi all,
    i want to make custom-sql query in service builder in Liferay 7 ,can u please provide the steps. so that i can get to know the custom sql in liferay 7

    Reply
  5. mahesh

    Hi developed service-builder template module it is compiled and built but when i try to deploy this module in server its giving “Unresolved requirement Import-package:com.test”.here service module is not getting deployed while api module does.

    Reply
  6. Seth

    This example is not working !

    i’m getting this error when i want to deploy at the last step :

    org.osgi.framework.BundleException: Could not resolve module: com.company.product [500]_ Unresolved requirement: Import-Package: com.company.product.model; version=”[1.0.0,2.0.0)”_ [Sanitized]

    Reply

Leave a Reply to shrikanth Cancel reply

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