Liferay service builder concept

Liferay provides a nice way of creating service and persistence layer. Liferay Service Builder is a tool to create service-persistence layer.

Service and persistence layer is a one of the most important and complex part of any application. As a java developer you may experience the amount of effort you put to develop service – persistence layer from scratch.

While working with Liferay, you may came across the situation where you need to save / update / retrieve / delete the data from Database in your custom portlet.

For example you are developing a portal for school management in liferay. You want to develop one portlet called student management which will add / updates / read / delete student information into database.

As a tradition, if you want to achieve this, you may write your own service-persistence layer and liferay still supports it. However Liferay provides smart alternate called Liferay service builder.

Liferay Service Builder

What is a Liferay service builder?

Liferay Service Builder is a tool to create a service-persistence layer in Liferay. It uses spring and hibernates internally to generate a set of classes, SQL scripts, and configuration files to interact with the database. It does these low-level jobs so you will get rid of writing this boilerplate code and concentrate on writing business logic. This way It saves the development time of building the service-persistence layer manually. Sounds good rt?

This article talks about the basics of Liferay service builder and its underlying concept.

What should be provided as input to Liferay Service Builder?

Liferay service builder takes service.xml file as an input and generates set of classes and interfaces to perform CRUD operation on Database.

What is the content of service.xml?

In service.xml, you need to define your business entities and their relation. Each entity in servce.xml represent DB table and attributes of entity are mapped to table column. You can define multiple entities in the same service.xml file. You can also take the references of entities defined by service.xml in other portlets.

Where to place service.xml?

Liferay expects you to place the service.xml on specific path. It should be placed under /WEB-INF folder as per below screenshot.

Servicexml_location - Liferay service builder

How to run a Liferay service builder?

There are two ways to run Liferay service builder.

  • From command prompt
    • Open the command prompt and go your portlet folder and fire a command ‘ant build-service
  • From Liferay IDE or Liferay Developer Studio.
    • In your Liferay IDE right click on service.xml and select Liferay–>Build Services as per below screenshot.

Build_Service_From_Liferay_IDE - Liferay service builder

Can I place more than one service.xml file for single plugin project ?

No. You can’t. Liferay expects you to place service.xml directly under /WEB-INF and you can’t place more than one file with same name in same folder. In general you can have one service.xml per one liferay plugin project. You can place different service.xml in different plugin project. Bottom line is – each plugin project can have only one service.xml file.

How Liferay Service builder works internally ?

Liferay service builder do a great job for us. It saves our development time by creating service-persistence layer automatically. You may want to know how this magic happens. Let’s understand how liferay service builder works internally.

There are two ways to create, build and deploy plugins in Liferay – Maven and Ant. Maven was added starting from liferay 6.2. Prior to 6.2, Ant was the way to build plugins out of the box. I have used Ant which is easy to understand.

For Ant based system, you must have to use liferay-plugin-sdk. When you build service by executing ant build-service command from command line or from Liferay IDE, it will execute build-service ant target from build-common-plugin.xml file. This file is located under your liferay-plugins-sdk folder.

To understand the build file reference, open build.xml file in your portlet. It imports build-common-portlet.xml which is located under liferay-plugins-sdk/portlets folder. build-common-portlet.xml imports build-common-plugin.xml which is located under liferay-plugins-sdk folder and build-service ant target is located in build-commn-plugin.xml file. build-service ant target looks like below snippet

       <target name="build-service">
		<mkdir dir="docroot/WEB-INF/classes" />
		<mkdir dir="docroot/WEB-INF/lib" />
		<mkdir dir="docroot/WEB-INF/service" />
		<mkdir dir="docroot/WEB-INF/sql" />
		<mkdir dir="docroot/WEB-INF/src" />

		<copy todir="docroot/WEB-INF/classes">
			<fileset dir="docroot/WEB-INF/src" excludes="**/*.java" />

		<path id="service.classpath">
			<path refid="lib.classpath" />
			<path refid="portal.classpath" />
			<fileset dir="${app.server.lib.portal.dir}" includes="commons-digester.jar,commons-lang.jar,easyconf.jar" />
			<fileset dir="docroot/WEB-INF/lib" includes="*.jar" />
			<pathelement location="docroot/WEB-INF/classes" />

			<os family="windows" />

				<isset property="service.input.file" />
				<property name="service.input.file" value="${basedir}/docroot/WEB-INF/service.xml" />

			<jvmarg value="-Xms512m" />
			<jvmarg value="-Xmx1024m" />
			<jvmarg value="-Xss2048k" />
			<jvmarg value="-XX:MaxPermSize=512m" />
			<arg value="-Dexternal-properties=com/liferay/portal/tools/dependencies/" />
			<arg value="-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger" />
			<arg value="service.input.file=${service.input.file}" />
			<arg value="service.hbm.file=${basedir}/docroot/WEB-INF/src/META-INF/portlet-hbm.xml" />
			<arg value="service.orm.file=${basedir}/docroot/WEB-INF/src/META-INF/portlet-orm.xml" />
			<arg value="service.model.hints.file=${basedir}/docroot/WEB-INF/src/META-INF/portlet-model-hints.xml" />
			<arg value="service.spring.file=${basedir}/docroot/WEB-INF/src/META-INF/portlet-spring.xml" />
			<arg value="service.spring.base.file=${basedir}/docroot/WEB-INF/src/META-INF/base-spring.xml" />
			<arg value="service.spring.cluster.file=${basedir}/docroot/WEB-INF/src/META-INF/cluster-spring.xml" />
			<arg value="${basedir}/docroot/WEB-INF/src/META-INF/dynamic-data-source-spring.xml" />
			<arg value="service.spring.hibernate.file=${basedir}/docroot/WEB-INF/src/META-INF/hibernate-spring.xml" />
			<arg value="service.spring.infrastructure.file=${basedir}/docroot/WEB-INF/src/META-INF/infrastructure-spring.xml" />
			<arg value="${basedir}/docroot/WEB-INF/src/META-INF/shard-data-source-spring.xml" />
			<arg value="service.api.dir=${basedir}/docroot/WEB-INF/service" />
			<arg value="service.impl.dir=${basedir}/docroot/WEB-INF/src" />
			<arg value="service.json.file=${basedir}/docroot/js/service.js" />
			<arg value="service.sql.dir=${basedir}/docroot/WEB-INF/sql" />
			<arg value="service.sql.file=tables.sql" />
			<arg value="service.sql.indexes.file=indexes.sql" />
			<arg value="" />
			<arg value="service.sql.sequences.file=sequences.sql" />
			<arg value="" />
			<arg value="service.bean.locator.util=com.liferay.util.bean.PortletBeanLocatorUtil" />
			<arg value="service.props.util=com.liferay.util.service.ServiceProps" />
			<arg value="${}" />
			<arg value="${}" />

			<os family="windows" />
				<delete file="build-service-classpath.jar" />

		<delete file="ServiceBuilder.temp" />


			<contains string="${build-service.output}" substring="Error" />
				<fail>Service Builder generated exceptions.</fail>

		<mkdir dir="docroot/WEB-INF/service-classes" />

		<path id="service.classpath">
			<path refid="lib.classpath" />
			<fileset dir="${}" includes="*.jar" />
			<fileset dir="docroot/WEB-INF/lib" excludes="${}-service.jar" includes="*.jar" />



		<delete dir="docroot/WEB-INF/service-classes" />

Quick Observation

  • The first few links of code will create various folders like classes, lib, service, SQL and src
  • Then it’s setting some jars into the service builder classpath which are used to generate the service-persistence code.
  • Then it’s reading our service.xml file in line no 35. If you want to set different path of Service.xml, you can make a change here. This will be then applicable to all plugin project.
  • Next, it’s calling class. This class does the magical job of creating a set of classes and files. It’s available in portal-impl.jar
  • This class takes various arguments like service.xml file path, spring and hibernate configuration files, SQL script, and other configuration file path. It will parse service.xml file and generate the source code (of service persistence layer) and files in the path specified in various arguments. You can observe the source code of this class from Liferay source. For this you need to configure liferay source in your Liferay IDE.
  • In the end, it compiles the generated source and creating a service jar file. This service jar contains the set of classes that are used to make a call to service-persistence API.

This all about the high-level introduction of service builder.

A practical example of Liferay service builder

  • Now you are aware of what is service builder and how it works internally. To better understand, you need a practical example.
  • You may visit my blog on Liferay service builder with practical example. In this article, I took a real example to build a service-persistence layer and explain the relationship between the generated java classes.

Benefits of using Liferay Service Builder

  • Since it’s designed by Liferay, it can be easily Integrate with any plugin developed in Liferay.
  • Based on the defined entities, it generates model, persistence, and service layer classes along with local and remote service.
  • It uses spring and hibernate internally so it generates underlying hibernate and spring configurations with just one click.
  • Along with basic CRUD operation, It allows writing custom read method. These custom read methods are called finder methods in Liferay. We can write different finder methods with different arguments and criteria.
  • One of the important advantages of using the Liferay service builder is it supports entity-level caching which helps to improve the performance of reading queries.
  • If your business requirement doesn’t satisfy the basic CRUD operation and finder method, you can still write custom SQL queries and dynamic queries in the Liferay service builder. This can be useful in a case when you want to access information from multiple tables by SQL join.
  • Liferay service builder generates all boilerplate code which will save overall development time.

Summing Up

  • Liferay service builder is a tool to generate service-persistence code in Liferay
  • It takes the service.xml file as input and generates the set of classes and interfaces to interact with the Database.
  • Go to Liferay documentation and search for Service Builder to get more ideas.

Recommended For You

About the Author: Nilang

Nilang Patel is a technology evangelist who loves to spread knowledge and helping people in all possible ways. He is an author of two technical books - Java 9 Dependency and Spring 5.0 Projects.

4 Comments to “Liferay service builder concept”

    1. Hello Hung Tran,

      Thanks for the appreciation and welcome to Tech Blog. Feel free to ask questions / give suggestion.


  1. Great post but a small correction. By default the service builder process will look for a service.xml file in the WEB-INF folder but you dont have to place it there. You can pass in the location of the file using a -DserviceFileName parameter. With this approach you can specify multiple service.xml files, or infact even call them something else altogether — it just means that you need to run the process once for each file/location. If you have a look at the portal source you’ll see that there are multiple service.xml files — basically one per “portlet” so that you can have multiple packages for the generated code.

    1. Hi Andrew,

      Welcome to Tech blog. Appreciate your suggestion and Thanks for giving valuable feedback. I will definately will check for parameter and multiple service.xml file.

      Feel free to ask questions / give suggestions

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.