Extending the REST API Outside of the Box for WebCenter Sites 12c

image

While the default REST API in WebCenter Sites 12c continues to provide the same basic and key functionalities for developers to use; if a developer or a project required a deeper and more targeted Sites specific task to be implemented, then this is where a customized controller and tailored end-point would have a place to shine.

Out of the Box

Out of the gate, WCS provides a decent collection of default API call functionalities.

For example:

  • Search all assets
  • Searching all assets in a specific site
  • Searching all assets in a specific site (with a specific asset type)

Using the default REST API call to get two random assets from avisports can look like this:

 

http://<yourHost>:<somePort>/Sites/REST/resources/v1/search/sites/avisports/assets?fields=name&limit=2

The response body would be in json:

 

{
  "offset": 0,
  "limit": 100,
  "count": 5,
  "hasMore": true,
  "links": [
    {
      "href": "http://<host>:<port>/<context>/REST/resources/v1/search/assets?field:name:startswith=1",
      "rel": "self",
      "templated": false,
      "mediaType": "",
      "method": "",
      "profile": ""
    },
    {
      "href": "http://<host>:<port>/<context>/REST/resources/v1/search/assets?field:name:startswith=1",
      "rel": "canonical",
      "templated": false,
      "mediaType": "",
      "method": "",
      "profile": ""
    },
    {
      "href": "http://<host>:<port>/<context>/REST/resources/v1/metadata-catalog/search/assets",
      "rel": "describedby",
      "templated": false,
      "mediaType": "application/schema+json",
      "method": "GET",
      "profile": ""
    },
    {
      "href": "http://<host>:<port>/<context>/REST/resources/v1/search/assets?field:name:startswith=1&offset=0",
      "rel": "first",
      "templated": false,
      "mediaType": "",
      "method": "",
      "profile": ""
    },
    {
      "href": "http://<host>:<port>/<context>/REST/resources/v1/search/assets?field:name:startswith=1&offset=0",
      "rel": "last",
      "templated": false,
      "mediaType": "",
      "method": "",
      "profile": ""
    }
  ],
  "items": [
    {
      "name": "Fit for Tennis, Fit for Life",
      "link": {
        "href": "http://<host>:<port>/<context>/REST/resources/v1/aggregates/avisports/AVIArticle/1330880448272",
        "rel": "assetReference",
        "templated": false,
        "mediaType": "",
        "method": "GET",
        "profile": ""
      },
      "id": "AVIArticle:1330880448272"
    },
    {
      "name": "Agility Drills",
      "link": {
        "href": "http://<host>:<port>/<context>/REST/resources/v1/aggregates/avisports/AVIArticle/1330881053255",
        "rel": "assetReference",
        "templated": false,
        "mediaType": "",
        "method": "GET",
        "profile": ""
      },
      "id": "AVIArticle:1330881053255"
    }
  ]
} 

 

Making use of these precooked API calls could be enough, they are already bundled into the product, they are convenient, and require a minimum of fuss to drop execute.

But, notice the bloat?

What if there is no real need for arrays of attributes, values like:profile, mediaType, or the large series of links, that bring in pieces like "next", "last", "first"?

It is plain enough to recognize that these additional pieces were built in to provide a convenience factor for the json consumer. But, if a cleaner REST call could be made with the exact specifications needed - trimmed of the unnessary bits and perfectly tailored to the task at hand - let's give that a try.

Just Outside of the Box

Begin in the Admin UI and create a new Controller.


The Admin UI will do some of the work in providing a sample shell of what the Controller should implement and override.


Provide a useful and descriptive name and click the "Save" disk.

Side-note: As a part of the WCS 12c Controller framework and by extending BaseController access to the ics component is already available.

Return a list of types eneabled for site: avisports

With the controller shell sample created, the next step is to configure the controller as a REST endpoint.

  • Import RESTful services resources
  • Include annotations for GET or POST methods
  • ...
  • Return a desired object - string, json, etc.

If the desired output is simply a line by line output of all enabled types for avisports, then the implementation could look something like the following:

 

@GET
@Path("/getSiteEnabledTypes")
public String getSiteEnabledTypes(@DefaultValue("avisports") @QueryParam("site") String siteName)
{   
   String returnValue = "";

   List<String> types = getEnabledAssetTypes(siteName);
        
   for(String t: types)
   {
     returnValue += t + "<br/>";
   }
return returnValue;
}

The getEnabledAssetTypes() method will do the lifting here:

 

private String getEnabledAssetTypes(String site)
{
  
  // instantiate necessary WCS components
  Session s = SessionFactory.getSession(ics);
  assetTypeDataManager = (AssetTypeDefManager) s.getManager(com.fatwire.assetapi.def.AssetTypeDefManager.class
            .getName());
  siteManager = (SiteManager) s.getManager(com.fatwire.assetapi.site.SiteManager.class.getName());
  
  // iterate over sites list
  for (SiteInfo si: siteManager.list())
  {
    if(site.equalsIgnoreCase(si.getName()))
    {
      List<Site> siteObj = siteManager.read(Arrays.asList(site));               
      if(siteObj != null && siteObj.size() == 1)
      {
        Site theSite = siteObj.get(0);          
        return theSite.getAssetTypes();
      }
    }
  }
  return Collections.emptyList();
}

REST call:

http://<host>:<port>/sites/REST/controller/myReallyGoodController/getSiteEnabledTypes?site=avisports

Result/Output:

WCS_ABTest
AVIArticle
ArticleCategory
ContentAttribute
AttrTypes
CSElement
WCS_Chart
ContentQuery
WCS_Controller
WCS_Dashboard
ContentDef
Device
DeviceGroup
FileResource
ContentFilter
AVIImage
ImageCategory
Page
PageAttribute
PageDefinition
ContentParentef
AdvCols
Segments
SiteNavigation
SiteEntry
Template
ScalarVals
WCS_AccessProviders
WCS_AggregationTemplates
WCS_VisitorsConfig
WCS_IdentityProviders
WCS_ProfileProviders
WebRoot
YouTube

This example serves as a small and simplified usage of a custom REST end-point. It would be a minor task to make use of JsonObject(s) in order to build out a more complex structure that is leaner than the out-of-the-box examples and fitted to the needs of a particular application.

For example, large queries across all known types and subtypes of a large WebCenter Sites deployment and selective attribute criteria filters can be applied and returned by a custom controller call in seconds rather than minutes or even hours from a cluttered stock API call. So, from a performance perspective we have found great success in improving the overall responsiveness in our integrations by building out these tailored and enhanced API calls, performing only one is needed and pairing down any unnecessary additional system formatting/processing.

 

Subscribe to Our Newsletter

Stay In Touch