Asset Framework

Liferay’s asset framework is a system that allow you to add common functionality to your application. For example, you might build an event management application that shows a list of upcoming events. It might be nice to be able to tag or categorize those events to provide users with metadata describing more about them. Or you might want to let users comment on events.

This common functionality is what Liferay’s asset framework gives you. Using the power of Liferay’s built-in message boards, tags, and categories, Liferay lets you infuse your application with these features in no time.

The term asset is a generic term referring to any type of content, including text, an external file, a URL, an image, or a record in an online book library. Consequently, when we use the term asset here, we’re referring to some type of Liferay content, like documents, blog entries, bookmarks, wiki pages, or anything you create in your applications.

Here are the features you can reuse thanks to the asset framework:

Associate tags to custom content types. New tags are created automatically when the author assigns them to the content.

Associate categories to custom content types. Authors are only allowed to select from predefined categories within several predefined vocabularies.

Manage tags from the control panel, including merging tags.

Manage categories from the control panel, including creating complex hierarchies.

Publish your content using the Asset Publisher portlet. Asset Publisher can publish dynamic asset lists or manually selected asset lists. It can also show an asset summary view with a link to the full view. This saves you time, since it likely won’t be necessary to develop custom portlets for your custom content types.

At this point you might be saying, “Asset Framework sounds great; but how do I leverage all these awesome functions?” Excellent question, young padawan, and perfect timing; we couldn’t have said it better ourselves.

We’ll describe the first two briefly here before we dive in head first:

The first step is mandatory; you must let the framework know whenever one of your custom content entries is added, updated or deleted.

The second step enables the asset framework in the UI: you can use a set of taglibs to provide widgets that allow authors to enter comments, tags and categories, as well as how to show the entered tags and categories along with the content.

Next let’s dive head first into the first step; informing the Asset Framework when you add, update, or delete assets.

Whenever you create a new entity, you need to let the Asset Framework know. In this sense, it’s similar to permission resources. It’s a simple procedure: you invoke a method of the Asset Framework that adds an AssetEntry so that Liferay can keep track of the asset.

Specifically, you should access these methods using either the static methods of AssetLocalServiceUtil or an instance of the AssetEntryLocalService injected by Spring. To simplify this section, we’ll be using the static methods of AssetLocalServiceUtil, since it doesn’t require any special setup in your application.

The method to invoke when one of your custom content entries is added or updated is the same, and is called updateEntry. Here’s the full signature:

Here’s a quick summary of the most important parameters of this method:

userId is the identifier of the user who created the content.

groupId identifies the scope of the created content. If your content doesn’t support scopes (extremely rare), just pass 0 as the value.

className identifies the type of asset. The recommended convention is to use the name of the Java class that represents your content type, but you can actually use any String you want as long as you are sure that it is unique.

classPK identifies the specific content being created among others of the same type. It’s usually the primary key of the table where the custom content is stored. If you want, you can use the classUuid parameter to specify a secondary identifier; it’s guaranteed to be universally unique. It’s especially useful if your content will be exported and imported across separate portals.

assetCategoryIds and assetTagNames represent the categories and tags selected by the author of the content. The Asset Framework will store them for you.

visible specifies whether the content should be shown at all by Asset Publisher.

title,description and summary are descriptive fields used by the Asset Publisher when displaying entries of your content type.

publishDate and expirationDate, when specified, tell Asset Publisher it shouldn’t show the content before a given publication date or after a given expiration date, respectively.

All other fields are optional; it won’t always make sense to include them. The sync parameter should always be false unless you’re doing something very advanced (feel free to look at the code if you’re really curious).

When one of your custom content entries is deleted, you should once again let Asset Framework know. That way it can clean up stored information and make sure that the Asset Publisher doesn’t show any information for the content that has been deleted. The signature of method to delete an asset entry is:

In the last section we let Asset Framework know about the tags and categories that we associated with a given asset; but how does a content author specify the tags and categories?

Liferay provides a set of JSP tags you can use to make this task very easy. You can put the following Liferay UI tags in your forms to create content that can be associated with new or existing tags or predefined categories:

These two taglibs create appropriate form controls that allow the user to search for a tag or create a new one or select an existing category.

Tip: If you’re using Liferay’s Alloy UI Form taglibs, creating fields to enter tags and categories is even simpler. You just use <aui:input name="tags" type="assetTags" /> and <aui:input name="categories" type="assetCategories" />, respectively.

Once the tags and categories have been entered, you’ll want to show them along with the content of the asset. Here’s how to display the tags and categories:

In both JSP tags, you can also specify a portletURL parameter; each tag that uses it will be a link containing the portletURLandtag or categoryId parameter value, respectively. This supports tags navigation and categories navigation within your portlet. You’ll need to implement the look-up functionality in your portlet code; do this by reading the values of those two parameters and using the AssetEntryService to query the database for entries based on the specified tag or category.

Great job! You’ll have no problem associating tags and categories with your assets. Before we go further with our example, let’s take a look at more JSP tags you can use to leverage Asset Framework’s features.

There are JSP tags, called Liferay UI tags, associated with each feature. You can find these tags used in the JSPs for Liferay’s built-in portlets (e.g. the edit_entry.jsp of the Blogs portlet). Here are some examples of the JSP tags from the Blogs portlet:

A huge benefit of using the asset framework is that you can leverage the Asset Publisher portlet to publish lists of your custom asset types. You can choose to have users specify lists dynamically (e.g., based on the asset tags or categories) or have administrators do it statically.

To display your assets, the Asset Publisher needs to know how to access their metadata. You also need to provide the Asset Publisher templates for the types of views (e.g. full view and abstract view) available to display your assets. You can provide all this to the Asset Publisher by implementing these two interfaces:

AssetRendererFactory: A class that knows how to retrieve specific assets from persistent storage using the classPK. The classPK is typically the asset’s primary key, but can be anything you specified to the updateAsset method, which you use to add or update the asset. Your factory implementation can grab the asset from a groupId (identifies a scope of data) and a urlTitle (a title that can be used in friendly URLs to refer uniquely to the asset within a given scope). Finally, the asset renderer factory can provide a URL for the Asset Publisher to use when a user wants to add a new asset of your custom type. This URL should point to your own portlet. There are other less important methods of the interface, but you can avoid implementing them by extending BaseAssetRendererFactory. By extending this base class instead of implementing the interface directly, your code will be more robust to possible interface changes in future versions of Liferay, since the base implementation will be updated to accommodate the interface changes.

AssetRenderer: This is an interface that provides metadata information about one specific asset. It checks whether the current user has permission to edit or view the asset and renders the asset for the different templates (e.g. abstract and full content view) by forwarding to a specific JSP. We recommend that you extend the BaseAssetRenderer class rather than directly implementing the interface. The base class provides helpful defaults and contains methods that get added to the interface in the future.

Let’s look at an example of these two classes. We’ll use Liferay’s Blogs portlet again, and we’ll start by implementing AssetRendererFactory:

In the render method, there’s a forward to a JSP in the case of the abstract and the full content templates. The abstract isn’t mandatory and if it isn’t provided, the Asset Publisher shows the title and the summary from the appropriate methods of the renderer. The full content template should always be provided. Here’s how it looks for blogs entries:

That’s about it. It wasn’t that hard, right? Now it’s time to get really fancy; put on your dancing shoes. If you need to extend the capabilities of the AssetRendererFactory for one of Liferay’s core portlets, check out the article Extending an AssetRendererFactory by Juan Fernàndez; he talks about doing just that.

Now get out there and start enjoying the benefits of the Asset Framework in your custom portlets.