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 Util
classes’ 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.impl
path
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
No comments:
Post a Comment