While working on the
Service Builder in Liferay it’s good to have a clear picture of what all
classes are generated by the Service Builder, how these classes are related to
each other, where can I put my custom code, how can I invoke persistence layer
methods.
In this post I intend
to answer some of the questions in a very simplistic view – the very basics in
plain English.
I’ll
take an example. I have created a very basic service.xml.
<?xml
version="1.0" encoding="UTF-8"?>
<!DOCTYPE
service-builder PUBLIC "-//Liferay//DTD
Service Builder 6.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd">
<service-builder
package-path="com.ab">
<author>gaurshar</author>
<namespace>B</namespace>
<entity name="Student"
local-service="true" remote-service="false">
<column
name="studentId" type="long"
primary="true" id-type="class"
id-param="com.liferay.counter.service.persistence.IDGenerator"></column>
<column
name="studentName" type="String"></column>
<column
name="classId" type="long"/>
<finder return-type="Collection"
name="StudentName">
<finder-column
name="studentName"></finder-column>
</finder>
</entity>
<entity name="Classroom"
local-service="true" remote-service="false">
<column
name="classId" type="long"
primary="true" id-type="class"
id-param="com.liferay.counter.service.persistence.IDGenerator"></column>
<column
name="className" type="String"></column>
<column
name="student" type="Collection"
entity="Student" mapping-key="studentId"></column>
<finder
return-type="Collection" name="ClassName">
<finder-column
name="className"></finder-column>
</finder>
</entity>
</service-builder>
Few
points to highlight –
1)
There are two entities – Student and Classroom
2)
There is a one-to-many relation defined between Classroom and Student
3)
There are few finder methods defined
When
we build the service through Service Builder, the framework generates a set of
classes as depicted in the diagram below.
Few
things to note here –
1)
All the column name mappings, getters and setters are defined in ClassroomLocalServiceBaseImpl.
2)
ClassroomLocalServiceImpl does not contain any method by default and
should contain any custom methods (more on it sortly…)
3)
Custom service classes, jsps, controllers should use ClassroomLocalServiceUtil
class for accessing any service, persistence related methods.
This class should be the single point of contact for our code .
4)
There is a parallel structure for Persistence layer generated by Service
Builder. There is an abstraction in terms of ClassroomUtil that wraps all the
methods of the persistence layer and provides a single point of contact for
Service Layer classes.
5)
We should not directly invoke methods of any of the persistence layer classes
including the ClassroomUtil class.
If
we need to invoke a method of ClassroomUtil, we must do the following –
- Taking the above example, we have a method in ClassroomUtil – getStudents(long pk) that returns all the students in a class. We should create a method ‘getStudents’ in ClassroomLocalServiceImpl (class where all the custom methods are written). This method calls ClassroomUtil.getStudents() method
- Regenerate the service classes using Service Builder. This regenerates the service layer classes and creates a method getStudents() in ClassroomLocalServiceUtil. This can now be invoked from custom code.
Remember the bottom line is ‘ClassroomLocalServiceUtil’ should be the single
point of contact for custom code.
Invoking
persistence layer methods from Service layer sets up transaction context and
hibernate sessions.
Thanks
Srikanth
There is a similar framework for Determination part produced by Support Designer. There is an abstraction with regards to ClassroomUtil that parcels all the techniques of the persistence part and provides a anchorman of contact for Support Layer sessions.
ReplyDeleteSpybubble