5. Generating Your Service Layer
5.2. Defining Your Object-Relational Map
In order to demonstrate how to use Service Builder, let's continue using the event-listing-portlet project that we created in Developing Apps with Liferay IDE. It's an example portlet project that Nose-ster, a fictitious organization, can use to schedule social events. We're using the event-listing-portlet project to manage and list these events. We need to add some entities, or model types, to represent Nose-ster's events and the locations where they hold their events. We'll define two entities: events and locations. The event entity represents a social event that can be
scheduled for Nose-ster, while the location entity represents a location at which a social event can take place. Since an event must have a location, the event entity will reference a location entity as one of its attributes.
Liferay 6.2 Developer Guide Page 196 If you'd like to examine the finished example project, it's a part of our Dev Guide SDK which you can browse at https://github.com/liferay/liferay-docs/tree/master/devGuide/code/devGuide-sdk. The project is in the SDK's portlets/event-listing-portlet folder.
Note: If you're looking for a fully-functional portlet application that can manage events, please use Liferay's Calendar portlet instead. The example described in this section is only intended to demonstrate how to use Service Builder. The Calendar portlet provides many more features than the simple example application described here. For information about the Calendar portlet, please refer to the chapter on Liferay's collaboration suite in Using Liferay Portal 6.2.
As with any portlet project, the event-listing-portlet project's Java sources lie in its docroot/WEB-INF/src folder. Notice that Liferay IDE's portlet wizard created the EventListingPortlet.java and LocationListingPortlet.java files in the com.nostester.portlet.eventlisting package. We'll add some business logic to these portlet classes after using Service Builder to create a service layer for our event and location entities.
The first step in using Service Builder is to define your model classes and their attributes in a service.xml file in your project's docroot/WEB-INF folder. In Service Builder terminology, your model classes (events and locations) are called entities. We've kept the requirements for our event and location entities fairly simple. Events should have the following
Liferay 6.2 Developer Guide Page 197 attributes:
Event Attributes
Attribute Attribute Type
Attribute Description
name String The name of the event description String A description of the event
date Date The date and time the event takes place
locationId long An event takes place at a location and we use a location Id to specify the location
Locations should have the following attributes:
Location Attributes
Attribute Attribute Type Attribute Description name String The name of the location description String A description of the location streetAddress String The street address of the location
city String The city of the location
stateOrProvince String The state or province of the location country String The country of the location
Service Builder defines a single file called service.xml for describing entities. Once you create the file, you can then define your entities. We'll walk you through the whole process for the entities we've defined above, using Liferay IDE, which makes it easy. It'll only take seven steps to do it:
1. Create the service.xml file in your project's docroot/WEB-INF folder, if one does not already exist there.
2. Define global information for the service.
3. Define service entities.
4. Define the columns (attributes) for each service entity.
5. Define relationships between entities.
6. Define a default order for the entity instances to be retrieved from the database.
7. Define finder methods that retrieve objects from the database based on specified parameters.
Let's start creating our service by using Liferay IDE to create your service.xml file.
5.2.1. Creating the service.xml File
To define a service for your portlet project, you must create a service.xml file. The DTD (Document Type Declaration) file http://www.liferay.com/dtd/liferay-service-builder_6_2_0.dtd specifies the format and requirements of the XML to use. You can create your service.xml file manually, following the DTD, or you can use Liferay IDE. Liferay IDE helps you build the service.xml file piece-by-piece, taking the guesswork out of creating XML that adheres to
Liferay 6.2 Developer Guide Page 198 the DTD. For our tutorial, we'll use Liferay IDE to build the service.xml file.
If a default service.xml file already exists in your docroot/WEB-INF/src folder, check to see if it has an <entity /> element named "Foo". If it has the Foo entity, remove the entire
<entity name="Foo" ...> ... </entity> element. The project wizard creates the Foo entity as an example, but it's of no use to us in this exercise.
If you don't already have a service.xml file it's easy to create one using Liferay IDE. Simply select your event-listing-portlet project in the Package Explorer and then select File
→ New → Liferay Service Builder. Liferay IDE creates a service.xml file in your docroot/WEB-INF/src folder and displays the file in Overview mode.
Liferay IDE also provides a Diagram mode and a Source mode to give you different perspectives of the service information in your service.xml file. Diagram mode is helpful for creating and visualizing relationships between service entities. Source mode brings up the service.xml file's raw XML content in the editor. You can switch between these modes as you wish. Since Overview mode facilitates creating service elements, we'll use it while creating our service.
Let's start filling out the global information for our service.
5.2.2. Defining Global Service Information
A service's global information applies to all of its entities, so let's specify this information first.
Select the Service Builder node in the upper left corner of the Overview mode of your
service.xml file. The main section of the view now shows the Service Builder form in which we can enter our service's global information. The fields include the service's package path, author, and namespace options. Here are the values we'll use for our example service:
• Package path: com.nosester.portlet.eventlisting
• Auto namespace tables: no
• Author: [your name]
• Namespace: Event
The package path specifies the package in which the service and persistence classes are
generated. The package path we defined above ensures that the service classes are generated in the com.nosester.portlet.eventlisting package under the docroot/WEB-INF/service folder. The persistence classes are generated in a package of that name under the docroot/WEB-INF/src folder. The complete file paths for the service and persistence classes are docroot/WEB-INF/service/com/nosester/portlet/eventlisting and docroot/WEB-INF/src/com/nosester/portlet/eventlisting,
respectively. Please refer to next section, Generating the Services, for a description of the contents of these packages.
Service Builder uses the service namespace in naming the database tables it generates for the service. Enter Event as the namespace for your example service. Service Builder uses the
namespace in the following SQL scripts it generates in your docroot/WEB-INF/sql folder:
• indexes.sql
• sequences.sql
Liferay 6.2 Developer Guide Page 199
• tables.sql
Liferay Portal uses these scripts to create database tables for all the entities defined in the
service.xml file. Service Builder prepends the namespace to the database table names. Since our namespace value is Event, the names of the database tables created for our entities start with Event_ as their prefix. The namespace for each Service Builder project must be unique.
Separate plugins should use separate namespaces and should not use a namespace already used by Liferay (such as Users or Groups). Check the table names in Liferay's database if you're wondering which namespaces are already in use.
As the last piece of global information, enter your name as the service's author in your
service.xml file. Service Builder adds @author annotations with the specified name to all of the generated Java classes and interfaces. Save your service.xml file to preserve the information you added. Next, we'll add entities for your service's events and locations.
5.2.3. Defining Service Entities
Entities are the heart and soul of a service. Entities represent the map between the model objects in Java and the fields and tables in your database. Once your entities are defined, Service Builder handles the mapping automatically, giving you a facility for taking Java objects and persisting them. For this example, you'll create two entities--one for events and one for locations.
Here's a summary of the information we'll enter for the Event entity:
• Name: Event
• Local service: yes
• Remote service: yes
And here's what we'll enter for the Location entity:
• Name: Location
• Local service: yes
• Remote service: yes
To create these entities, select the Entities node under the Service Builder node in the outline on the left side of the service.xml editor in Overview mode. In the main part of the view, notice that the Entities table is empty. Create an entity by clicking on the Add Entity icon (a green plus sign) to the right of the table. Enter Event for your entity's name and select both the Local Service and the Remote Service options. Create a second entity named Location and select the Local Service and the Remote Service options for it too.