In my last article on Creating Service layer with Service builder in Liferay we have seen how to create service layer for each entity in liferay through service builder. We took Student entity to understand it.
In this article we will see some useful trick to add custom method in service layer. We will go ahead with the same example that we took in Creating Service layer with Service builder in Liferay article, So I strongly recommend to go through it before starting this article.
Follow all the steps in last article (Creating Service layer with Service builder in Liferay) and create the student entity. After service build, it will create the StudentLocalSerciceUtil class with following methods.
If you observe, this class contains basic CRUD methods. Many business scenarios, we need to get data based on some condition.
For example, If I want to fetch all the students who are in standard 8, there is no direct method available. At max we can call getStudents method (Which will return all students) and then from the list we can take 8th standard student programatically. But this is not efficient way. In case of let say 10000 students, if the total no of 8th standard student is just 30, then there is no meaning to fetch all 10000 students.
Liferay provides finder method technique to achieve this. Let us see how to write finder method.
So far now, we have created the student entity as per below snippet(I am omitting DTD definition).
<entity name="Student" local-service="true" remote-service="false">
<column name="studentId" type="long" primary="true" />
<column name="name" type="String" />
<column name="age" type="int" />
<column name="fatherName" type="String" />
<column name="motherName" type="String" />
<column name="standard" type="int" />
</entity>
We are going to add finder method in this entity. Generally finder methods are build on columns so first we need to identify on which column(s) we want finder methods.
In our case we want to search all the students who are from 8th Standard. So we will write finder method on column standard. We will add the finder element for standard column so that finally it will looks like below snippet.
<entity name="Student" local-service="true" remote-service="false">
<column name="studentId" type="long" primary="true" />
<column name="name" type="String" />
<column name="age" type="int" />
<column name="fatherName" type="String" />
<column name="motherName" type="String" />
<column name="standard" type="int" />
<finder return-type="Collection" name="Standard">
<finder-column name="standard"/>
</finder>
</entity>
Explanation:-
- We have defined one element (finder) inside student entity. This will create finder method for column standard.
- The value of return-type is Collection which means that the return type of finder method will be List<T>.
- The value of name attribute will be used to construct finder method name. We gave Standard so the generated finder method name will be findByStandard().
- Note:- You can give any value in name attribute of <finder> element. The only thing you need to make sure it to give first letter as capital. It will still work if you give first letter small. But then the method name become findBystandard() which should be findByStandard() (Camel Case as Java coding standard).
- <finder-column> element Inside the <finder> element represents the column name.
- the name attribute of <finder-column> element represents the name of the column. It should have exact same name as <column>'s name attribute of which we want finder method.
Now run the service builder by ant build-service command and refresh the page. After running it, the finder method won't be directly created inside StudentLocalServiceUtil class. The finder method will be created inside
- StudentPersistence.java (under /WEB-INF/service/com/opensource/techblog/myservice/service/persistence/)
- StudentPersistenceImpl.java (under WEB-INF/src/com/opensource/techblog/myservice/service/persistence).
The first is the interface and the second is it's implementation. You will observe that the method findByStandard(int standard) is created in above interface and class.
The only class accessible outside the service builder is StudentLocalServiceUtil.
This class (StudentLocalServiceUtil) can be used to perform CRUD operation. We need to make sure the finder method is also available in this class. (to access it in our portlet class).
So let us see how to achieve this. Our half work is done (finder method is available in persistence class).
If you remember from previous blog (Creating Service layer with Service builder in Liferay), the only service class that is available to add custom method is StudentLocalServiceImpl.java (available under WEB-INF/src/com/opensource/techblog/myservice/service/impl). Open this class and you will observe that by default there is no method defined.
Add following method in this (StudentLocalServiceImpl) class.
/**
*
* @param standard
* @return List<Student>
* @throws SystemException
*/
public List<Student> getStudentForStandard(int standard) throws SystemException{
return this.studentPersistence.findByStandard(standard);
}
Explanation:-
- We first declare method (getStudentForStandard) which takes standard as input and return the list of the students who are for specific standard.
- The name of the method can be taken any thing that you feel relevant since its our custom method. The same signature method will be created in StudentLocalServiceUtil class on next service build. The method inside the StudentLocalServiceUtil will call the corresponding method of StudentLocalServiceImpl class.
- Next we are calling this.studentPersistence.findByStandard method.
- This is because StudentLocalServiceImpl method extends StudentLocalServiceBaseImpl class and this (StudentLocalSeriveBaseImpl) class having reference of persistence (StudentPersistence) class.
- After the first service run the finder method is created in persistence (StudentPersistence) class which is accessible now in StudentLocalServiceImpl class.
- So we are simply calling finder method from persistence class and pass the standard which gives the list of student for that particular standard which finally we return of this method (getStudentForStandard).
- Next, just run the service builder once again and refresh the project structure. This time you will observe that the corresponding method (with same signature of what we defined in StudentLocalServiceImpl class) is created for StudentLocalServiceUtil class as per below screenshot.

Open StudentLocalServiceUtil class and check the method getStudentForStandard(int standard). The following are the facts about it.
- It has same method signature that we defined in StudentLocalServiceImpl class.
- It will internally call the corresponding method of service class.
- If you do any change in method signature defined in StudentLocalServiceImpl, it will create new method in StudentLocalSericeUtil class. The old method will not be vanished.
In short If we want any custom method (either finder or other), we need to add them into LocalServiceImpl and re-run service builder. After this, it will generate the method with same signature in LocalServiceUtil class.
And that is all done. Try to create more finder method for other columns and check how the code is generated.
Feel free to give suggestion / ask questions.