oo

Business Logic with Service Builder

Once you’ve generated model, persistence, and service code with Service Builder, you can begin adding business logic. Entities generated by Service Builder contain a model implementation and local service implementation class. Your application’s business logic can be implemented in these classes. The generated service later contains default methods that call CRUD operations from the persistence layer. Once you have business logic, you run Service Builder again to propagate your application’s interfaces, which makes your new logic available for invocation.

See the Example Project

Start a new Liferay DXP instance by running

docker run -it -m 8g -p 8080:8080 liferay/dxp:2024.q1.1

Sign in to Liferay at http://localhost:8080 using the email address test@liferay.com and the password test. When prompted, change the password to learn.

Then, follow these steps:

  1. Download and unzip Business Logic with Service Builder.

    curl https://resources.learn.liferay.com/dxp/latest/en/building-applications/data-frameworks/service-builder/liferay-e4g5.zip -O
    
    unzip liferay-e4g5.zip
    
  2. From the module root, build and deploy.

    ./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
    
    Note

    This command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.

  3. Confirm the deployment in the Liferay Docker container console.

    STARTED com.acme.e4g5.api_1.0.0 [1034]
    STARTED com.acme.e4g5.service_1.0.0 [1035]
    STARTED com.acme.e4g5.web_1.0.0 [1036]
    
  4. Verify that the example module is working. Open your browser to https://localhost:8080.

  5. Add the E4G5 Portlet to a page. You can find the example portlet under Sample Widgets.

    Add the E4G5 Portlet to a page.

  6. Add an entry by entering a name and description (e.g. e4g5_name1 and e4g5_description1). Click Add, and the new entry appears under E4G5 Entries. Take note of the e4g5EntryId number.

  7. Next, update this entry but entering the e4g5EntryId from the previous step and a new name and description. (e.g. 41804, e4g5_name2, e4g5_description2). Click Update, and the entry is now updated.

  8. Finally, delete the entry by entering the e4g5EntryId. Click Delete, and the entry is now deleted.

Update the Service Layer

Extend the local service by adding methods that can add, update, and delete E4G5Entry entries.

Implement the Add Method

  1. Declare an add* method with parameters for creating an entity.
public E4G5Entry addE4G5Entry(String description, String name)
	throws PortalException {

	E4G5Entry e4g5Entry = e4g5EntryPersistence.create(
		counterLocalService.increment());

	e4g5Entry.setDescription(description);
	e4g5Entry.setName(name);

	return e4g5EntryPersistence.update(e4g5Entry);
}
  1. The *Persistence class associated with your entity has a create() method that constructs an entity instance with the given ID. Every *BaseLocalServiceImpl has a counterLocalService object for the entity. Invoke the counter service’s increment() method to generate a primary key for your entity instance.

  2. Use the entity’s setter methods to populate your entity’s attributes. The sample sets two attributes: name and description.

  3. Invoke the *Persistence class’s update() method, passing in the entity object.

Implement the Update Method

  1. Declare an update* method with parameters for updating an entity. The sample receives name and description attributes, along with e4g5EntryId.
public E4G5Entry updateE4G5Entry(
		long e4g5EntryId, String description, String name)
	throws PortalException {

	E4G5Entry e4g5Entry = e4g5EntryPersistence.findByPrimaryKey(
		e4g5EntryId);

	e4g5Entry.setDescription(description);
	e4g5Entry.setName(name);

	return e4g5EntryPersistence.update(e4g5Entry);
}
  1. Use the *Persistence class’s findByPrimaryKey() method to retrieve the entity instance by entry ID.

  2. Use the entity’s setter methods to populate your entity’s attributes.

  3. Invoke the *Persistence class’s update() method, passing in the entity object.

Implement the Delete Method

  1. Declare a delete* method that receives the entity’s entry ID.
public E4G5Entry deleteE4G5Entry(long e4g5EntryId) throws PortalException {
	E4G5Entry e4g5Entry = e4g5EntryPersistence.findByPrimaryKey(
		e4g5EntryId);

	e4g5EntryPersistence.remove(e4g5Entry);

	return e4g5Entry;
}
  1. Invoke the *Persistence class’s delete() method, passing in the entity object.

After implementing your add*, update*, and delete* methods, run Service Builder to propagate your new service methods to the *LocalService interface.

Integrate the Backend

Now implement the service methods you created into your web module with portlet actions.

Portlet Actions

You can use an MVC Portlet for your web module. The sample project’s Portlet has entry actions for add, update, and delete.

public void addE4G5Entry(
		ActionRequest actionRequest, ActionResponse actionResponse)
	throws PortalException {

	_e4g5EntryLocalService.addE4G5Entry(
		ParamUtil.getString(actionRequest, "description"),
		ParamUtil.getString(actionRequest, "name"));
}

public void deleteE4G5Entry(
		ActionRequest actionRequest, ActionResponse actionResponse)
	throws PortalException {

	_e4g5EntryLocalService.deleteE4G5Entry(
		ParamUtil.getLong(actionRequest, "e4g5EntryId"));
}

public void updateE4G5Entry(
		ActionRequest actionRequest, ActionResponse actionResponse)
	throws PortalException {

	_e4g5EntryLocalService.updateE4G5Entry(
		ParamUtil.getLong(actionRequest, "e4g5EntryId"),
		ParamUtil.getString(actionRequest, "description"),
		ParamUtil.getString(actionRequest, "name"));
}

Each method takes an ActionRequest and ActionResponse parameter. The ActionRequest receives information from the view layer and the ActionResponse can be used to pass information back to the view layer.

The addE4G5Entry() method receives a name and description and calls the service to add the entry. The updateE4G5Entry() method receives an entry ID, name, and description and calls the service to updated a specific entry. The deleteE4G5Entry() method receives an entry ID and calls the service to delete the entry.

Map the Actions in the JSP

Now map the action methods you created into your JSP.

<h3>Add a E4G5 Entry</h3>

<portlet:actionURL name="addE4G5Entry" var="addE4G5EntryURL" />

<aui:form action="<%= addE4G5EntryURL %>">
	<aui:input name="name" type="text" />
	<aui:input name="description" type="text" />

	<aui:button type="submit" value="add" />
</aui:form>

<hr />

<h3>Update a E4G5 Entry</h3>

<portlet:actionURL name="updateE4G5Entry" var="updateE4G5EntryURL" />

<aui:form action="<%= updateE4G5EntryURL %>">
	<aui:input name="e4g5EntryId" type="text" />
	<aui:input name="name" type="text" />
	<aui:input name="description" type="text" />

	<aui:button type="submit" value="update" />
</aui:form>

<hr />

<h3>Delete a E4G5 Entry</h2>
<portlet:actionURL name="deleteE4G5Entry" var="deleteE4G5EntryURL" />

<aui:form action="<%= deleteE4G5EntryURL %>">
	<aui:input name="e4g5EntryId" type="text" />

	<aui:button type="submit" value="delete" />
</aui:form>

The JSP binds actions to UI components using the tag library’s portlet:actionURL tag. Note that the portlet:actionURL’s name attribute must match each of the action methods created in the portlet. The var attribute assigns the portlet action URL to an arbitrary variable. The <aui:form> renders text fields for user input. On submitting the form, its values are passed along with the ActionRequest to the portlet method.