ddraper

v1 REST APIs with Aikau

Blog Post created by ddraper on Oct 25, 2016

My colleague Gavin Cornwell has started writing a series of blog posts on how to make use of the v1 REST APIs that will be available in the next release of Alfresco. PLEASE NOTE: If you want to test out the example in this post then you'll need to follow the setup steps from Gavin's posts!

 

Aikau was originally written to work with the the internal WebScript based REST APIs written for Share. As these REST APIs were not intended for public consumption there is some inconsistency in both the parameters used for the requests and the schema of the response body. This meant that Aikau widgets were intentionally written to be easily configurable to work with different APIs and the use of the services meant that it was easy to normalise any data provided.

 

One of the many great things about Aikau is the fact that it will quite happily work with any of the REST APIs provided by the Alfresco Repository be they WebScripts, CMIS or even the new v1 APIs. This blog post provides a very simple example of how to access and render the data shown in Gavin's second post. The point of the post is to show how to provide a service that can work with the v1 APIs and how to widgets can be configured. At some point in the near future Aikau is likely to start providing dedicated services for working with the v1 APIs (in fact the FileUploadService already can be configured to work with them!). I've stripped the example back to the most basic rendering to focus on how to access the data - the usual principles of building Aikau pages can be applied to make a more interesting and useful interface.

 

Our custom service "blogs/V1RestApiDocumentService" looks like this:

 

define(["dojo/_base/declare",
        "alfresco/services/BaseService",
        "alfresco/core/CoreXhr",
        "alfresco/core/topics",
        "service/constants/Default",
        "dojo/_base/lang"], 
        function(declare, BaseService, CoreXhr, topics, AlfConstants, lang) {
   
   return declare([BaseService, CoreXhr], {

      registerSubscriptions: function blog_V1RestApiDocumentService_registerSubscriptions() {
         this.alfSubscribe(topics.GET_DOCUMENT_LIST, lang.hitch(this, this.onRetrieveDocumentsRequest));
      },

      onRetrieveDocumentsRequest: function blog_V1RestApiDocumentService_onRetrieveDocumentsRequest(payload) {
         var url =  AlfConstants.URL_CONTEXT + "proxy/alfresco-api/-default-/public/alfresco/versions/1/nodes/-root-/children";
         var config = {
            alfSuccessTopic: payload.alfSuccessTopic,
            alfFailureTopic: payload.alfFailureTopic,
            url: url,
            method: "GET",
            callbackScope: this
         };
         this.serviceXhr(config);
      
   });
});

 

The service comprises of two functions registerSubscriptions (which all services should implement) to create the subscription to the topics that the service should respond to - in this case the standard topic for getting documents. The subscription creates the binding to the onRetrieveDocumentsRequest function that actually makes the XHR request for the data.

 

The key thing to note here is how the url variable is constructed - by appending "/proxy/alfresco-api" to the application context (i.e. "/share") then you get authenticated access to the v1 REST APIs (in much the same way that "/proxy/alfresco" will get authenticated access to the WebScript REST APIs). The remainder of the URL (from "-default-" onward) is taken from the example in the blog post.

 

Our custom service mixes in the CoreXhr module to gain access to the serviceXhr function that is called to make the XHR request. The alfSuccessTopic and alfFailureTopic attributes are expected to be provided (which will be handled by the defaultSuccessCallback and defaultFailureCallback functions respectively provided by the CoreXhr module).

 

A simple page model to use this service and render the results could look like this:

 

model.jsonModel = {
   services: ["blog/V1RestApiDocumentService"],
   widgets: [
      {
         name: "alfresco/lists/AlfList",
         config: {
            itemsProperty: "list.entries",
            metadataProperty: "list.pagination",
            startIndexProperty: "list.pagination.skipCount",
            totalResultsProperty: "list.pagination.totalItems",
            widgets: [
               {
                  name: "alfresco/lists/views/AlfListView",
                  config: {
                     widgets: [
                        {
                           name: "alfresco/lists/views/layouts/Row",
                           config: {
                              widgets: [
                                 {
                                    name: "alfresco/lists/views/layouts/Cell",
                                    config: {
                                       widgets: [
                                          {
                                             name: "alfresco/renderers/Property",
                                             config: {
                                                propertyToRender: "entry.name"
                                             }
                                          }
                                       ]
                                    }
                                 }
                              ]
                           }
                        }
                     ]
                  }
               }
            ]
         }
      }
   ]
};

 

It is the AlfList that will make the request to the service - but in order to be able to work with the v1 REST API schema it is necessary to reconfigure:

  • the itemsProperty - to indicate where the array of items can be found in the response
  • the metadataProperty - to indicate where information about the items can be found
  • the startIndexProperty -  for pagination data handling (not used in this example) - to indicate what page
  • the totalResultsProperty - also for pagination data handling

 

Unfortunately we're not able to reuse any of the existing Document Library views (such as AlfSimpleView, AlfDetailedView, etc) because the properties in the v1 REST API response schema are different. So here we're just constructing a simple view to render the name of each node. More information on build views for lists can be found in the Aikau tutorial on GitHub.

 

The end result is not especially exciting, it looks like this:

 

Aikau-V1-REST-API-1.png

... but you should hopefully recognize the rendered values as the names of the folders that you'd find in the alfresco://company/home in the Alfresco Repository.

 

The key thing to takeaway from this post is how easy it is to setup up Aikau to work with the new APIs. In future releases of Aikau we will provide services for working directly with the new APIs, but this should hopefully demonstrate that you can easily write your own services to use them and still make full use of the hundreds of widgets that are currently available in Aikau.

 

Update 26/05/2016

I've done some more experimenting with the V1 REST APIs and made a better user interface (see video below). This video demonstrates some widgets from a development branch of Aikau that has (at the time of writing) yet to be merged into the main project. This branch contains a number of performance improvements as well as a set of widgets with a Material Design Lite skin. You should note that the majority of the existing capabilities of Aikau lists are being re-used and that the interface is driving the browsing, pagination and sorting capabilities of the v1 REST API.

 

Outcomes