Understanding ServiceContext

The ServiceContext class is a parameter class used for passing contextual information for a service. Using a parameter class lets you consolidate many different methods with different sets of optional parameters into a single, easier-to-use method. The class also aggregates information necessary for features used throughout Liferay’s core portlets, such as permissions, tagging, categorization, and more.

In this section, you’ll examine the Service Context fields, learn how to create and populate a Service Context, and learn to access Service Context data. First, let’s look at the fields of the ServiceContext class.

Although all the ServiceContext class fields are optional, services that store any kind of scopeable data need to at least specify the scope group ID. Here’s a simple example of creating a ServiceContext instance and passing it as a parameter to a Liferay service API using Java:

If you invoke the service from a servlet, a Struts action, or any other front-end end class which has access to the PortletRequest, use one of the ServiceContextFactory.getInstance(...) methods. These methods create a ServiceContext object from the request and automatically populate its fields with all the values specified in the request. The above example looks different if you invoke the service from a servlet:

You can see an example of populating a ServiceContext with information from a request object in the code of the ServiceContextFactory.getInstance(...) methods. The methods demonstrate how to set parameters like scope group ID, company ID, language ID, and more. They also demonstrate how to access and populate more complex context parameters like tags, categories, asset links, headers, and the attributes parameter. By calling ServiceContextFactory.getInstance(String className, PortletRequest portletRequest), you can assure that your Expando bridge attributes are set on the ServiceContext. Expandos are the back-end implementation of custom fields for entities in Liferay.

Liferay’s API can be invoked in languages other than Java, such as Beanshell, Groovy, JavaScript, Python, and Ruby. Some methods of Liferay’s API require or allow a ServiceContext parameter. If you’re invoking such a method via Liferay’s JSON web services, you might want to create and populate a ServiceContext object in JavaScript. Creating a ServiceContext object in JavaScript is no different from creating any other object in JavaScript.

Before examining a JSON web service invocation that uses a ServiceContext object, it helps to see a simple JSON web service example in JavaScript:

If you run this code, the test@liferay.com user (JSON object) is logged to the JavaScript console.

The Liferay.Service(...) function takes three arguments:

A string representing the service being invoked

A parameters object

A callback function

The callback function takes the result of the service invocation as an argument.

The Liferay JSON web services page (its URL is localhost:8080/api/jsonws if you’re running Liferay locally on port 8080) generates example code for invoking web services. To see the generated code for a particular service, click on the name of the service, enter the required parameters, and click Invoke. The JSON result of your service invocation appears. There are multiple ways to invoke Liferay’s JSON web services: click on JavaScript Example to see how to invoke the web service via JavaScript, click on curl Example to see how to invoke the web service via curl, or click on URL example to see how to invoke the web service via a URL.

Figure 1: When you invoke a service from Liferay’s JSON web services page, you can view the result of your service invocation as well as example code for invoking the service via JavaScript, curl, or URL.

To learn more about Liferay’s JSON web services, please see the JSON Web Services tutorial.

For an example of how to create and populate a ServiceContext object in JavaScript and how to pass it as a parameter to a Liferay JSON web service invocation, please see the Sample JSONWS Portlet. All the Sample JSONWS portlet’s functionality is provided in its view.jsp file. The portlet displays a button that, when clicked, creates a new user by invoking Liferay’s JSON web services. Let’s examine the JSON web service invocation:

The Add User service requires a lot of parameters. The serviceContext parameter is optional. You can use it with the Add User service to specify tags to be applied to the user that’s being created. See the Javadoc of the service method for details: https://docs.liferay.com/portal/6.2/javadocs/com/liferay/portal/service/UserServiceUtil.html. In the example above, the serviceContext parameter specifies that the tag test should be applied to the user that’s being created.

To test the service invocation with the serviceContext parameter, deploy the Sample JSONWS Portlet, add it to a page, and click on the Create User button. Then navigate to the Control Panel, click on Users and Organizations, edit the newly created user, click on Categorization, and confirm that the specified tag has been applied.

Figure 2: To test invoking a Liferay JSON web service, deploy the Sample JSONWS Portlet, add it to a page, click on Create User, and confirm that the tag test has been applied to the newly created user.

Important: To invoke Liferay web services via JavaScript, your JavaScript context must include AlloyUI. In the Sample JSONWS Portlet, the JavaScript code in view.jsp was wrapped in the <aui:script use="node, event"> and </aui:script> tags. The node and event modules were required to implement the button. Only the base AUI is required to invoke a Liferay JSON web service. The <aui:script> tag was made available to the view.jsp page by this taglib import:

<%@ taglib uri="http://alloy.liferay.com/tld/aui" prefix="aui" %>

If you’re not working in a JSP, you won’t have access to taglibs. In this case, you can create an Alloy context manually. For example,

In this section, you’ll find code snippets from BlogsEntryLocalServiceImpl.addEntry(..., ServiceContext). This code demonstrates how to access information from a ServiceContext and provides an example of how the context information can be used.

As mentioned above, services for scopeable entities need to get a scope group ID from the ServiceContext object. This is true for the Blogs entry service because the scope group ID provides the scope of the Blogs entry (the entity being persisted). For the Blogs entry, the scope group ID is used in the following way:

The snippet above also demonstrates the trackbacks attribute, a standard attribute for the blogs entry service. There may be cases where you need to pass in custom attributes to your blogs entry service. Use Expando attributes to carry custom attributes along in your ServiceContext. Expando attributes are set on the added blogs entry like this:

entry.setExpandoBridgeAttributes(serviceContext);

You can see that the ServiceContext can be used to transfer lots of useful information for your services. Understanding how ServiceContext is used in Liferay helps you determine when and how to use ServiceContext in your own Liferay application development.