Extract from the course "Working with the REST API" on Hyland 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:
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
{
"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:
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
{
"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:
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
{
"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
Breadcrumb
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
{
"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:
- permissions: http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/core/io/marshallers/json/enrichers/BasePermissionsJsonEnricher.html
- children: http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/core/io/marshallers/json/enrichers/ChildrenJsonEnricher.html
- permanent link (documentURL): http://community.nuxeo.com/api/nuxeo/release-7.10/javadoc/org/nuxeo/ecm/platform/url/io/DocumentUrlJsonEnricher.html
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;
}
}
}
Don't forget to set the proper header to use this enricher:
X-NXenrichers.logEntry = sfLogEntry