Content Presenter-CMIS-Complete

July 29, 2011 | 9 minute read
Text Size 100%:

Introduction

This post is focusing on how to create Content Presenter based pages with complex CMIS and custom content presenter templates that will create a filterable content list viewer using complex data types including Site Studio Region Elements.

The post will walk you through all steps based on a new Portal project, the tools you require to try this out is, JDeveloper 11gR1PS3 or 11gR1PS4, Oracle UCM Content Server 11gR1PS3 or 11gR1PS4, Oracle HTTP Services (optional), Oracle WebCenter Suite 11gR1PS3 or 11gR1PS4
In this demo we will serve all applications via the Oracle HTTP Server since this will enable in context editing from Content Presenter in the Portal.

Main Article

We are going to build a landing page where a filter bar will control Content Item listings, the content item listings will contain: Metadata and Regional Element Content from UCM. The Region Element content will originate from the Site Studio part of UCM. The end result will look like this:

Create Portal Project

  • Start Oracle JDeveloper as Default Role
  • Create New Application: Name: BlogJuly2011
  • Application Template: WebCenter Portal Application

CMIS_complete_1

  • Add Content Server Connection to application

CMIS_complete_2

  • Open the home.jspx, located in Web Content/oracle/webcenter/portalapp/pages

CMIS_complete_3

  • Setting up content presenter and the filter bar, currently we will use a hard coded filter bar, however getting this to be automatic generated from ADF-BC or RIDC is a small task if the data structure and infrastructure is in place
  • First we will add page markup with the filter and drop the Content Presenter Region, when dropping the region do not set the task flow parameters

In above code pay attention to row “25 to 35”, this rows add three filters (Business, Fashion, TV), this filters is based on af:commandLink with attached setPropertyListener.  The setPropertyListener is posting to a Page Parameter that is used to control the Content filter. In next step we will create this member.  Secondly other interesting point is row “40”, here we have added a region referencing the Content Presenter Taskflow, currently left the parameters unassigned.

CMIS_complete_4

<?xml version='1.0' encoding='UTF-8'?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"           xmlns:f="http://java.sun.com/jsf/core"           xmlns:af="http://xmlns.oracle.com/adf/faces/rich"           xmlns:pe="http://xmlns.oracle.com/adf/pageeditor"           xmlns:cust="http://xmlns.oracle.com/adf/faces/customizable">    <jsp:directive.page contentType="text/html;charset=UTF-8"/>    <f:view>       <af:document id="d1" title="Home">          <af:messages id="m1"/>          <af:form id="f1" usesUpload="true">             <af:pageTemplate value="#{bindings.pageTemplateBinding.templateModel}"                              id="pt1">                <f:facet name="content">                   <pe:pageCustomizable id="hm_pgc1">                      <cust:panelCustomizable id="hm_pnc1" layout="scroll">                         <af:panelGroupLayout layout="vertical" id="pgl4">                            <af:panelGroupLayout layout="horizontal" id="pgl22">                               <af:spacer width="90px" id="asdf"/>                               <af:panelGroupLayout layout="vertical" id="pgl2">                                  <af:panelGroupLayout layout="horizontal"                                                       id="pgl5">                                     <h1>News</h1>                                     <af:spacer width="60px" id="s2"/>                                  </af:panelGroupLayout>                                  <af:panelGroupLayout layout="horizontal"                                                       id="pgl3"                                                       inlineStyle="background-color:#DDD; border:1px solid #BBB; padding:10px; margin-bottom:20px;">                                     <af:commandLink text="Business" id="cl1"                                                     styleClass="taglink">                                        <af:setPropertyListener from="#{'Business'}"                                                                to="#{bindings.selectedTargetGroup1.inputValue}"                                                                type="action"/>                                     </af:commandLink>                                     <af:spacer width="10px" id="pt_s111"/>                                     <af:commandLink text="Fashion" id="cl11"                                                     styleClass="taglink">                                        <af:setPropertyListener from="#{'Fashion'}"                                                                to="#{bindings.selectedTargetGroup1.inputValue}"                                                                type="action"/>                                     </af:commandLink>                                     <af:spacer width="10px" id="pt_s1111"/>                                     <af:commandLink text="TV" id="cl111"                                                     styleClass="taglink">                                        <af:setPropertyListener from="#{'TV'}"                                                                to="#{bindings.selectedTargetGroup1.inputValue}"                                                                type="action"/>                                     </af:commandLink>                                  </af:panelGroupLayout>                               </af:panelGroupLayout>                            </af:panelGroupLayout>                            <af:panelGroupLayout layout="vertical" id="pgl1">                               <af:region value="#{bindings.doclibcontentpresenter1.regionModel}"                                          id="r1"                                          partialTriggers="::cl1 ::cl11 ::cl111"/>                            </af:panelGroupLayout>                         </af:panelGroupLayout>                      </cust:panelCustomizable>                      <f:facet name="editor">                         <pe:pageEditorPanel id="pep1"/>                      </f:facet>                   </pe:pageCustomizable>                </f:facet>             </af:pageTemplate>          </af:form>       </af:document>    </f:view> </jsp:root>
  • We are now going to update the page definition to have correct settings for the PPR refresh, CMIS query and other Content Presenter parameters.
<?xml version="1.0" encoding="UTF-8" ?> <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"                 version="11.1.1.55.96" id="homePageDef"                 Package="oracle.webcenter.portalapp.pages">    <parameters>       <parameter id="page_info"                  value="title=Home;desc=;keywords=;createdBy=weblogic;createDate=2010-06-08T10:12:28;lastUpdatedBy=weblogic;lastUpdateDate=2010-06-08T16:07:52;permissionClass=oracle.webcenter.security.auth.HierarchicalResourcePermission;target=serviceID=oracle.webcenter.page,scopeID=s8bba98ff_4cbb_40b8_beee_296c916a23ed,resourceID=/oracle/webcenter/portalapp/pages/home.jspx;excluded=false;style="/>       <parameter id="page_title" value="Home"/>       <parameter id="page_parent"                  value="/oracle/webcenter/portalapp/pagehierarchy/pages.xml"/>    </parameters>    <executables>       <variableIterator id="variables">          <variable Name="selectedTargetGroup" Type="java.lang.String"/>       </variableIterator>       <page viewId="${preferenceBean.defaultPageTemplate}"             id="pageTemplateBinding" Refresh="ifNeeded"/>       <taskFlow id="pageeditorpanel"                 taskFlowId="#{pageEditorBean.pageEditorPanel}"                 xmlns="http://xmlns.oracle.com/adf/controller/binding"/>       <taskFlow id="doclibcontentpresenter1"                 taskFlowId="/oracle/webcenter/doclib/view/jsf/taskflows/presenter/contentPresenter.xml#doclib-content-presenter"                 activation="deferred"                 xmlns="http://xmlns.oracle.com/adf/controller/binding"                 Refresh="ifNeeded">          <parameters>             <parameter id="taskFlowInstId"                        value="${'6d099918-cd61-4719-89f5-1cae8c6cb53e'}"/>             <parameter id="datasourceType" value="${'dsTypeQueryExpression'}"/>             <parameter id="datasource"                        value="${'SELECT * FROM ora:t:IDC:GlobalProfile WHERE ora:p:xTargetGroup = \''}${bindings.selectedTargetGroup1}${'\''}"/>             <parameter id="templateCategory" value="${''}"/>             <parameter id="templateView" value="${'ica.news.list.template'}"/>             <parameter id="regionTemplate" value="${false}"/>             <parameter id="maxResults" value="${''}"/>          </parameters>       </taskFlow>    </executables>    <bindings>       <attributeValues IterBinding="variables" id="selectedTargetGroup1">          <AttrNames>             <Item Value="selectedTargetGroup"/>          </AttrNames>       </attributeValues>    </bindings>    <permission permissionClass="oracle.webcenter.security.auth.HierarchicalResourcePermission"                target="serviceID=oracle.webcenter.page,scopeID=s8bba98ff_4cbb_40b8_beee_296c916a23ed,resourceID=/oracle/webcenter/portalapp/pages/home.jspx"                xmlns="http://xmlns.oracle.com/adf/security">       <privilege-map operation="create" privilege="create"/>       <privilege-map operation="delete" privilege="delete"/>       <privilege-map operation="edit" privilege="update"/>       <privilege-map operation="personalize" privilege="personalize"/>       <privilege-map operation="view" privilege="view"/>    </permission> </pageDefinition>
  • When updating the pageDef it can be easier to use the UI, Content Presenter is updated as below:

CMIS_complete_5

<parameter id="taskFlowInstId" value="${'6d099918-cd61-4719-89f5-1cae8c6cb53e'}"/> <parameter id="datasourceType" value="${'dsTypeQueryExpression'}"/> <parameter id="datasource" value="${'SELECT * FROM ora:t:IDC:GlobalProfile WHERE ora:p:xTargetGroup = \''}${bindings.selectedTargetGroup1}${'\''}"/> <parameter id="templateCategory" value="${''}"/> <parameter id="regionTemplate" value="${false}"/> <parameter id="maxResults" value="${''}"/>

As you can see in the step above the data source is set to a SQL like statement, this statement is based on CMIS markup, lets look further into what is it is actually doing:

  • SELECT * FROM ora:t:IDC:GlobalProfile : This part selects all fields from the GlobalProfile, if use the GlobalProfile we get access to all attributes including extend attributes in UCM
  • -WHERE ora:p:xTargetGroup = \''}${bindings.selectedTargetGroup1}${'\''} :This parts filters out all Documents where the xTargetGroup is set to ${bindings.selectedTargetGroup1}

This is the selection made when clicking in the filter.

xTargetGroup is an extend attribute in UCM that I have added to filter on, this can be any attribute where you can store on of the example values (Business, Fashion, TV).  Add this attribute to UCM metadata!

  • Run the application by right clicking on index.html in the root of the “Portal” project

CMIS_complete_6

Lets add some content so we get something in the list, however before we do that lets add a Region Definition that will handle element data for future task.

  • Start Site Studio Designer and connect to the content server
  • Create new Region Definition call it RD_NEWS make sure following
    • Doc Title (dDocTitle) = RD_NEWS
    • Content ID (dDocName) = RD_NEWS
    • Security Group = Public
  • Add four elements to the RD_NEWS
    • TITLE (Plain Text Element)
    • LEAD (Plain Text Element)
    • IMAGE (Image Element)
    • BODY (WYSIWYG Element) (Will not be used in this example)

CMIS_complete_7

Now we ready to create content that will be based on the new Region Definition (RD_NEWS).

  • Create three new Data Files
    • File 1: dDocTitle: Business News 1
    • dSecurityGroup: Public
    • xTargetGroup: Business
    • Title: Latest Business News
    • Lead: IPSUM (add about 2 – 3 rows of text)
    • Image: Pick suitable image
    • Body: Leave blank for now
  • File 2: dDocTitle: Fashion News 1
    • dSecurityGroup: Public
    • xTargetGroup: Fashion
    • Title: Latest Fashion News
    • Lead: IPSUM (add about 2 – 3 rows of text)
    • Image: Pick suitable image
    • Body: Leave blank for now
  • File 3: dDocTitle: TV News 1
    • dSecurityGroup: Public
    • xTargetGroup: TV
    • Title: Latest TV News
    • Lead: IPSUM (add about 2 – 3 rows of text)
    • Image: Pick suitable image
    • Body: Leave blank for now

Now lets test the result by launching the new portal and navigate the Filter

CMIS_complete_8

The Result presentation is pretty dull, lets spice it up so we can use all information that the records are carrying. In this section we will create 2 new Content presenter templates, one template to handle the list and the second one will print each item in the list.

  • Step one create new content presenter template
    • Create folder called contenttemplates in path /Web Content/oracle/webcenter/portalapp
    • Create new JSFF (Fragment) name it, news-list-template.jsff
    • Add following code to the new fragment
<?xml version = '1.0'?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"           xmlns:af="http://xmlns.oracle.com/adf/faces/rich"           xmlns:dt="http://xmlns.oracle.com/webcenter/content/templates">    <dt:contentListTemplateDef var="nodes">       <af:panelGroupLayout layout="vertical" id="nodeListPanel" valign="top">          <af:iterator rows="0" var="node" varStatus="iterator" value="#{nodes}">             <dt:contentTemplate node="#{node}" view="news.item.template"                                 nodesHint="#{nodes}"/>             <div style="height:15px; background-color:#ddd; width:100%">                <af:spacer height="15px" id="s1"/>             </div>          </af:iterator>       </af:panelGroupLayout>    </dt:contentListTemplateDef> </jsp:root>

Pay attention to the tag – dt:contentListTemplate, this tag is used to start a Content Presenter Listing when you get a list of items. The second important detail in the source code is the dt:contentTemplate where the view attribute is set to news.item.template. This tag include the template with  View Id: news.item.template. This content presenter template is not yet created, this will be created in the step below.

Next step is to add this as an Portal Resource, right click the news-list-template.jsff and fill in the values accordingly

CMIS_complete_10

The most important step on this screen is the View ID: news.list.template.  This will be used as templateView the content presenter taskflow binding, lets update this now.

Open the homePageDef and edit the doclibcontentpresenter1 Task Flow Binding

CMIS_complete_11

Now we need to create the single item content presenter template. This template will reference metadata from the given content item.

  • Create new JSFF (Fragment), name it news-template.jsff
  • Add following code to the new fragment
<?xml version = '1.0'?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"           xmlns:af="http://xmlns.oracle.com/adf/faces/rich"           xmlns:dt="http://xmlns.oracle.com/webcenter/content/templates">    <dt:contentTemplateDef var="node">       <af:panelGroupLayout layout="vertical" id="pgl3">          <af:panelGroupLayout layout="horizontal" valign="top"                               inlineStyle="background-color:#FFF; padding:10px;"                               id="pgl4">             <af:panelGroupLayout layout="vertical" id="pgl2" valign="top">                <af:outputText value="#{node.propertyMap['dInDate'].value.calendarValue}"                               id="ot3" styleClass="bodytext"                               converter="javax.faces.DateTime"/>             </af:panelGroupLayout>             <af:spacer width="10px;" id="s1"                        inlineStyle="background-color:#DDD; color:white;"/>             <af:panelGroupLayout layout="vertical" id="pgl1" valign="top">                <af:outputText value="#{node.propertyMap['xTargetGroup'].value}"                               id="ot12"                               inlineStyle="background-color:#0A9FC0; color:white; text-align:left; padding:5px;"/>                <af:goLink text="#{node.propertyMap['RD_NEWS:TITLE'].asTextHtml}"                           id="gil1"                           destination="#{'/faces/home/news-viewer?news_id='}#{node.propertyMap['dDocName'].value}"                           styleClass="newstitle"/>                <af:outputText value="#{node.propertyMap['RD_NEWS:LEAD'].asTextHtml}"                               id="ot2" styleClass="bodytext"/>             </af:panelGroupLayout>             <af:panelGroupLayout layout="vertical" id="pgl32" valign="top"                                  styleClass="newsimage">                <af:outputText value="#{node.propertyMap['RD_NEWS:IMAGE'].asTextHtml}"                               escape="false" id="ot1"                               inlineStyle="max-width:100px;"/>             </af:panelGroupLayout>          </af:panelGroupLayout>          <af:panelGroupLayout layout="horizontal" id="aaaa"></af:panelGroupLayout>       </af:panelGroupLayout>    </dt:contentTemplateDef> </jsp:root>

Important points in the code above is the various references to metadata assets in the content item, most remarkable is the site studio region elements references.  Pay attention to the tag – dt:contentTemplateDef, this tag is used to present a individual Content Presenter item. In the code markup we have also implemented two different metadata types, one is data from the table content and other type is embedded element data from the site studio content. Table Metadata example: Row 10: <af:outputText value="#{node.propertyMap['dInDate'].value.calendarValue}" Site Studio Element data: Row 15: <af:goLink text="#{node.propertyMap['RD_NEWS:TITLE'].asTextHtml}" . The unique markup to reference Site Studio Element data is to prefix the element name with the Region Definition Name that is enclosing the selected element. I.E {Region Def}:{Name}.

Final step is to register the new Content Presenter Template as a Portal Resource.

CMIS_complete_12

The important step here is to set the View ID to news.item.template, this name is referenced in the content presenter list template news-list-template.jsff

  • Last step is to deploy the application to the application server where you want to run the portal. My result of last actions:

CMIS_complete_13

To further test the new portal you can add more content to the enabled filters by repeating step above.  Finally you can update the skin to get improved look and feel, replace contents of portal-skin.CSS with following:

.globalnavi {     background: -moz-linear-gradient(center top , #F5F5F5 0%, #DEDEDE 100%) repeat scroll 0 0 transparent;     height:15px;     font-family:ICASansSerif-Bold,Arial,Helvetica,sans-serif; } .megamenu {     border-color: #CC0000;     border-style: solid;     border-width: 7px 7px; } .menuHome {     background: url('/images/bg-mega-active.png') no-repeat scroll right top transparent;     width:70px;     height:40px;     border-radius: 4px 4px 0 0; } .menuLinkSelected{     font-family:Arial,Helvetica,sans-serif;     font-size:14px;     color:#FFF; } .menuLink{     font-family:Arial,Helvetica,sans-serif;     font-size:14px; color:#222; } .AFPopupSelectorContentStart{     border-bottom:0px none;     border-right:0px;     border-top:0px;     border-width:0px;     font-size:0px; } .AFPopupSelectorHeader{     border-bottom:0px none;     border-right:0px;     border-top:0px;     border-width:0px;     font-size:0px; } .af_goLink{     color:#222; } .af_goLink:visited{     color:#222; } .af_document{     background-color:#DDD;     background-image:none; } .af_panelBorderLayout{     background-color:#FFF; } .af_pageCustomizable{     background-color:#FFF; } .taglink{     padding: 4px 7px;     background: -moz-linear-gradient(center top , #595959 0%, #404040 100%) repeat scroll 0 0 transparent;     border-radius: 4px 4px 4px 4px;     float:left; color:white;     font-size: 13px; } .taglink a{     color:white; } .categoryLink{     font-size:14px;     color:#555;     height:20px; } .categoryLinkTitle{     font-size:14px;     padding:0px;     color:#FFF;     background-color:#333;     height:20px; } .leftmenu{     width:180px; } .leftmenu div{     padding:10px;     border-bottom:1px solid #CCC; } H1{     font-size:33px; } .leadtext{      font-size:14px;      font-weight:bold;      line-height:160% } .bodytext{      font-size:14px;     line-height:160% } .newstitle{      font-size:33px;      color:#333;      font-weight:bold; } #filteroptions ul li {      border-radius: 4px 4px 4px 4px;      float: left;      margin: 0 5px 6px 0; } #filteroptions ul li a {      border-radius: 4px 4px 4px 4px;      color: #FFFFFF;      display: block;      float: left;      padding: 4px 7px; } #filteroptions ul li a.personalized {      background: -moz-linear-gradient(center top , #595959 0%, #404040 100%) repeat scroll 0 0 transparent; } .newsimage div img {      max-width:150px; }

New Portal Result

CMIS_complete_13

References

Content Presenter

REST Service Developers Guide

Stefan Krantz


Previous Post

Continuous Integration with SCA Tests

Mark Nelson | 12 min read

Next Post


Couple of things you need to know about the User/Role API

Andre Correa Neto | 3 min read