Dokumentáció
A Liferay az erőforrások és az ismeretek gazdag tárházát kínálja, hogy elősegítse technológiájának a közösség általi jobb használatát és alkalmazását.
Service Context
The ServiceContext class is a parameter class to be used in passing contextual information for a service. By using a parameter class, it is possible to consolidate many different methods with different sets of optional parameters into a single, easier to use method. The class also aggregates information necessary for transversal features such as permissioning, tagging, categorization, etc.
This section covers:
The Service Context fields
Creating and populating a Service Context
Accessing Service Context data
First, we’ll take a look at the fields of the ServiceContext class.
Service Context Fields
There are a good number of fields found in ServiceContext. The best descriptions of these fields are found in the Javadoc comments for of their corresponding getter methods found at http://docs.liferay.com/portal/6.1/javadocs-all/com/liferay/portal/service/ServiceContext.html. But what may also be helpful is the following categorical listing of the fields:
Actions:
_command_workflowAction
Attributes:
_attributes_expandoBridgeAttributes
Classification:
_assetCategoryIds_assetTagNames
IDs and Scope:
_companyId_portletPreferencesIds_plid_scopeGroupId_userId_uuid
Language:
_languageId
Miscellaneous:
_headers_signedIn
Permissions:
_addGroupPermissions_addGuestPermissions_deriveDefaultPermissions_groupPermissions_guestPermissions
Resources:
_assetEntryVisible_assetLinkEntryIds_createDate_indexingEnabled_modifiedDate
URLs, paths and addresses:
_currentURL_layoutFullURL_layoutURL_pathMain_portalURL_remoteAddr_remoteHost_userDisplayURL
In case you are wondering how the ServiceContext fields get populated, we’re going to look at that next.
Creating and Populating a Service Context
All of the fields of the ServiceContext class are optional, although your services that store any type of content will require you to specify at least the scope group ID. Here is a simple example of how to create a ServiceContext instance and pass it as a parameter to a service API using Java:
ServiceContext serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(myGroupId);
...
BlogsEntryServiceUtil.addEntry(...., serviceContext);
If you are invoking the service from a servlet, a Struts action or any other front-end class which has access to the PortletRequest, use one of the ServiceContextFactory.getInstance(...) methods. These methods create the ServiceContext object and fill it with all the necessary values automatically. If you are invoking the service from a servlet, the above example could be rewritten as follows:
ServiceContext serviceContext =
ServiceContextFactory.getInstance(BlogsEntry.class.getName(),
portletRequest);
BlogsEntryServiceUtil.addEntry(..., serviceContext);
To see an example of how to populate a ServiceContext with information from a request object, check out the code of the ServiceContextFactory.getInstance(...) methods. Not only do the methods demonstrate setting parameters such as scope group ID, company ID, language ID, etc., but they also demonstrate accessing and populating more complex context parameters such as tags, categories, asset links, headers, and the attributes parameter. Note, by calling ServiceContextFactory.getInstance(String className, PortletRequest portletRequest), you can assure your expando bridge attributes are also set on the ServiceContext.
You’re not limited to using only Java with ServiceContext; you can use ServiceContext from other languages like JavaScript. In fact, since our API can be invoked from JavaScript, it is often required to pass the ServiceContext from JavaScript to the server, and this can be done in a very simple way – by passing the ServiceContext as any other JavaScript object. There are plenty of examples of this in the JavaScript code of Liferay’s portlets. Here is an example from [liferay-portal]/portal-web/html/portlet/journal/js/main.js that demonstrates using ServiceContext in calling the updateStructure method of the JournalStructure service:
var instance = this;
var defaultLocale = instance.getDefaultLocale();
var serviceParameterTypes = [
'long',
'java.lang.String',
'java.lang.String',
'java.util.Map<java.util.Locale, java.lang.String>',
'java.util.Map<java.util.Locale, java.lang.String>',
'java.lang.String',
'com.liferay.portal.service.ServiceContext'
];
Liferay.Service.Journal.JournalStructure.updateStructure(
{
groupId: groupId,
structureId: structureId,
parentStructureId: parentStructureId || '',
nameMap: '{' + defaultLocale + ':' + name + '}',
descriptionMap: '{' + defaultLocale + ':' + (description == '' ? null : description ) + '}',
xsd: xsd,
serviceContext: A.JSON.stringify(
{
scopeGroupId: groupId
}
),
serviceParameterTypes: A.JSON.stringify(serviceParameterTypes)
},
function(message) {
if (Lang.isFunction(callback)) {
callback(message);
}
}
);
Note, the example above uses JSON to populate the ServiceContext.
On the front-end, you can use Alloy UI and Liferay UI tags in your forms to extract information and automatically insert the corresponding data into your request object. As an example, see portal-web/docroot/html/portlet/blogs/edit_entry.jsp. Next, let’s take a look at an example of accessing information from a ServiceContext.
Accessing Service Context data
This section provides code snippets from BlogsEntryLocalServiceImpl.addEntry(..., ServiceContext) that demonstrates how to access information from a ServiceContext and provides comments on how the context information is being used.
As previously mentioned, your service will need a scope group ID from your ServiceContext. The same holds true for the blogs entry service because the scope group ID provides the scope of the blogs entry (the entity being persisted). In the case of adding a blogs entry, the scope group ID is used in the following manner:
- Used as the groupId for the
BlogsEntryentity - Used in generating a unique URL for the blog entry
- Setting the scope for comments on the blog entry
Here are the corresponding code snippets:
long groupId = serviceContext.getScopeGroupId();
...
entry.setGroupId(groupId);
...
entry.setUrlTitle(getUniqueUrlTitle(entryId, groupId, title));
...
// Message boards
if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
mbMessageLocalService.addDiscussionMessage(
userId, entry.getUserName(), groupId,
BlogsEntry.class.getName(), entryId,
WorkflowConstants.ACTION_PUBLISH);
}
The ServiceContext is also used to access the UUID and the time this blog entry was added.
entry.setUuid(serviceContext.getUuid());
...
entry.setCreateDate(serviceContext.getCreateDate(now));
Can ServiceContext be used in setting permissions on resources? You bet! When adding a blog entry, new permissions can be added or existing permissions can be applied for the blog entry:
// Resources
if (serviceContext.isAddGroupPermissions() ||
serviceContext.isAddGuestPermissions()) {
addEntryResources(
entry, serviceContext.isAddGroupPermissions(),
serviceContext.isAddGuestPermissions());
}
else {
addEntryResources(
entry, serviceContext.getGroupPermissions(),
serviceContext.getGuestPermissions());
}
Categories, tag names, and the link entry IDs can be applied to the AssetEntry for the blogs entry, as demonstrated:
// Asset
updateAsset(
userId, entry, serviceContext.getAssetCategoryIds(),
serviceContext.getAssetTagNames(),
serviceContext.getAssetLinkEntryIds());
The ServiceContext also plays a part in starting a workflow instance for the blogs entry. As you can see, the scope group ID sets the scope for the workflow to be started for the blog entry.
// Workflow
if ((trackbacks != null) && (trackbacks.length > 0)) {
serviceContext.setAttribute("trackbacks", trackbacks);
}
else {
serviceContext.setAttribute("trackbacks", null);
}
WorkflowHandlerRegistryUtil.startWorkflowInstance(
user.getCompanyId(), groupId, userId, BlogsEntry.class.getName(),
entry.getEntryId(), entry, serviceContext);
The previous snippet also demonstrates using the trackbacks attribute which is a standard attribute for the blogs entry service. But there may be cases where you need to pass in custom attributes to your blogs entry service. To do so, use Expando attributes to carry these custom attributes along in your ServiceContext. Expando attributes are set on the added blogs entry like so:
entry.setExpandoBridgeAttributes(serviceContext);
As we’ve demonstrated, the ServiceContext can be used to transfer lots of useful information for your services.