Create Finder method for Service builder in liferay

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 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 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.
Create Finder method for Service builder in liferay -StudentLocalServiceUtil

If you observe, this class contains basic CRUD methods. Many business scenarios, we need to get data based on some condition. For more information about service layer, you can refer this link.

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).

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.

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.



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.

Create Finder method for Service builder in liferay -added finder method

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.

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.

Share This Post

12 Comments - Write a Comment

  1. 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.

    Reply
    1. 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

      Reply
  2. 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

    Reply
  3. 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.

    Reply
  4. 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

    Reply
  5. 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..

    Reply
  6. 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.

    Reply
    1. 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

      Reply

Post Comment

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