Using the CMIS Provider to integrate WebCenter Content

What is CMIS?

CMIS is an acronym for 'Content Management Interoperability Services'.  Basically, it's a specification that will enable greater interoperability of Enterprise Content Management (ECM) systems.  WebCenter CMIS provides a means to integrate with Oracle's UCM content management system.

A good overview of CMIS and how it is implemented as a REST service is provided in the WebCenter CMIS documentation.

Personalization is all about delivering relevant content: documents or images that are targeted to a particular user based on the dynamic interaction of that user with the site.  This blog post shows how WebCenter Personalization can help you leverage the power of CMIS to achieve that goal.

The CMIS Provider

WebCenter Personalization integrates with CMIS via a data provider implementation, enabling easy integration with other WCP services.  The CMIS provider can also be used on its own to retrieve query-based content from the UCM server.  Several examples are given in the WebCenter Personalization demo application

 Limitations

The CMIS Provider supports only the query API, since this is the only service implemented by Oracle's CMIS REST service.   Full text search is not yet supported by Oracle's CMIS REST service; search is limited to content metadata.

A Tour of the CMIS Provider APIs

Users invoke methods on the CMIS Executable Resource.   More information about the details of the Conductor and its use can be found in the WebCenter Personalization User's Guide. The purpose of this blog is to dive into the methods available to invoke on the CMIS Provider.

Here's what a scenario invoking the CMIS Provider looks like:

We'll learn more about the 'Method name' and 'Parameters' entries.  Basically, they are all query APIs with an input search String, returning various types of Objects.  Some of those Objects can me marshaled back to the client; others cannot, but can be used within the scenario to pass as parameters to other constructs.  Unless otherwise noted in the method descriptions below, the return types can be marshaled back to the client;

Example queries (the 'search' parameter) are given in the WebCenter CMIS documents

Note that the 'select * from xxx' value of xxx in the query can be 'cmis:document', for documents only, or 'ora:t:IDC!;GlobalProfile' to retrieve properties associated with WebCenter content.  The distinction is important because the former will not contain attributes such as classURN and objectURN that can be used as input to other providers, such as Activity Graph.

public String search(String search)

This returns the entire ATOM String from the search.   It is not very useful to use within a scenario (for example, to manipulate the data to extract IDs or links), but may be returned to the caller for further manipulation or use.  See examples of using the CMISFunctionProvider in the example scenarios.  The maximum number of search results will default to the UCM setting.

public String search(String search, int maxItems, int skipCount)

There is also a similar  API with 'maxItems' and 'skipCount' to support limiting the number of return items and jumping to a particular index in the return value.

public List<WcpsContent> searchAsWcpsContent(String search)

This is most commonly used, since it marshals the ATOM response into the WcpsContent Object.  Basically, it's a Java Bean that's able to recognize WebCenter content via the last 4 parameters.  Additionally, you can just use 'cmis:document' instead of the more unwieldy 'ora:t:IDC!;GlobalProfile'; this method will convert the call for you.

The attributes on WcpsContent are derived from the Abdera Feed List<Entry>

public class WcpsContent
{
   // Taken from the link href, converted into a form that WebCenter understands.  
   // Example:  stanl18-ucm11g#dDocName:STANL18USORACL150001
   String id;

   // Entry title
   String title;
 
   // Entry author name
   String author;

   // Entry updated value toString() so it is marshallable
   String updated;

   // Entry contentSource, the URL to the content stream
   String contentSource;

   // Taken from one of the property values, "webcenter:serviceid"
   String serviceId;

   // Taken from one of the property values, "webcenter:resourceType"
   String resourceType;

   // Derived from serviceId and resourceType.  
   // Examples are WC.document, WC.wiki-page, WC.blog, WC.user
   String classURN;

   // Derived from serviceId and resourceType.  The object identifier.  
   // Example user, "carl".  
   // Example document: stanl18-ucm11g#dDocName:STANL18USORACL150001
   String objectURN;

   ...
}

...

WcpsContent has a List of WcpsContentProperties, also Java Beans derived from the ATOM response transformed into a CMISObject, looping over its properties:

public class  WcpsContentProperties
{ 
String name;
Object value; 
....

public List<WcpsContent> searchAsWcpsContent(String search, int maxItems, int skipCount)

There is also a similar  API with 'maxItems' and 'skipCount' to support limiting the number of return items and jumping to a particular index in the return value.

public Feed searchAsAbderaFeed(String search)

This returns the search results as an Abdera Feed object.  It is not marshalable, but can be used as an input parameter to other calls within the scenario.

public Feed searchAsAbderaFeed(String search, int maxItems, int skipCount)

Same as above, supporting limits and jumping to index.

public List<CMISObject> searchAsCMISObjectList(String search)

Returns the search results as a list of CMISObjectIt is not marshalable, but can be used as an input parameter to other calls within the scenario.

public List<CMISObject> searchAsCMISObjectList(String search, int maxItems, int skipCount)

Same as above, supporting limits and jumping to index.

CMIS Function Provider

The CMIS function provider exists mostly to transform data.  It is accessible in the JDev UI when creating an expression:

Note the syntax of using the function provider.

public static String getCMISQueryForDocIDsFromFullIDs(List<String> ids)

One of the most useful APIs is that to convert a list of IDs (perhaps coming in from the Activity Graph Provider) to a CMIS query string to retrieve multiple content items.  The ID will be in the form of a WebCenter ID, such as 'stanl18-ucm11g#dDocName:MOUNTAINS'

public static List<CMISObject> atomAsCMISObjects(String atomFeed)

Since CMISObject is not marshalable, this method could be used in your Java client code to convert the ATOM query response to List<CMISObject>.

public static List<Entry> atomAsEntries(String atomFeed)

Again useful in the client Java code, since Entry is an attribute on Abdera Feed, it also is not marshalable.   This method could be used in your Java client code to convert the ATOM query response to List<Entry>.

Using the providers in scenarios

Configuration 

If you're using the  WCP demo application,  please note the section on how to configure wcps-connections.xml.  This will provide anonymous access to the UCM server backing the CMIS REST service (the user/password is ignored and simply overrides the secure trust service).  If you want to enable the secure trust service for cross-domain authentication, please see this post.  Enabling cross-domain security will permit users to see only the data they are entitled to see, including content in private WebCenter Spaces.

 Jump-start

 Download and use the WCP demo application for a quick jump-start using the CMIS Provider.  Example scenarios are given for CMIS, along with a UI to execute them.   Also, I've attached a zip file of many example scenarios to demonstrate uses of the CMIS Provider, CMIS Function Provider, EL syntax, scenario collections and looping, and so on.  You'll probably want to change the name of the <connection> entry in each to be 'CmisConfigConnection' if you're using the WCP demo application.

Dot notation of return objects

The Conductor scenario syntax uses EL (Expression Language).  Therefore, you can reference nested objects.  Let's say you have a List<WcpsContent> assigned to the variable $searchResults.  Then:

  • ${searchResults[0]} is the first item
  • ${searchResults[0].title} is the title of the first

You could also iterate over the search results and get its properties:

<scenario:scenario xmlns:common="http://xmlns.oracle.com/wcps/conductor/common/1.0.0"
                   xmlns:scenario="http://xmlns.oracle.com/wcps/conductor/scenarios/1.0.0">
    <body>

        <!-- Invoke CMIS Search.  Store variable in 'searchResults' -->
        <call-provider>
            <provider-name>CMISProvider</provider-name>
            <connection-name>CmisConfigConnection</connection-name>
            <method-name>searchAsWcpsContent</method-name>
            <variable>searchResults</variable>
            <input>
                <parameter>
                    <common:name>search</common:name>
                    <common:value>select * from cmis:document where cmis:name LIKE '%jpg'</common:value>
                </parameter>
                <parameter>
                    <common:name>maxItems</common:name>
                    <common:value>2</common:value>
                </parameter>
                <parameter>
                    <common:name>skipCount</common:name>
                    <common:value>0</common:value>
                </parameter>
            </input>
        </call-provider>

        <!-- Iterate over that return list and create a new collection of Properties only -->
        <!-- First, we need a new collection to store the URLs in -->
        <assign-variable>
            <variable>props</variable>
            <expression>${collections:new()}</expression>
        </assign-variable>

        <!-- Now iterate over search results, extract properties, add to collection -->
        <for-each>
            <body>
                <assign-variable>
                    <variable>props</variable>
                    <expression>${collections:append(props,wcpscontent.properties)}</expression>
                </assign-variable>
            </body>
            <variable>wcpscontent</variable>
            <max-iterations>-1</max-iterations>
            <items>${searchResults}</items>
        </for-each>

        <return>
            <expression>${props}</expression>
        </return>
    </body>
    <name>wcpsContentPropertiesScenario</name>
</scenario:scenario>

Summary

The CMIS Provider is a great component to use in Personalization; after all, personalization is mostly about tailoring content for a given user.   This post shows how the CMIS Provider can be used in the Conductor framework to easily integrate content into your application.  Links to the existing demo app using the CMIS Provider should jump-start you using CMIS, and the example scenarios give plenty of examples to learn from.

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

This blog is dedicated to topics related to WebCenter Personalization, a new feature in Oracle 11gR1. It will focus mostly on a hands-on approach of how to leverage Personalization in your application to target and maintain customers by delivering dynamic, relative content.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today