REST API

Content Enricher

 

Extract from the course "Working with the REST API" on Nuxeo University

Pluggable Context

It is sometimes useful to optimize the number of requests you send to the server. For that reason we provide a mechanism for requesting more information on the answer, simply by specifying the context you want in the request header.

For example, it is some times useful to get the children of a document while requesting that document. Or its parents. Or its open related workflow tasks. The Nuxeo Platform provides you with several content enrichers out of the box for the most common use cases, and you can contribute your own if needed.

How To Call a Content Enricher

Content enrichers can be called by sending the proper header(s) in your request. The header you need to call depends on the entity-type being enriched by the enricher. Hence, enrichers enriching documents can be called using the header:

X-NXenrichers.document: enricherName

If you want to call an enricher enriching a user for instance, you would do it through a slightly different header:

X-NXenrichers.user: enricherName

Several enrichers can be called in a single request by specifying a comma separated list in the header, or by sending several headers:

X-NXenrichers.document: enricher1,enricher2,enricher3

is equivalent to sending:

X-NXenrichers.document: enricher1
X-NXenrichers.document: enricher2
X-NXenrichers.document: enricher3

and combination would work.

The enrichers can be called the same way by passing GET parameters.

http://NUXEO_SERVER/nuxeo/site/api/v1/path/default-domain/workspaces?enrichers.document=enricher1,enricher2
http://NUXEO_SERVER/nuxeo/site/api/v1/path/default-domain/workspaces?enrichers.document=enricher1&enrichers.document=enricher2

Default Content Enrichers

Thumbnail

When specifying X-NXenrichers.document: thumbnail, the JSON payload of the document REST calls response that contains the related attached file thumbnail of the document:

Call Example

Request URL:
http://localhost:8080/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
 Request Method:
 GET
 Request Headersview source
 ...
 Content-type:
 application/json+nxentity
 X-NXenrichers.document:
 thumbnail
 X-NXproperties:
 dublincore

JSON Response Example

{
    "entity-type": "document",
    "repository": "default",
    "uid": "4246ca87-c076-4bf4-b62b-0bab9dd21102",
    "path": "/default-domain/workspaces/Marketing/photo.jpg",
    "type": "Picture",
    "state": "project",
    "parentRef": "036f99ec-a500-4a1e-9d89-e8eb656a0ff7",
    "isCheckedOut": true,
    "changeToken": "1426696491000",
    "title": "photo.jpg",
    "lastModified": "2015-03-18T16:34:51.00Z",
    "properties":
    {
        "dc:description": "",
        ...
    },
    "facets":
    [
        "Versionable",
        ...
    ],
    "contextParameters":
    {
        "thumbnail":
        {
            "url": "http://localhost:8080/nuxeo/nxthumb/default/4246ca87-c076-4bf4-b62b-0bab9dd21102/thumb:thumbnail/Small_photo.jpg"
        }
    }
}

More details about the thumbnail enricher: http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/platform/ui/web/io/ThumbnailJsonEnricher.html

ACLs

When specifying X-NXenrichers.document: acls, the JSON payload of the document REST calls response that contains all related ACLs of the document:

Call Example

Request URL:
http://localhost:8080/nuxeo/api/v1/id/036f99ec-a500-4a1e-9d89-e8eb656a0ff7
Request Method:
GET
Request Headers
...
Content-type:
application/json+nxentity
X-NXenrichers.document:
acls
X-NXproperties:
dublincore

JSON Response Example

{
    "entity-type": "document",
    "repository": "default",
    "uid": "036f99ec-a500-4a1e-9d89-e8eb656a0ff7",
    "path": "/default-domain/workspaces/Marketing",
    "type": "Workspace",
    "state": "project",
    "parentRef": "02d7b1d5-791a-4939-ae6e-aaa75c05bd2c",
    "isCheckedOut": true,
    "changeToken": "1426695969000",
    "title": "Marketing",
    "lastModified": "2015-03-18T16:26:09.00Z",
    "properties":
    {
        "dc:description": "",
        ...
    },
    "facets":
    [
        "Folderish",
        ...
    ],
    "contextParameters":
    {
        "acls":
        [
            {
                "name": "local",
                "aces":
                [
                    {
                        "username": "jsmith",
                        "permission": "ReadWrite",
                        "granted": true
                    }
                ]
            },
            {
                "name": "inherited",
                "aces":
                [
                    {
                        "username": "jdoe",
                        "permission": "Everything",
                        "granted": true
                    },
                    {
                        "username": "Administrator",
                        "permission": "Everything",
                        "granted": true
                    },
                    {
                        "username": "members",
                        "permission": "Read",
                        "granted": true
                    }
                ]
            }
        ]
    }
}

More details about the acls enricher: http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/permissions/ACLJsonEnricher.html

Preview

When specifying X-NXenrichers.document: preview, the JSON payload of the document REST calls response that contains the related attached file preview of the document:

Call Example

Request URL:
http://localhost:18090/api/v1/repo/test/path/folder_1/photo.jpg
 Request Method:
 GET
 Request Headersview source
 ...
 Content-type:
 application/json+nxentity
 X-NXenrichers.document:
 preview
 X-NXproperties:
 dublincore

JSON Response Example

{
    "entity-type": "document",
    "repository": "default",
    "uid": "4246ca87-c076-4bf4-b62b-0bab9dd21102",
    "path": "/default-domain/workspaces/Marketing/photo.jpg",
    "type": "Picture",
    "state": "project",
    "parentRef": "036f99ec-a500-4a1e-9d89-e8eb656a0ff7",
    "isCheckedOut": true,
    "changeToken": "1426696491000",
    "title": "photo.jpg",
    "lastModified": "2015-03-18T16:34:51.00Z",
    "properties":
    {
        "dc:description": "",
        ...
    },
    "facets":
    [
        "Versionable",
        ...
    ],
    "contextParameters":
    {
        "preview":
        {
            "url": "http://localhost:8080/nuxeo/restAPI/preview/default/4246ca87-c076-4bf4-b62b-0bab9dd21102/default/"
        }
    }
}

More details about the preview enricher: http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/platform/preview/io/PreviewJsonEnricher.html

Call Example

Request URL:
http://localhost:8080/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
 Request Method:
 GET
 Request Headersview source
 ...
 Content-type:
 application/json+nxentity
 X-NXenrichers.document:
 breadcrumb
 X-NXproperties:
 dublincore

JSON Response Example

{
    "entity-type": "document",
    "repository": "default",
    "uid": "4246ca87-c076-4bf4-b62b-0bab9dd21102",
    "path": "/default-domain/workspaces/Marketing/IMG_20141004_132816.jpg",
    "type": "Picture",
    "state": "project",
    "parentRef": "036f99ec-a500-4a1e-9d89-e8eb656a0ff7",
    "isCheckedOut": true,
    "changeToken": "1426696491000",
    "title": "IMG_20141004_132816.jpg",
    "lastModified": "2015-03-18T16:34:51.00Z",
    "properties":
    {
        "dc:description": "",
       ...
    },
    "facets":
    [
        "Versionable",
        ...
    ],
    "contextParameters":
    {
        "breadcrumb":
        {
            "entity-type": "documents",
            "entries":
            [
                {
                    "entity-type": "document",
                    "repository": "default",
                    "uid": "42bbc2f6-13bd-4eb1-8c35-07342358f5f8",
                    "path": "/default-domain",
                    "type": "Domain",
                    "state": "project",
                    "parentRef": "22288b40-7879-4665-b01e-b9bacb132506",
                    "isCheckedOut": true,
                    "changeToken": "1426694633000",
                    "title": "Default domain",
                    "lastModified": "2015-03-18T16:03:53.00Z",
                    "facets":
                    [
                        "Folderish",
                        ...
                    ]
                },
                {
                    "entity-type": "document",
                    ...
                },
                {
                    "entity-type": "document",
                    ...
                },
                {
                    "entity-type": "document",
                    ...
                    ]
                }
            ]
        }
    }
}

More details about the breadcrumb enricher: http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/core/io/marshallers/json/enrichers/BreadcrumbJsonEnricher.html

Other Enrichers

Additional enrichers are:

Contributing Your Own Content Enricher

Adding a content enricher is done by providing a Java class and a XML contribution. You can enrich a Nuxeo Document Model or any kind of specific object returned.

Document Model Content Enricher

Here is a sample to get you started, that provides a document's parent id, title and description.

<?xml version="1.0" encoding="UTF-8"?>
<component name="org.nuxeo.sample.enrichers.parentDocEnricher">
<!-- Start copying here if you declare the enricher in Nuxeo Studio -->
<extension target="org.nuxeo.ecm.core.io.MarshallerRegistry" point="marshallers">
  <register class="org.nuxeo.university.enrichers.ParentDocEnricher" enable="true" />
</extension>
<!-- Stop copying here if you declare the enricher in Nuxeo Studio -->
</component>

package org.nuxeo.sample.enrichers;

import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON;
import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;

// The class will be instanciated as a singleton
// Priority defines which marshaller will be used in case of conflict. Priority is an integer.
// The higher the number, the more priority you get: 10 > 1 for instance.
@Setup(mode = SINGLETON, priority = REFERENCE)
public class ParentDocEnricher extends AbstractJsonEnricher<DocumentModel> { // You could also enrich a user or anything else

    // The enricher will be called using X-NXenrichers.document: name (name being parentDoc here)
    // If you were enriching a user, you would call it using X-NXenrichers.user: name (X-NXenrichers.entity-type)
    public static final String NAME = "parentDoc";

    public ParentDocEnricher() {
        super(NAME);
    }

    // Method that will be called when the enricher is asked for
    @Override
    public void write(JsonGenerator jg, DocumentModel doc) throws IOException {
      // We use the Jackson library to generate Json
      ObjectNode parentDocJsonObject = addParentDocAsJson(doc);
      jg.writeFieldName(NAME);
      jg.writeObject(parentDocJsonObject);
    }

    private ObjectNode addParentDocAsJson(DocumentModel doc) {
      ObjectMapper o = new ObjectMapper();

      // First create the parent document's Json object content
      CoreSession session = doc.getCoreSession();
      DocumentModel parentDoc = session.getDocument(doc.getParentRef());

      ObjectNode parentObject = o.createObjectNode();
      parentObject.put("id", parentDoc.getRef().toString());
      parentObject.put("title", parentDoc.getTitle());
      parentObject.put("description", parentDoc.getPropertyValue("dc:description").toString());

      return parentObject;
    }
}

Specific Object Content Enricher

Here is a sample to get you started with a content enricher for the object org.nuxeo.ecm.platform.audit.api.LogEntry:

<?xml version="1.0" encoding="UTF-8"?>
<component name="org.nuxeo.sample.enrichers.logEntryEnricher">
<!-- Start copying here if you declare the enricher in Nuxeo Studio -->
<extension target="org.nuxeo.ecm.core.io.MarshallerRegistry"
           point="marshallers">
  <register class="org.nuxeo.sample.enrichers.LogEntryEnricher" enable="true" />
</extension>
<!-- Stop copying here if you declare the enricher in Nuxeo Studio -->
</component>
package org.nuxeo.sample.enrichers;
import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON;
import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

import org.codehaus.jackson.JsonGenerator;
import org.nuxeo.ecm.core.api.CoreInstance;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.NuxeoPrincipal;
import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher;
import org.nuxeo.ecm.core.io.registry.reflect.Setup;
import org.nuxeo.ecm.platform.audit.api.LogEntry;
import org.nuxeo.ecm.platform.usermanager.UserManager;
import org.nuxeo.runtime.api.Framework;

import com.google.common.base.Strings;

@Setup(mode = SINGLETON, priority = REFERENCE)
public class LogEntryEnricher extends AbstractJsonEnricher<LogEntry> {

    public static final String NAME = "sfLogEntry";

    public LogEntryEnricher() {
        super(NAME);
    }

    @Override
    public void write(JsonGenerator jsonGenerator, LogEntry logEntry) throws IOException {
        CoreSession session = CoreInstance.openCoreSession(logEntry.getRepositoryId());
        DocumentModel targetDocument = session.getDocument(new IdRef(logEntry.getDocUUID()));
        Date creationDate = ((GregorianCalendar) targetDocument.getPropertyValue("dc:created")).getTime();
        Date modificationDate = ((GregorianCalendar) targetDocument.getPropertyValue("dc:modified")).getTime();

        jsonGenerator.writeObjectFieldStart(NAME);
        jsonGenerator.writeObjectField("contact", getPrincipalName(logEntry));
        jsonGenerator.writeObjectField("creation", new SimpleDateFormat("yyyy-MM-dd").format(creationDate));
        jsonGenerator.writeObjectField("modification", new SimpleDateFormat("yyyy-MM-dd").format(modificationDate));
        jsonGenerator.writeEndObject();
    }

    protected String getPrincipalName(LogEntry logEntry) {
        UserManager userManager = Framework.getLocalService(UserManager.class);
        NuxeoPrincipal principal = userManager.getPrincipal(logEntry.getPrincipalName());
        String firstName = principal.getFirstName();
        String lastName = principal.getLastName();
        if (Strings.isNullOrEmpty(firstName) && Strings.isNullOrEmpty(lastName)) {
            return principal.getName();
        } else {
            return firstName + " " + lastName;
        }
    }
}

REST Request Header

Don't forget to set the proper header to use this enricher:

X-NXenrichers.logEntry = sfLogEntry

We'd love to hear your thoughts!

All fields required