Finder method in Liferay provides facility to add customization in service layer. Finder method allows to define custom methods which is used to fetch data from DB for different table column.
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 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.
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).
1 2 3 4 5 6 7 8 | <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> |
Add finder method
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.
I would recommend looking at index page ‘A Complete Liferay Guide‘ to browse all topics about liferay.
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.
1 2 3 4 5 6 7 8 9 10 11 12 | <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).
1 2 3 4 5 6 7 8 9 | /** * * @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.
- 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.
Summing Up
- Finder methods are way to define customization in service layer provided by Liferay
- It allows to add additional methods to fetch data from data base
- We can get data from one or more db column with specific value.
hey hi nilang will please tell about query mapping or table mappin like many to many in liferay service builder?
how to write join query between tables?
Thank you for great and easy article.
Hello Prasanna,
Sorry for late respond. Ideally when you need to fetch data from multiple tables, I would prefer to write custom query. In case if there are multiple joins are there, you can shift it to Stored procedure for faster recovery of data. I am planning to write separate blog on how to write custom sql query with service builer but you can find the help from google for time being.
Regards
Nilang
Hi Dhaval,
Thank you for your sharing.
It’s very helpful for me. However, I met an issue when deploy service builder to portal.
After I inserted method to StudentServiceImpl (remote API), I could see my api in http://localhost:8080/api/jsonws.
Do you think I should build service.xml again?
Thank you for your help!
Tung Nguyen
Hi Nilang,
I’ve done the steps as your post, however I encountered some error “org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) ….”,
can you help me this problem?
Thanks a Lot.
Hi Sinh,
Can you please provide steps you are following. Also send me your portlet on my email address [email protected]
Hi nilang,
Can you please reply for the above comment.
Thanks in advance
Hi nilang, I have created a EXT in which i have written a custom interceptor extending methodinterceptor. so that this interceptor should be called for my service calls in all portlets. and this is being called for customservices provided by liferay like userlocalservice..but it is not getting called for custom services. please help me out.
Thanks in advance
excellent nilang excellent..awesome…i cant express my joy. am newbie to liferay struggling fr hours in office to understand all these concepts..please post articles on ext plugins also. it will help us a lot..
Hi Welcome to tech blog and thanks for appreciation.
Regards
Nilang
hello follow the whole process but I have to edit my view.jsp to add a button or text field?
HelpMe
Superb,Excellant you are doing a gr8 job,
Such a detailed post ,its like spoonfeeding to newbies in Liferay ,
Really please keep on posting it is really helpful to us .
Thanks a Lot.
A post on IPC concept,Hooks,ExtPlugins and little theory on them would be really appreciated …waiting for that post too, hope you will write on this topics too.
Hi Dhaval,
Thanks for appreciation !! and welcome to Tech blog. Since beginning I keep all article such that any person can easily understand. As you suggest, I will sure write the blogs for the topics you suggest.
Regards
Nilang I Patel