Pluggable Context
Sometimes it's useful to optimize the number of requests you send to the server. For this reason, we provide a mechanism for requesting more information on the response, simply by specifying the context you require in the request header.
For example, sometimes you need to get the children, parents or workflow tasks of a document while requesting that document. 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.
Default Content Enrichers
Enricher | Included in Response: |
---|---|
thumbnail |
Related attached file thumbnail of the current document |
preview |
Related attached file preview of the current document |
documentURL |
Document's URL |
breadcrumb |
Document breadcrumb (list of all parent documents) |
subtypes |
Array of document types that can be created under the current document |
children |
List of all children documents |
hasContent |
Boolean flag indicating whether or not current Folderish or Collection document has children or members |
hasFolderishChild |
Boolean flag indicating whether or not current document has folderish child document |
favorites |
Boolean flag indicating whether or not current document belongs to user's Favorites |
collections |
The collections to which the current document belongs |
tags |
The tags on the current document |
firstAccessibleAncestor |
The closest document's ancestor which is used to find what safe document to redirect to when deleting some. |
runningWorkflows |
Workflow instances running on the current document |
runnableWorkflows |
Workflow models that can be launched on the current document |
pendingTasks |
Pending tasks on the current document |
acls |
All related ACLs of the current document |
permissions |
Current user's permissions on the current document |
publications |
Publication count of the current document |
userVisiblePermissions |
List of permissions available on current document |
audit |
Latest log entries related to the current document |
subscribedNotifications |
Current user's subscribed notifications for the current document |
userprofile |
DOB, phone number and avatar of current user |
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 affected by the enricher. Enrichers on documents can be called using the header:
enrichers.document: enricherName
If you want to call an enricher on a user, you would do it through a slightly different header:
enrichers.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:
enrichers.document: enricher1,enricher2,enricher3
is equivalent to sending:
enrichers.document: enricher1
enrichers.document: enricher2
enrichers.document: enricher3
The enrichers can be called the same way by passing GET parameters.
http://NUXEO_SERVER/nuxeo/api/v1/path/default-domain/workspaces?enrichers.document=enricher1,enricher2
http://NUXEO_SERVER/nuxeo/api/v1/path/default-domain/workspaces?enrichers.document=enricher1&enrichers.document=enricher2
Examples
Thumbnail
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: thumbnail
properties: 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://NUXEO_SERVER/nuxeo/api/v1/4246ca87-c076-4bf4-b62b-0bab9dd21102/@rendition/thumbnail"
}
}
}
More details about the thumbnail enricher: http://community.nuxeo.com/api/nuxeo/latest/javadoc/org/nuxeo/ecm/platform/thumbnail/io/ThumbnailJsonEnricher.html
ACLs
Request URL: http://NUXEO_SERVER/nuxeo/api/v1/id/036f99ec-a500-4a1e-9d89-e8eb656a0ff7
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: acls
properties: 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/latest/javadoc/org/nuxeo/ecm/permissions/ACLJsonEnricher.html
Preview
Request URL:
http://localhost:18090/api/v1/repo/test/path/folder_1/photo.jpg
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: preview
properties: 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://NUXEO_SERVER/nuxeo/restAPI/preview/default/4246ca87-c076-4bf4-b62b-0bab9dd21102/default/"
}
}
}
More details about the preview enricher: http://community.nuxeo.com/api/nuxeo/latest/javadoc/org/nuxeo/ecm/platform/preview/io/PreviewJsonEnricher.html
Breadcrumb
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: breadcrumb
properties: 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/latest/javadoc/org/nuxeo/ecm/core/io/marshallers/json/enrichers/BreadcrumbJsonEnricher.html
Favorites
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: favorites
properties: 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": {
"favorites": {
"isFavorite": true
}
}
}
Collections
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: collections
properties: 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": {
"collections": [{
"changeToken": "1464771452017",
"entity-type": "document",
"facets": [
"Versionable",
"Collection",
"NotCollectionMember"
],
"isCheckedOut": true,
"lastModified": "2016-06-01T08:57:32.01Z",
"parentRef": "8e62af0a-a74c-4bd1-96a4-66034834bf3b",
"path": "/default-domain/UserWorkspaces/Administrator/Collections/Fox Icons",
"repository": "default",
"state": "project",
"title": "Fox Icons",
"type": "Collection",
"uid": "50110ba5-b129-40b2-9880-3d9783710404"
}]
}
}
Tags
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: tags
properties: 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": {
"tags": [{
"label": "My Tag",
"weight": 0
}]
},
}
First Accessible Ancestor
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: firstAccessibleAncestor
properties: 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": {
"firstAccessibleAncestor": {
"entity-type": "document",
"path": "/default-domain/workspaces/Marketing",
...
}
},
}
Running Workflows
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: runningWorkflows
properties: 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": {
"runningWorkflows": [{
"attachedDocumentIds": [{
"id": "4246ca87-c076-4bf4-b62b-0bab9dd21102"
}],
"entity-type": "workflow",
"graphResource": "http://NUXEO_SERVER/nuxeo/api/v1/workflow/75dfb9e0-65dd-4150-9d66-ade0597e27c2/graph",
"id": "75dfb9e0-65dd-4150-9d66-ade0597e27c2",
"initiator": "Administrator",
"name": "ParallelDocumentReview.27323664461439033",
"state": "running",
"title": "wf.parallelDocumentReview.ParallelDocumentReview",
"variables": {
"end_date": "2016-05-27T22:00:00.00Z",
"initiatorComment": null,
"participants": [],
"review_result": "",
"review_result_file": {
"data": "http://NUXEO_SERVER/nuxeo/nxfile/default/75dfb9e0-65dd-4150-9d66-ade0597e27c2/var_ParallelDocumentReview:review_result_file/output.ftl",
"digest": "f5bd3d4fc1431be93631ecc3862a4ddc",
"digestAlgorithm": "MD5",
"encoding": null,
"length": "68",
"mime-type": "text/xml",
"name": "output.ftl"
},
"validationOrReview": null
},
"workflowModelName": "ParallelDocumentReview"
}]
}
}
Runnable Workflows
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: runnableWorkflows
properties: 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": {
"runnableWorkflows": [{
"attachedDocumentIds": [],
"entity-type": "workflow",
"graphResource": "http://NUXEO_SERVER/nuxeo/api/v1/workflowModel/SerialDocumentReview/graph",
"id": "0b0a21b7-284c-4f69-99e6-c334f2c69077",
"initiator": null,
"name": "SerialDocumentReview",
"state": "validated",
"title": "wf.serialDocumentReview.SerialDocumentReview",
"variables": {
"index": 0,
"initiatorComment": null,
"participants": [],
"validationOrReview": "validation"
},
"workflowModelName": "SerialDocumentReview"
}]
}
}
Pending Tasks
Request URL:
http://NUXEO_SERVER/nuxeo/api/v1/id/4246ca87-c076-4bf4-b62b-0bab9dd21102
Request Method: GET
Request Headers
...
Content-type: application/json
enrichers.document: pendingTasks
properties: 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": {
"pendingTasks": [{
"actors": [{
"id": "Administrator"
}],
"comments": [],
"created": "2016-05-28T22:00:00.12Z",
"directive": "wf.parallelDocumentReview.consolidate.directive",
"dueDate": "2016-06-02T22:00:00.12Z",
"entity-type": "task",
"id": "18b6767a-990e-4d7d-870c-ba20494fe3b6",
"name": "wf.parallelDocumentReview.consolidate.title",
"nodeName": "Task2169",
"state": "opened",
"targetDocumentIds": [{
"id": "d6b4be3e-e1e9-454b-812d-c156d1c2e96a"
}],
"taskInfo": {
...
},
"variables": {
"assignees": [],
"comment": null,
"review_result": ""
},
"workflowInstanceId": "75dfb9e0-65dd-4150-9d66-ade0597e27c2",
"workflowModelName": "ParallelDocumentReview"
}]
}
}
Contributing Your Own Content Enricher
You can add your own content enricher 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. It 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 is instantiated as a singleton
// Priority defines which marshaller is used in case of conflict. Priority is an integer.
// The higher the number, the higher the priority: 10 > 1 for instance.
@Setup(mode = SINGLETON, priority = REFERENCE)
public class ParentDocEnricher extends AbstractJsonEnricher<DocumentModel> {
// The enricher is called using enrichers.document: parentDoc
public static final String NAME = "parentDoc";
public ParentDocEnricher() {
super(NAME);
}
// Method that is called when the enricher is called
@Override
public void write(JsonGenerator jg, DocumentModel doc) throws IOException {
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
An example 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.getService(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:
enrichers.logEntry = sfLogEntry
{
"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": {
"favorites": {
"isFavorite": true
}
}
}
Learn More
- Watch the video Using Content Enrichers as part of the REST API course at Hyland University.
- Use Nuxeo CLI to bootstrap your Content Enricher.
- Test these content enrichers on your local instance with Nuxeo API Playground (see documentation to configure your local instance).
- Checkout the Nuxeo REST API explorer of your instance at
http://NUXEO_SERVER/nuxeo/api/v1/doc
.