Liferay's Architecture: The services layer

Here I am again for a second entry on the series of Liferay Architecture. This time I'm going to talk a bit more about the services layer of Liferay. As can be seen in the architecture diagram with which I started this series, the services layer is at the core of Liferay Portal:

The Services layer contains the great majority of the business logic for the portal platform and all of the portlets included out of the box. The services are organized in two sets:

  • Portal services (com.liferay.portal.service): contains the services for the portal level entities. A simple trick to identify them is to look at the "Portal" section of the Control Panel menu.
  • Portlet services (com.liferay.portlet.*.service): contains the services used by the different portlets in Liferay. There are also some packages that are not really associated to one portlet (or to more that one), so the word portlet here is being abused a little bit. What matters is that all the services that are no part of the core portal platform are properly organized and componentized.

One very specific aspect of the services layer is that it is divided in two sub-layers:

  1. Local Services (<Entity>LocalService.java): this are the ones that that contain the business logic and communicate with the persistance layer.
  2. Remote Services (<Entity>Service.java): the main goal is to perform security checks before invoking the equivalent method in the local service. In some cases the remote services are also responsible for converting the Java objects returned by the local services layer to other formats. For example, the RSS generation for portlets that support it is done in remote services.

I'm going to finish the entry with some further facts and patterns of Liferay's services layer. The first are more well known but some aren't:

  1. Each persisted entity has an associated service. For example, the User entity has UserService, DLFileEntry (the entity used to store documents of Documents & Media) has the DLFileEntryService.
  2. The services methods are executed in a transaction. That means that if your database supports it (and most do) if there is an error in the middle of the execution of a service method (or in any other method invoked by it), all the previous operations will be undone (rolled back) automatically for you. Liferay implements this under the hood using Spring's transations mechanisms.
  3. The persistance layer is always accessed from local services. You should never access it directly unless you really know what you are doing and you are able to handle transactions manually from the invoking code.
  4. The local services are very strict with the return types of its methods. The return type should be one of the following:
    1. void
    2. <Entity>
    3. List<Entity>
    4. primitive type (this is not used often)

That's it for this second entry. I'm looking forward for your feedback. I'd love to know what topics are more interesting to you so that I can keep them into account for next entries.

Update Nov 29th: Added primitive type as a 4th return type. Thanks David for the note about it.

Write a blog post too!

Write a deep dive into how you use Liferay projects in your technology stack. Or let people know useful tips and tricks for a particular functionality. The Liferay community needs you!

Login or Create an account