The Nuxeo Content Services Platform is designed from the ground up to be highly configurable, extensible and applicable for use as an application platform. Our API is a key component of this. Today, I’ll explain the API architecture and suggest some best practices in content management system architecture, so you can take advantage of the modular nature of the Nuxeo Platform. The idea is to take the maximum advantage of what’s available.

API ArchitectureAPI Architecture

Nuxeo API Architecture

First, noting the architecture, we have the Nuxeo repository and storage back ends at the core. On top of that is a set of services with which the rest of the system interacts to perform all content management functions. This is based on the OSGI model of modularity and extensibility. Standard distribution packages as well as additional Marketplace packages all contribute various definitions and services to build out the comprehensive capability of the system.

We go further by providing an additional modular layer called Content Automation, to configure and contain as much as possible within the platform. This allows for external application clients, custom front ends and other integrations to have only the minimal amount of content management process implementation required. We provide a variety of clients, such as JavaScript, and Java to handle the setting of parameters, making connections, and processing the JSON output.

Nuxeo APINuxeo API

Content Automation

Content Automation is a Nuxeo service that exposes common actions you do on a Nuxeo application as atomic operations. There are over 100 exposed operations covering all platform functionalities. You can assemble them to create complex business rules and logic, as Automation Chains in our configuration and design tool, Nuxeo Studio . These operations and chains can be called based on User Actions or Event Listeners as configured in Studio and deployed on the server, or remotely by API through HTTP/JSON.

Furthermore, you can create new atomic operations (i.e. write a Java class that defines an operation) in addition to the set of built-in operations and contribute them.

Ways to Use the API

As illustrated above, focusing on the external client via the API, you can see 3 different ways to use the API - Resource centric API, Command Endpoint for individual operations, and Automation Chains. Using the JavaScript client example, regardless of which endpoint, you’ll initialize the client:

var client = new nuxeo.Client({
  baseURL: 'http://demo.nuxeo.com/nuxeo'
});

This client object can now create a Request object for the REST API calls as well as an operation object for the Command Endpoint.

RESTful API

The resource centric API simplifies the most commonly called tasks by fixed URL definitions and is fully RESTful. This minimizes the need to reference and name an operation, as calls are evident from URL and HTTP method.

There are endpoints for CRUD operations on all the Nuxeo resources; Documents by ID or path, Users, Groups, Directories, Workflows as well as a Query endpoint to return a set of Documents.

Nuxeo API - ResourceNuxeo API - Resource

For example, to retrieve a document by path, you’d send a GET request to the Nuxeo server at ../api/v1/path/{docPath}, with nothing more than the path added on to the URL. You’d get a JSON object with structured data representing the document.

With the client, first create a request to the path endpoint:

var request = client.request('path/folder/document/etc');

Then execute a GET call to retrieve the document. You could also execute a Delete, Put or Post for other CRUD tasks. The doc reference represents the JSON result object, in this case a single document.

request.get(function(error, doc) {
   if(error) {
     throw error;
   }
   console.log('Fetched '+ doc.title + ' document');
 });

Command Endpoint (Operations)

The other part of the API is the Command Endpoint. Here instead of addressing a repository object, you call an operation and supply parameters. You have access to all deployed Nuxeo operations but the name is passed as a parameter. This is because you can create and deploy your own operations as well as call your own Automation Chains. This demonstrates the dynamically extensible nature of the Nuxeo Platform.

Nuxeo API - AutomationNuxeo API - Automation

As an example, we’ll use the JS client again and actually accomplish the same document retrieval as in the REST example.

Reference the operations documentation to find the name of the one you want to use. In this case, the Fetch operation is the one we will use:

var operation = client.operation('Document.Fetch') ;

Set the input value that the operation requires. In this case, it’s the path of the document you seek.

operation.input('doc:/folder/document/etc');

You can set parameters or headers if the operation requires based on its specification. Or you can just execute and implement the callback:

operation.execute(function(error, doc) {
   if(error) {
     throw error;
   }
   console.log('Fetched '+ doc.title + ' document');
 });

Note that both the REST and Command method accomplished the same thing.

Automation Chains

Finally, let’s look at the use of Automation Chains and why they are so useful.

Nuxeo API - Automation ChainsNuxeo API - Automation Chains

An Automation Chain can be configured in Studio by combining operations. Each operation accepts a Document or Blob as input, and returns an output document or Blob. In this way, the output of one operation becomes the input of the following operation in the chain sequence. In Studio, it’s simply a matter of drag and drop and setting required parameter values. Your chain can also define your own input parameters which you can set when you call the chain. As mentioned, they can be called from a user action, an event, or directly by your external client in the same manner as individual operations. You just specify the name.

It’s designed to define your higher level business tasks, which run just like native low level calls.

In Studio, you can also define Automation Chains by scripting in JavaScript, which makes more complex looping and conditions easier to program.

There are a few important benefits of using a chain:

  • It is executed as one transaction and rolls back as a whole if one operation fails. You can be sure your content will not become inconsistent.
  • It’s executed on the server and doesn’t require multiple client calls.
  • Finally, they can be called from other clients if needed, eliminating the need to duplicate the process definition, as well as making the chain available on the server to be called as a response to an Event or User action.

Nuxeo Automation ChainNuxeo Automation Chain

In the example illustrated above, with one client call you are passing in a property change to a Document, adding a tag to flag it, changing the lifecycle state, creating a version, converted it to a PDF, and returning it back to the client.

Prefer Automation Chains over Multiple Client Calls

Instead of doing multiple calls from the client for what is conceptually an atomic task, it’s better to create an Automation Chain in Studio, deploy to Nuxeo server, and make a single call from the client. The key benefit of this is that it’s run atomically as a transaction, ensuring content consistency. You are also improving performance by eliminating the overhead of multiple HTTP client calls. Your whole process is run in the server’s memory space.

Also, this allows you to reuse the same business task from other client calls, other applications, as well as on the Nuxeo side by User Actions and Event listeners. You can also use scripting to define Automation Chains just like you would have in the client.

It may be tempting to keep the flow and logic in your client for more clarity in your development process, but the benefits of Studio defined Automation Chains will usually outweigh the standard way of doing things.

Other Best Practices

Use the RESTful API for single step CRUD operations.

In the examples above, both methods achieved the same result. I suggest that RESTful would be a better choice because it’s more intuitive when you are thinking in terms of the resource. It’s designed that way. You can call a GET on an object to display in UI for edit, take user changes and just call a POST on the same client object resource. You don’t need to create, find, and instantiate a different operation call object in the client, but simply use a different HTTP method in the RESTful way. There is also a fewer number of steps required to define your task, since the URL includes both the object type and it’s reference path or ID.

Use operation commands for more complex needs, custom operations, or multiple related calls.

The set of operations available is over 100 and covers the whole of the platform capability, which isn’t covered by the REST API. You can execute complex tasks involving multiple steps, made more convenient by being able to pass in the result/output object from one operation call to another as input.

Documentation, References and More Advanced Topics

You can look into more related advanced topics I didn’t cover here, such as Adapters and Content Enrichers in the main REST API documentation or the JavaScript Client.

With the Nuxeo API Playground, you can explore all the concepts I mentioned here, and also browse the Command API with a list of available operations, the RESTful API, Batch Uploads, and Data Structures.

Finally, a catalog of all operations in available in the Nuxeo Platform Explorer.