Every Liferay asset is represented by a row in the AssetEntry
table of
Liferay’s database. Each row in this table has an entryId
primary key and
classNameId
and classPK
foreign keys (among many others). An asset entry
row’s classNameId
specifies the type of asset represented by the asset entry.
E.g., if a row has a classNameId
corresponding to JournalArticle
, this means
that the asset entry row represents a web content article. (In Liferay,
JournalArticle
is the back-end name for web content article.) An asset entry
row’s classPK
represents the primary key of the entity represented by the
asset. E.g., the classPK
field of an asset entry row corresponding to a web
content article contains the primary key of the web content article in the
JournalArticle
table of Liferay’s database.
Your first step in asset-enabling your guestbook and guestbook entry entities is
to make Liferay’s asset services available to your entities’ service layers.
Open your guestbook-portlet project’s docroot/WEB-INF/service.xml
file and add
the following references just above the closing </entity>
tag corresponding to
the guestbook entity:
<reference package-path="com.liferay.portlet.asset" entity="AssetEntry" />
<reference package-path="com.liferay.portlet.asset" entity="AssetLink" />
Add the same two references just above the closing </entity>
tag of the
guestbook entry entity. As discussed above, you need to use Liferay’s
AssetEntry
service so that your application can add asset entries
corresponding to guestbooks and guestbook entries. You’ll also use Liferay’s
AssetLink
service so that your application will support related assets.
“Asset links” are Liferay’s back-end term for related assets.
Handling Assets at the Guestbook Service Layer
Next, you need to update the add, update, and delete methods of your project’s
GuestbookLocalServiceImpl
and EntryLocalServiceImpl
classes. Open your
project’s GuestbookLocalServiceImpl
class and find the addGuestbook
method.
Replace it with the following method:
public Guestbook addGuestbook(long userId, String name,
ServiceContext serviceContext) throws SystemException,
PortalException {
long groupId = serviceContext.getScopeGroupId();
User user = userPersistence.findByPrimaryKey(userId);
Date now = new Date();
validate(name);
long guestbookId = counterLocalService.increment();
Guestbook guestbook = guestbookPersistence.create(guestbookId);
guestbook.setUuid(serviceContext.getUuid());
guestbook.setUserId(userId);
guestbook.setGroupId(groupId);
guestbook.setCompanyId(user.getCompanyId());
guestbook.setUserName(user.getFullName());
guestbook.setCreateDate(serviceContext.getCreateDate(now));
guestbook.setModifiedDate(serviceContext.getModifiedDate(now));
guestbook.setName(name);
guestbook.setExpandoBridgeAttributes(serviceContext);
guestbookPersistence.update(guestbook);
resourceLocalService.addResources(user.getCompanyId(), groupId, userId,
Guestbook.class.getName(), guestbookId, false, true, true);
AssetEntry assetEntry = assetEntryLocalService.updateEntry(userId,
groupId, guestbook.getCreateDate(),
guestbook.getModifiedDate(), Guestbook.class.getName(),
guestbookId, guestbook.getUuid(), 0,
serviceContext.getAssetCategoryIds(),
serviceContext.getAssetTagNames(), true, null, null, null,
ContentTypes.TEXT_HTML, guestbook.getName(), null, null, null,
null, 0, 0, null, false);
assetLinkLocalService.updateLinks(userId, assetEntry.getEntryId(),
serviceContext.getAssetLinkEntryIds(),
AssetLinkConstants.TYPE_RELATED);
Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
Guestbook.class);
indexer.reindex(guestbook);
return guestbook;
}
Your call to assetEntryLocalService.updateEntry
is responsible for adding a
new row (corresponding to the guestbook that’s being added) to the AssetEntry
table in Liferay’s database. The updateEntry
method of
AssetEntryLocalServiceImpl
can be used for both adding and updating asset
entries. It checks whether or not the asset entry already exists in the
database. If it does not, it adds it. If it does, it updates it. If you check
Liferay’s Javadocs for
AssetEntryLocalServiceUtil.updateEntry
, you’ll see that this method is
overloaded. Why did you use a version of this method with such a long message
signature? There’s only one version of the updateEntry
method that takes a
title
parameter (to set the asset entry’s title). Since you want to set the
asset title, that’s the version you use. In your call to
AssetEntryLocalServiceUtil.updateEntry
, you’re setting the asset entry’s title
to guestbook.getName()
, i.e., to the name of the guestbook entity.
Later in this learning path, you’ll update the Guestbook Admin portlet’s form
for adding guestbooks to allow related assets to be selected. Related assets are
stored in the AssetLink
table of Liferay’s database. Your call to
assetLinkLocalService.updateLinks
is responsible for adding the appropriate
entries to Liferay’s AssetLink
table so that the related assets feature works
for your guestbook entities. Just as the updateEntry
method of
AssetEntryLocalServiceImpl
can be used for both adding and updating asset
entries, the updateLink
method of AssetLinkLocalServiceImpl
can be used for
both adding and updating asset links.
Next, replace the updateGuestbook
method of GuestbookLocalServiceImpl
with
the following one:
public Guestbook updateGuestbook(long userId, long guestbookId,
String name, ServiceContext serviceContext) throws PortalException,
SystemException {
Date now = new Date();
validate(name);
Guestbook guestbook = getGuestbook(guestbookId);
User user = UserLocalServiceUtil.getUser(userId);
guestbook.setUserId(userId);
guestbook.setUserName(user.getFullName());
guestbook.setModifiedDate(serviceContext.getModifiedDate(now));
guestbook.setName(name);
guestbook.setExpandoBridgeAttributes(serviceContext);
guestbookPersistence.update(guestbook);
resourceLocalService.updateResources(serviceContext.getCompanyId(),
serviceContext.getScopeGroupId(), name, guestbookId,
serviceContext.getGroupPermissions(),
serviceContext.getGuestPermissions());
AssetEntry assetEntry = assetEntryLocalService.updateEntry(guestbook.getUserId(),
guestbook.getGroupId(), guestbook.getCreateDate(),
guestbook.getModifiedDate(), Guestbook.class.getName(),
guestbookId, guestbook.getUuid(), 0,
serviceContext.getAssetCategoryIds(),
serviceContext.getAssetTagNames(), true, null, null, null,
ContentTypes.TEXT_HTML, guestbook.getName(), null, null, null,
null, 0, 0, null, false);
assetLinkLocalService.updateLinks(serviceContext.getUserId(),
assetEntry.getEntryId(), serviceContext.getAssetLinkEntryIds(),
AssetLinkConstants.TYPE_RELATED);
Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
Guestbook.class);
indexer.reindex(guestbook);
return guestbook;
}
Here, you’re using assetEntryLocalService.updateEntry
to update an existing
asset entry and assetLinkLocalService.updateLinks
to add or update that
entry’s asset links (related assets). As mentioned above, you can use the
updateEntry
method of AssetEntryLocalServiceImpl
for both adding and
updating asset entries. assetLinkLocalService.updateLinks
works the same way.
Next, replace the deleteGuestbook
method of GuestbookLocalServiceImpl
with
the following one:
public Guestbook deleteGuestbook(long guestbookId,
ServiceContext serviceContext) throws PortalException,
SystemException {
Guestbook guestbook = getGuestbook(guestbookId);
List<Entry> entries = EntryLocalServiceUtil.getEntries(
serviceContext.getScopeGroupId(), guestbookId);
for (Entry entry : entries) {
EntryLocalServiceUtil.deleteEntry(entry.getEntryId(),
serviceContext);
}
resourceLocalService.deleteResource(serviceContext.getCompanyId(),
Guestbook.class.getName(), ResourceConstants.SCOPE_INDIVIDUAL,
guestbookId);
AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
Guestbook.class.getName(), guestbookId);
assetLinkLocalService.deleteLinks(assetEntry.getEntryId());
assetEntryLocalService.deleteEntry(assetEntry);
Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
Guestbook.class);
indexer.delete(guestbook);
guestbook = deleteGuestbook(guestbookId);
return guestbook;
}
Here, you use the guestbook’s classname and guestbook ID to retrieve the corresponding asset entry. Then you delete the asset links corresponding to the asset entry and, finally, the asset entry itself. As you might expect, the method signatures of the methods for deleting asset entries and asset links are shorter than the ones for adding/updating!
Handling Assets at the Entry Service Layer
You’ve updated the guestbook entity’s service methods. Now it’s time to update
the guestbook entry entity’s service methods. The calls you need to make to
assetEntryLocalService
and assetLinkLocalService
in the guestbook entry
entity’s service methods are identical to the ones you made in the guestbook
entity’s service methods. Open EntryLocalServiceImpl
and replace the
addEntry
method with the following method:
public Entry addEntry(long userId, long guestbookId, String name,
String email, String message, ServiceContext serviceContext) throws PortalException, SystemException {
long groupId = serviceContext.getScopeGroupId();
User user = userPersistence.findByPrimaryKey(userId);
Date now = new Date();
validate(name, email, message);
long entryId = counterLocalService.increment();
Entry entry = entryPersistence.create(entryId);
entry.setUuid(serviceContext.getUuid());
entry.setUserId(userId);
entry.setGroupId(groupId);
entry.setCompanyId(user.getCompanyId());
entry.setUserName(user.getFullName());
entry.setCreateDate(serviceContext.getCreateDate(now));
entry.setModifiedDate(serviceContext.getModifiedDate(now));
entry.setExpandoBridgeAttributes(serviceContext);
entry.setGuestbookId(guestbookId);
entry.setName(name);
entry.setEmail(email);
entry.setMessage(message);
entryPersistence.update(entry);
resourceLocalService.addResources(user.getCompanyId(), groupId, userId,
Entry.class.getName(), entryId, false, true, true);
AssetEntry assetEntry = assetEntryLocalService.updateEntry(userId,
groupId, entry.getCreateDate(), entry.getModifiedDate(),
Entry.class.getName(), entryId, entry.getUuid(), 0,
serviceContext.getAssetCategoryIds(),
serviceContext.getAssetTagNames(), true, null, null, null,
ContentTypes.TEXT_HTML, entry.getMessage(), null, null, null,
null, 0, 0, null, false);
assetLinkLocalService.updateLinks(userId, assetEntry.getEntryId(),
serviceContext.getAssetLinkEntryIds(),
AssetLinkConstants.TYPE_RELATED);
Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
Entry.class);
indexer.reindex(entry);
return entry;
}
Next, replace the updateEntry
method with the following one:
public Entry updateEntry(long userId, long guestbookId, long entryId,
String name, String email, String message,
ServiceContext serviceContext) throws PortalException,
SystemException {
long groupId = serviceContext.getScopeGroupId();
User user = userPersistence.findByPrimaryKey(userId);
Date now = new Date();
validate(name, email, message);
Entry entry = getEntry(entryId);
entry.setUserId(userId);
entry.setUserName(user.getFullName());
entry.setName(name);
entry.setEmail(email);
entry.setMessage(message);
entry.setModifiedDate(serviceContext.getModifiedDate(now));
entry.setExpandoBridgeAttributes(serviceContext);
entryPersistence.update(entry);
resourceLocalService.updateResources(user.getCompanyId(), groupId,
Entry.class.getName(), entryId,
serviceContext.getGroupPermissions(),
serviceContext.getGuestPermissions());
AssetEntry assetEntry = assetEntryLocalService.updateEntry(userId,
groupId, entry.getCreateDate(), entry.getModifiedDate(),
Entry.class.getName(), entryId, entry.getUuid(), 0,
serviceContext.getAssetCategoryIds(),
serviceContext.getAssetTagNames(), true, null, null, null,
ContentTypes.TEXT_HTML, entry.getMessage(), null, null, null,
null, 0, 0, null, false);
assetLinkLocalService.updateLinks(userId, assetEntry.getEntryId(),
serviceContext.getAssetLinkEntryIds(),
AssetLinkConstants.TYPE_RELATED);
Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
Entry.class);
indexer.reindex(entry);
return entry;
}
Finally, replace the deleteEntry
method with the following one:
public Entry deleteEntry(long entryId, ServiceContext serviceContext)
throws PortalException, SystemException {
Entry entry = getEntry(entryId);
resourceLocalService.deleteResource(serviceContext.getCompanyId(),
Entry.class.getName(), ResourceConstants.SCOPE_INDIVIDUAL,
entryId);
AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
Entry.class.getName(), entryId);
assetLinkLocalService.deleteLinks(assetEntry.getEntryId());
assetEntryLocalService.deleteEntry(assetEntry);
Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
Entry.class);
indexer.delete(entry);
entry = deleteEntry(entryId);
return entry;
}
Excellent! You’ve asset-enabled your guestbook and guestbook entry entities at the service layer. Your next step is to implement asset renderers for these entities so that they can be fully integrated into Liferay’s asset framework. Every Liferay asset needs an asset renderer class so that it can be displayed by the Asset Publisher portlet.