Introduction:
Liferay Service Builder is a tool to generate service layer to liferay portlets. It will create all necessary CRUD operation related classes and respective methods.
We will use Utilclasses’ methods to perform CRUD operations in portlet development.
The following is the tutorial about Service Builder.
Liferay Service Builder have provided some Util classes so that we can use those classes and its methods
The following are the important Service Util classes we will use
XXXLocalServiceUtil XXXServiceUtil XXXUtil XXX is your entity name in service.xml file example say Student is your entity name. StudentLocalServiceUtil StudentServiceUtil StidentUtil |
XXXLocalServiceUtil (StudentLocalServiceUtil)
All important CRUD operation related methods will be available. We can use this class anywhere in our code implementation i.e. when we want to interacts with database. The operations are like add, update, delete, and read.
When we call methods from this classes there is no security check applied or there no permission checking applicable.
XXXServiceUtil(StudentServiceUtil)
This class is similar to Local Service Util and available all CRUD operation methods but here it will use some security checks and permission checking are applied when we call the methods. If the user does not have required permissions then it will throw Principle Exception
Scenario:
Use some XXXServiceUtil method in JSP page and access the page as Guest User then you can get Principle Exception
Same page you can access after login as Admin then no exception will be thrown.
Generally this class will use to perform admin related task if we call this method in Guest user mode then it will throw the exception
Principle Exception |
XXXUtil (StudenUtil)
This class especially for finder methods and all finder methods will be available.
Generally in liferay we can create finder methods with help of service.xml file
We will use following tag in service.xml file so that respective finder method will be create in XXXUtil class.
<entity name="Student" local-service="true" remote-service="true"> <!-- PK fields --> <column name="studentId" type="long" primary="true" /> <column name="firstName" type="String" /> <column name="lastName" type="String" /> <column name="studentAge" type="int" /> <column name="studentGender" type="int" /> <column name="studentAddress" type="String" /> <!-- Finder methods --> <finder name="Gender" return-type="Collection"> <finder-column name="studentGender"/> </finder> </entity> |
Note:
When we declared Collection return type is a java.uti.List<ObjectType>
Method Syntax in Java Class
public returnType findByXXX (finderColumns){ } XXX is the name we specified in finder tag as name attribute. |
Example:
public List findByGender(int stdentGender){ } |
When we use finder tag we need to specify the finder columns inside the finder tag.
We need specify the finder method return type i.e. Collection or Object type
If the methods want return more than one value or records then need to specify as Collection
If the method returns only one object or one record then we can specify as Object i.e. respective object we specified as entity.
Example:
By Gender we can get more records or values so its return type should be Collection
<finder name="byGender" return-type="Collection"> <finder-column name="studentGender"/> </finder> |
For above Configuration respective SQL query as follows
Select * from LS_Student Where studentgender=? |
For Above Finder Configuration respective Java Method in XXXUtil(StudentUtil) as follows
public class StudentUtil { public static java.util.List<com.meera.dbservice.model.Student> findByGender( int studentGender) throws com.liferay.portal.kernel.exception.SystemException { return getPersistence().findBybyGender(studentGender); } } |
If the finder returns only one value or single object, Assume by first name we have only one record is expected.
<finder name="fistName" return-type="Student"> <finder-column name="firstName"/> </finder> |
For above Configuration respective SQL query as follows
Select * from LS_Student Where firstName=? |
Note:
In the above configuration we can expect only one value that is respective entity model object that is why return type we specified as Object i.e. Student
Finder on Multiple Columns
If we want find the records based on multiple columns
<finder name="Gender_Age" return-type="Collection"> <finder-column name="studentGender"/> <finder-column name="studentAge"/> </finder> |
For above Configuration respective SQL query as follows
Select * from LS_Student Where studentGender=? AND StudentAge=? |
For Above Finder Configuration respective Java Method in XXXUtil(StudentUtil) as follows
public class StudentUtil{ public static java.util.List<com.meera.dbservice.model.Student> findByGender_Age(int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return getPersistence().findByGender_Age(studentGender, studentAge); } } |
Note:
When we use finder on multiple columns it will apply the AND operator in SQL query.
When we call XXXUtil methods in JSP or Portlet action class then we will get Exception
Example:
java.util.List<com.meera.dbservice.model.Student> studentsList= StudentUtil. findByGender_Age(1,20) |
When we use above code in anywhere then we will get Hibernate Exception
org.hibernate.HibernateException: No Hibernate Session bound to thread |
Solution:
We need to use these methods in XXXLocalServiceImpl then we will call these methods using XXXLocalServiceUtil
Note:
We can call any method which is in XXXLocalServiceUtil class in JSP, Portlet Action class or other places.
Custom Method Implementation:
When we thing about above scenarios we are not able to call finder methods and some the methods in XXXServiceUtil methods. This is where we need to implement custom methods.
Steps:
- Implement Custom method in XXXLocalServiceImpl class
- Run service Builder
- Call Implemented method using XXXLocalServiceUtil
Implement Custom method in XXXLocalServiceImpl class
Whenever we get the requirement to write our custom methods then we need to implement in respective entity local service implementation class
XXXLocalServiceImpl StudentLocalServiceImpl |
Assume scenario we are not able to call finder methods form StudentUtil so we will implement custom method in StudentLocalServiceImpl.java
public java.util.List<com.meera.dbservice.model.Student> findByGenderAndAge(int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return StudentUtil.findByGender_Age(studentGender, studentAge); } |
Here we have implemented our custom method in XXXLocalServiceImpl
(StudentLocalServiceImpl.java) and inside the custom method we have used XXXUtil methods.
Like this we can use XXXServiceUtil and XXXUtil methods in XXXLolcalServiceImpl custom method implementation.
Note:
XXXLocalServiceImpl class available in basepackage.service.implpath
Run service Builder
Once we implement the custom method in XXXServiceImpl then we need to run service builder using ant build-service target from ant view in eclipse.
After run service builder respective method signature will be created in XXXLocalServiceUtil class.
Note:
For every change in XXXLocalServiceImpl class we need to re run the service builder.
Call Implemented method using XXXLocalServiceUtil
Now the method is available in XXXLocalSeriviceUtil class so that we can call method anywhere.
Example:
Method in StudentUtil.java
public class StudentUtil{ public static java.util.List<com.meera.dbservice.model.Student> findByGender_Age( int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return getPersistence().findByGender_Age(studentGender, studentAge); } } |
Note:
We can’t call above method directly
Implement the Custom method in StudentLocalServiceImpl.java
public class StudentLocalServiceImpl extends StudentLocalServiceBaseImpl { public java.util.List<com.meera.dbservice.model.Student> findByGenderAndAge( int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return StudentUtil.findByGender_Age(studentGender, studentAge); } } |
Respective method Signature in StudentLocalServieUtil.java
public static java.util.List<com.meera.dbservice.model.Student> findByGenderAndAge( int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return getService().findByGenderAndAge(studentGender, studentAge); } |
Note:
Method signature available after run the service builder
Using custom method in JSP page or Portlet Action Class
java.util.List<Student> studentsList= StudentLocalServiceUtil. findByGenderAndAge(1,20) |
Important Points
- Whenever we need to implement custom method then we will use XXXLocalServiceimpl class
- We can’t call XXXUtil and XXXServiceUtil methods directly so we need to use XXXLocalServiceImpl class to implement custom methods.
- All finder methods will be created in XXXUtil
- When we call XXXServiceUtil methods as Guest then we will get Principle Exception.
- When we call XXXUtil methods directly then we will get Hibernate Exception says No Hibernate Session bound to thread
- For every custom method implementation in XXXLocalServiceImpl then the respective method signature will be created in XXXLocalServiceUtil and this is happened after run the service builder.
- We always use XXXLocalServiceUtil to interact with database and some time we will use XXXServiceUtil too.
Note:
We can use Dynamic Query API to meet all finder requirements. We can do same as finder methods in Liferay Dynamic Query API.
Complete code for Example
Cutome Method Implemetation(StudentLocalServiceImpl.java)
public class StudentLocalServiceImpl extends StudentLocalServiceBaseImpl { public java.util.List<com.meera.dbservice.model.Student> findByGenderAndAge( int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return StudentUtil.findByGender_Age(studentGender, studentAge); } } |
Cstome method Signature in
public class StudentLocalServiceUtil { public static java.util.List<com.meera.dbservice.model.Student> findByGenderAndAge( int studentGender, int studentAge) throws com.liferay.portal.kernel.exception.SystemException { return getService().findByGenderAndAge(studentGender, studentAge); } } |
Calling method in JSP page(/html/jsps/get_students_by_gender_age.jsp)
<%@page import="com.liferay.portal.kernel.util.ListUtil"%> <%@page import="com.meera.dbservice.model.Student"%> <%@page import="java.util.List"%> <%@page import="com.meera.dbservice.service.StudentLocalServiceUtil"%> <%@ include file="init.jsp"%> <a href="<portlet:renderURL />">«Home</a> <div class="separator"></div> <liferay-portlet:renderURL varImpl="getStudentsByAgeAndGender"> <portlet:param name="mvcPath" value="/html/jsps/get_students_by_gender_age.jsp" /> </liferay-portlet:renderURL> <liferay-portlet:renderURL varImpl="iteratorURL"> <portlet:param name="studentAge" value="<%= String.valueOf(studentAge) %>" /> <portlet:param name="studentGender" value="<%= String.valueOf(studentGender) %>" /> <portlet:param name="mvcPath" value="/html/jsps/get_students_by_gender_age.jsp" /> </liferay-portlet:renderURL> <h2>Search Students</h2><br/> <form action="<%=getStudentsByAgeAndGender%>" name="studentForm" method="POST"> <b>Age</b><br/> <input type="text" name="<portlet:namespace/>studentAge" id="<portlet:namespace/>studentAge" value="<%=String.valueOf(studentAge)%>"/><br/> <b>Gender</b><br/> <input type="radio" name="<portlet:namespace/>studentGender" value="1" <%=studentGender==1?"checked":""%>>Male<br> <input type="radio" name="<portlet:namespace/>studentGender" value="0" <%=studentGender==0?"checked":""%>>Female<br/> <input type="submit" name="addStudent" id="addStudent" value="Search"/> </form> <liferay-ui:search-container displayTerms="<%= new DisplayTerms(renderRequest) %>" emptyResultsMessage="there-are-no-students" headerNames="firstName,studentAge,studentGender" iteratorURL="<%= iteratorURL %>" delta="5" > <liferay-ui:search-container-results> <% List<Student> studentList= StudentLocalServiceUtil.findByGenderAndAge(studentGender, studentAge); searchContainer.setTotal(studentList.size()); studentList = ListUtil.subList(studentList,searchContainer.getStart(), searchContainer.getEnd()); searchContainer.setResults(studentList); %> </liferay-ui:search-container-results> <liferay-ui:search-container-row className="Student" keyProperty="studentId" modelVar="currentStudent"> <liferay-portlet:renderURL varImpl="rowURL"> <portlet:param name="backURL" value="<%= currentURL %>" /> <portlet:param name="mvcPath" value="/html/jsps/display_student.jsp" /> <portlet:param name="studentId" value="<%= String.valueOf(currentStudent.getStudentId()) %>" /> </liferay-portlet:renderURL> <liferay-ui:search-container-column-text href="<%= rowURL %>" name="firstName" property="firstName" /> <liferay-ui:search-container-column-text href="<%= rowURL %>" name="studentAge" property="studentAge" /> <liferay-ui:search-container-column-text href="<%= rowURL %>" name="studentGender" value='<%=currentStudent.getStudentGender()==1?"Male":"Female"%>' /> </liferay-ui:search-container-row> <liferay-ui:search-iterator searchContainer="<%=searchContainer %>" /> </liferay-ui:search-container> |
Download Liferay Custom Service Methods Portlet
Environment:
Liferay IDE 2.x+Eclipse (Kepler) +Liferay Plugins SDK 6.2+Tomcat 7.x Liferay Portal Bundle
Deployment and its Working.
Download portlet you can source or war file to deploy into liferay portal as your convenient.
Once portlet successfully deployed drag the portlet in any desired page. Portlet is available in sample category.
In the portlet page you can click on Get Student By Gender And Age link then you can see the search container with search inputs.
Portlet Screens:
Default Page
Search the students by Age and Gender
Reference Links
Author
0 comments:
Post a Comment