Integrating WebCenter Likes / Comments in Content Presenter - I
This post will explain how to use the API in order to use the Likes Service in a Content Presenter Task Flow.
"Comments part will be soon in Integrating WebCenter Likes / Comments in Content Presenter-II"
There is an OOTB Likes service implemented in WebCenter Portal allowing the users to “like” and comment the activities and content in WebCenter Portal.
Download LikesComments JDeveloper Project
For example:
Document Manager Task Flow allows to “Like“/“Unlike” Content.
How can I add the same functionality to the Content Presenter Templates?
The sample brings an API to retrieve the Likes / Comments information from a given oracle.webcenter.content.integration.Node (the var of the Content Presenter template).
package custom.oracle.webcenter.likescomments; import java.util.HashMap; import java.util.List; import java.util.Map; import oracle.adf.share.logging.ADFLogger; import oracle.webcenter.activitystreaming.ActivityException; import oracle.webcenter.activitystreaming.ActivityObject; import oracle.webcenter.activitystreaming.ActivityStreamingService; import oracle.webcenter.activitystreaming.ActivityStreamingServiceFactory; import oracle.webcenter.comments.Comment; import oracle.webcenter.comments.CommentsSummary; import oracle.webcenter.content.integration.Node; import oracle.webcenter.content.integration.RepositoryException; import oracle.webcenter.content.integration.spi.ucm.UCMConstants; import oracle.webcenter.doclib.internal.model.VCRUtils; import oracle.webcenter.framework.service.Scope; import oracle.webcenter.framework.service.ServiceContext; import oracle.webcenter.framework.service.ServiceObjectType; import oracle.webcenter.likes.Like; import oracle.webcenter.likes.LikesSummary; /** * Utility class to access to Likes and Comments of a specific Node. * This class will access in Map EL Expression way * TODO: Implement a Declarative Component / or bean bigger scope to don't recalculate everything * @author Daniel Merchan Garcia * @version 1.0 */ public final class LikesCommentsProcessor { /** * Logger */ private static final ADFLogger LOG = ADFLogger.createADFLogger(LikesCommentsProcessor.class); /** * Class name to be used by the logger */ private static final String CLASS_NAME = LikesCommentsProcessor.class.getName(); /** * Map holding nodeLikesComments */ private Map<Node, NodeLikeComments> nodeLikesComments; /** * Default Constructor */ public LikesCommentsProcessor() { super(); // Implementation via Map EL expression nodeLikesComments = new HashMap<Node, NodeLikeComments>() { @Override public NodeLikeComments get(Object key) { if (key != null && key instanceof Node) { Node node = (Node)key; NodeLikeComments nlc = this.getCommentsLikes(node); return nlc; } else { return super.get(key); } } /** * Extract from a Node all Comments and Likes * @param node */ private NodeLikeComments getCommentsLikes(Node node) { LOG.entering(CLASS_NAME, "getCommentsLikes"); // FIXME prevent Folder item asking about isFolder NodeLikeComments nlc = new NodeLikeComments(); nlc.setNode(node); try { ActivityStreamingService as = ActivityStreamingServiceFactory.getInstance().getActivityStreamingService(); // Extract inforamtion required for ActivityStreaming API and Likes Tag String resourceId = getResourceId(node); String serviceId = VCRUtils.getStringProperty(node, UCMConstants.SERVICE_ID_PROP_DEF_NAME); String resourceType = VCRUtils.getStringProperty(node, UCMConstants.RESOURCE_TYPE_PROP_DEF_NAME); String name = node.getName(); ServiceObjectType serviceObjType = as.findObjectType(serviceId, resourceType); ActivityObject activityObject = as.createObject(resourceId, serviceObjType, name); activityObject.setServiceID(serviceId); ActivityObject actObj = ActivityStreamingServiceFactory.getInstance().getActivityStreamingService().getObjectDetailsManager().getObjectDetail(activityObject); // Extract all information using ActivityObject and node information if (actObj != null) { nlc = getCommentsLikesFromActivityObject(actObj, nlc); } else { // In case of not being registered yet the Id and the Type must to be provided // FIXME: Current GUID or default GUID???? to be decided... nlc.setScopeGUID(ServiceContext.getContext().getScope().getGUID()); //nlc.setScopeGUID(ServiceContext.getContext().getDefaultScope().getGUID()); nlc.setActivityId(activityObject.getId()); nlc.setActivityType(activityObject.getType().getName()); } } catch (RepositoryException e) { e.printStackTrace(); } catch (ActivityException e) { e.printStackTrace(); } return nlc; } /** * Auxiliar method to get the resourceId expected from the content * @param node * @return [repositoryName]#dDocName:[dDocNameValue] */ private String getResourceId(Node node) { String repository = node.getId().getRepositoryName(); String dDocName = node.getId().getUid(); return repository "#dDocName:" dDocName; } /** * Extract and store likes and comments from an ActivityObject * @param actObj with all content information about comments and Likes * @param nlc NodeLikeComments to fill */ private NodeLikeComments getCommentsLikesFromActivityObject(ActivityObject actObj, NodeLikeComments nlc) { int commentsCount = 0; int likesCount = 0; Like myLike = null; List<Comment> recentComments = null; try { // Retrieving all comments CommentsSummary commentsSummary = actObj.getCommentsSummary(); if (commentsSummary != null) { commentsCount = commentsSummary.getCount(); recentComments = commentsSummary.getRecentComments(); for (Comment o : recentComments) { // TODO: Testing API purpose LOG.fine("Comment:" o.toString()); // LOG.fine("AuthorId:" o.getId()); // LOG.fine("CommentText:" o.getCommentText()); // LOG.fine("Creation Date:" o.getCreationDate()); } } LikesSummary likesSummary = actObj.getLikesSummary(); if (likesSummary != null) { likesCount = likesSummary.getCount(); myLike = likesSummary.getMyLike(); } nlc.setActivityType(actObj.getType().getName()); nlc.setActivityId(actObj.getId()); Scope scope = actObj.getScope(); if (scope != null) { nlc.setScopeGUID(scope.getGUID()); } else { nlc.setScopeGUID(ServiceContext.getContext().getDefaultScope().getGUID()); } // nlc.setScopeGUID(actObj.getScope().getGUID()); //nlc.setScopeGUID(ServiceContext.getContext().getScope().getGUID()); nlc.setRecentComments(recentComments); nlc.setCommentsCount(Integer.valueOf(commentsCount)); nlc.setLikesCount(Integer.valueOf(likesCount)); nlc.setMyLike(myLike); if (LOG.isFinest()) { LOG.finest(CLASS_NAME,"getCommentsLikes",nlc.toString()); } } catch (ActivityException e) { LOG.warning(CLASS_NAME,"getCommentsLikes","Error using Activity Stream API for Likes / Comments",e); } LOG.exiting(CLASS_NAME, "getCommentsLikes"); return nlc; } }; } /** * Get map containing the nodes and likes associated to the content * @return Map */ public Map<Node, NodeLikeComments> getNodeLikesComments() { return nodeLikesComments; } }
The API is implemented in EL Expression / Map way in order to pass the Node as parameter.
#{backingBeanScope.likesComments.nodeLikesComments[node].likesCount}
With the API the following parameters are retrieved for the required input parameters of <likes:likesLink> :
Parameter | Description | Type |
Id | Id of the UI Component | String |
rendered | Flag to render or not the component. | Boolean |
serviceId | ID of the service that holds the content (oracle.webcenter.content, oracle.webcenter.doclib…) | String |
objectType | Type of the content. In case of oracle.webcenter.doclib service then can be webContent, content, blog, wiki, folder | String |
objectId | Id of the object. In case of content of oracle.webcenter.content/doclib then is [repoName]#dDocName:[dDocNameValue] | String |
scopeId | Scope GUID of the content in case of being in a WebCenter Portal (Spaces) | String |
likesCount | Number of likes | Int |
myLike | Likes Services associated to the current user | oracle.webcenter.likes.Like |
The sample Content Presenter is the following:
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:dt="http://xmlns.oracle.com/webcenter/content/templates"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
xmlns:likes="http://xmlns.oracle.com/webcenter/likes">
<dt:contentTemplateDef var="node">
<af:panelGroupLayout id="pgl1" layout="vertical">
<!-- General information of the test node -->
<af:outputText value="#{node.propertyMap['webcenter:serviceid'].value.stringValue}"
id="ot1"/>
<af:outputText value="#{node.propertyMap['webcenter:resourcetype'].value.stringValue}"
id="ot2"/>
<af:outputText value="#{backingBeanScope.likesComments.nodeLikesComments[node].activityId}"
id="ot3"/>
<af:outputText value="#{backingBeanScope.likesComments.nodeLikesComments[node].activityType}"
id="ot4"/>
<af:outputText value="#{backingBeanScope.likesComments.nodeLikesComments[node].scopeGUID}"
id="ot5"/>
<af:outputText value="#{backingBeanScope.likesComments.nodeLikesComments[node].commentsCount}"
id="ot6"/>
<af:outputText value="#{backingBeanScope.likesComments.nodeLikesComments[node].likesCount}"
id="ot7"/>
<af:outputText value="#{backingBeanScope.likesComments.nodeLikesComments[node].myLike}"
id="ot8"/>
<!-- Likes testing -->
<likes:likesLink id="ol1" rendered="#{true}"
serviceId="#{node.propertyMap['webcenter:serviceid'].value.stringValue}"
objectType="#{node.propertyMap['webcenter:resourcetype'].value.stringValue}"
objectId="#{backingBeanScope.likesComments.nodeLikesComments[node].activityId}"
scopeId="#{backingBeanScope.likesComments.nodeLikesComments[node].scopeGUID}"
likesCount="#{backingBeanScope.likesComments.nodeLikesComments[node].likesCount}"
myLike="#{backingBeanScope.likesComments.nodeLikesComments[node].myLike}"/>
</af:panelGroupLayout>
</dt:contentTemplateDef>
</jsp:root>
It uses a scoped managed bean (registered customizing Content Presenter) using the LikesCommentsProcessor to retrieve all the information required by likes:likesLink tag.
Now the Likes button appears and works perfectly for the associated content:
How to deploy and use it?
The sample is deployed as shared-lib and registered in the weblogic.xml of the WebCenter Portal or Framework Portal application.
Content Presenter was customized to add the manage bean as low scope (backing or request scope).
Download LikesComments JDeveloper Project