Table of Contents
Nuxeo integrates the Restlet framework to provide an easy way to contribute new REST API on top of the platform.
The REST API provides an easy way to call Nuxeo services from an
external application. Even if REST is a very simple concept, we choose to
leverage an existing REST framework to provide an REST API on top of
Nuxeo. The selected framework is Restlets (http://www.restlet.org/) that
provides a lightweight and flexible REST framework. The Nuxeo REST
integration API (org.nuxeo.ecm.platform.ui.web.restAPI
)
provides:
A runtime service to contribute new restlets
Base classes for new restlets
A main servlet that handles the routing between restlets
An integration with the Nuxeo API and Seam context
To implement a restlet you simply have to implement the
Restlet
interface.
Nuxeo 5 defines 3 different types of restlets :
Stateless restlets
No integration with Seam and no state management. This is the original logic of Restlet.
You can use BaseStalessNuxeoRestlet
as
base class that provides helpers for accessing main services (like
the repository).
Seam-aware restlets
For restlet declared as Seam-aware, the Nuxeo Restlet servlet
initializes the Seam context before executing the restlet. Thanks to
this initialization your restlet can use injection
(@In
) to access the Seam context. This solution gives
you the possibility of using existing Seam components. You don't
have to use Service Platform API to access the service since you can
access Seam delegates for that.
You can use BaseNuxeoRestlet
that
provides helper API for error handling, security and URL
management.
Conversation-aware restlets
The are Seam restlets that are tied to a Seam conversation.
For these restlets, the Seam context initialization is done in order
to setup the current Conversation. Conversational restlets must be
called with a conversationId
as parameter.
Conversational restlet can be used if you need to access the current Seam context associated with a browser session. Typically this is what is used by the Firefox helper to upload files.
You can use BaseNuxeoRestlet
that
provides helper API for error handling, security and URL
management.
All restlets are bound to one or more URL patterns. These URLs
patterns are used by Nuxeo RestletServlet
to
determine which restlet needs to receive the call.
When defining URLs you can use {} to have parts of the URL that will be converted as parameters.
For example :
/{repo}/{docid}/{filename}/upload
will define a URL pattern with 4 parts and you will have access from withing your code to 3 parameters: repo, docId and filename.
These parameters can be used via Restlet API :
req.getAttributes().get("repo");
You can also access the standard GET/POST parameters via
req.getResourceRef().getQueryAsForm().getFirstValue("SomeParameter");
Contributing a new restlet is quite simple.
The first thing to do is to write a new restlet: you can either
implement the Restlet
Interface "by hand"
or just inherit from BaseNuxeoRestlet
or
BaseStatelessNuxeoRestet
.
Once your class is written, you need to contribute to the restlets
extension point exposed by
org.nuxeo.ecm.platform.ui.web.restAPI.service.PluggableRestletService
.
<?xml version="1.0"?> <component name="org.nuxeo.ecm.platform.ui.web.restAPI.contrib"> <extension target="org.nuxeo.ecm.platform.ui.web.restAPI.service.PluggableRestletService" point="restlets"> <restletPlugin name="upload" class="org.nuxeo.ecm.platform.ui.web.restAPI.UploadRestlet" enabled="true" useSeam="true" useConversation="false"> <urlPatterns> <urlPattern>/{repo}/{docid}/{filename}/upload</urlPattern> </urlPatterns> </restletPlugin> ...
The useSeam
and
useConversation
flags define how the Nuxeo Restlet
servlet will handle the call.
Nuxeo comes by default with very simple restlet that can be seen as samples.
The Browse restlet is a simple way to navigate into the repository via REST.
A typical call to list content of default repository would be : http://127.0.0.1:8080/nuxeo/restAPI/default/*/browse
If you need to browse the document 95ce52b2-6959-4afa-bc63-396096b376b4 a typical call would be : http://127.0.0.1:8080/nuxeo/restAPI/default/95ce52b2-6959-4afa-bc63-396096b376b4/browse
Typical output for this restlet would be:
<document title="2fbf878d-9c2f-42c6-acbb-ea339ce15615" type="Root" id="2fbf878d-9c2f-42c6-acbb-ea339ce15615" url="/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615"> <document title="Default domain" type="Domain" id="95ce52b2-6959-4afa-bc63-396096b376b4" url="/default/95ce52b2-6959-4afa-bc63-396096b376b4"/> </document>
This restlet uses Seam in order to have documentManager injected (this is not a need but rather a simple way of accessing the repository without using the Service API)
Browse restlet registration looks like this:
<restletPlugin name="browse" class="org.nuxeo.ecm.platform.ui.web.restAPI.BrowseRestlet" enabled="true" useSeam="true"> <urlPatterns> <urlPattern>/{repo}/{docid}/browse</urlPattern> </urlPatterns> </restletPlugin>
This restlet is a simple REST frontend on top of IO core service. This can be used to export a document or a document tree as XML.
A typical call would be :
http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/export
to export the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615 as XML
http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/export?format=ZIP
to export the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615 as a ZIP archive
http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/exportTree
to export the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615 and all its children as a Zip Archive
http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/exportTree?format=XML
to export the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615 and all its children as XML
This restlet uses Seam in order to have documentManager injected (this is not a need but rather a simple way of accessing the repository without using the Service API)
Export restlet registration looks like this:
<restletPlugin name="export" class="org.nuxeo.ecm.platform.ui.web.restAPI.ExportRestlet" enabled="true" useSeam="true"> <urlPatterns> <urlPattern>/{repo}/{docid}/export</urlPattern> <urlPattern>/{repo}/{docid}/exportSingle</urlPattern> <urlPattern>/{repo}/{docid}/exportTree</urlPattern> </urlPatterns> </restletPlugin>
This restlet provide a REST API for Lock Management.
A typical call would be:
GET http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/Locking/status
to get Lock status of the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615
GET http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/Locking/lock
or
LOCK http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/Locking
to Lock status the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615
GET http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/Locking/unlock
or
UNLOCK http://127.0.0.1:8080/nuxeo/restAPI/default/2fbf878d-9c2f-42c6-acbb-ea339ce15615/Locking
to Unlock status the document 2fbf878d-9c2f-42c6-acbb-ea339ce15615
This restlet is stateless and uses Nuxeo Service API
Lock restlet registration looks like this
<restletPlugin name="locking" class="org.nuxeo.ecm.platform.ui.web.restAPI.LockingRestlet" enabled="true" useSeam="false" useConversation="false"> <urlPatterns> <urlPattern>/{repo}/{docid}/Locking</urlPattern> </urlPatterns> </restletPlugin>
This restlet provides a REST API for file upload that is used by the Firefox helper.
A typical call would be:
POST http://127.0.0.1:8080/nuxeo/restAPI/default/e5125b5e-8b9e-43bd-8959-7e7e5caf2a1b/pluginUpload/myfolder/myfile
to upload a file
This restlet uses Seam conversation.
pluginUpload restlet registration looks like this
<restletPlugin name="pluginUpload" class="org.nuxeo.ecm.platform.ui.web.restAPI.PluginUploadRestlet" enabled="true" useSeam="true" useConversation="true"> <urlPatterns> <urlPattern>/{repo}/{docid}/pluginUpload</urlPattern> </urlPatterns> </restletPlugin>
The RestPack is an additional component for Nuxeo EP that provides additional restlets on top of Nuxeo Services.
The primary goal of the RestPack is to provide the needed RestAPI to build simple JSR168 portlets (like search portlets) that communicate with Nuxeo via HTTP/XML.
You can download the RestPack from Nuxeo download site or build it from source.
To deploy the module, just copy the jar file in nuxeo.ear/system folder and restart you JBoss
The Vocabulary restlet exports as XML the content of a given vocabulary
Sample call :
GET http://127.0.0.1:8080/nuxeo/restAPI/vocabulary/{vocName}/
parameters
{vocName}
Name of the vocabulary to export, must be last part of QueryPath
lang
GET (QueryString) parameter used to set language used to generate the labels
Sample calls
http://127.0.0.1:8080/nuxeo/restAPI/vocabulary/subject?lang=en
<entries> <entry id="arts" label="label.directories.subject.arts" translatedLabel="Arts"/> <entry id="business" label="label.directories.subject.business" translatedLabel="Business"/> <entry id="computers" label="label.directories.subject.computers" translatedLabel="Computers"/> ...
http://127.0.0.1:8080/nuxeo/restAPI/vocabulary/continent_country?lang=en
<entries> <entry id="africa" label="label.directories.continent.africa" translatedLabel="Africa"> <entry id="Algeria" label="label.directories.country.Algeria" translatedLabel="Algeria" parent="africa"/> <entry id="Angola" label="label.directories.country.Angola" translatedLabel="Angola" parent="africa"/> <entry id="Benin" label="label.directories.country.Benin" translatedLabel="Benin" parent="africa"/> <entry id="Botswana" label="label.directories.country.Botswana" translatedLabel="Botswana" parent="africa"/> <entry id="Burkina_Faso" label="label.directories.country.Burkina_Faso" translatedLabel="Burkina Faso" parent="africa"/> <entry id="Burundi" label="label.directories.country.Burundi" translatedLabel="Burundi" parent="africa"/> <entry id="Cameroon" label="label.directories.country.Cameroon" translatedLabel="Cameroon" parent="africa"/> ...
Export as RSS or ATOM the list of children document of the targeted container
Sample call:
http://127.0.0.1:8080/nuxeo/restAPI/{repoId}/{docId}/{format}
Parameters:
{repoId}
Name of the target repository (use default on a standard installation)
{docId}
DocumentRef of the target container (use the docId present in the standard nuxeo URL when browsing the webapp)
{format}
Defines the syndication format: rss or atom
Export user's workflow tasks as XML or ATOM
Sample call:
http://127.0.0.1:8080/nuxeo/restAPI/workflowTasks/{repoId}/?format=XML/ATOM
Parameters:
{repoId}
Name of the target repository (use default on a standard installation)
format
Defines the export format: xml or atom
Sample call:
http://127.0.0.1:8080/nuxeo/restAPI/workflowTasks/default/?format=xml
<nxt:tasks> <nxt:category category="None"> <nxt:task name="review" workflowType="document_review_approbation" author="Administrator" startDate="2007-10-09 11:10:41"/> </nxt:category> </nxt:tasks>
Export user's workflow tasks that match the query as XML or ATOM
Sample call:
http://127.0.0.1:8080/nuxeo/restAPI/queryForWorkflowTask/{repoId}/?format=XML/ATOM&workflowRequest=author&comparisonType=0/1&workItemFromUser=true/false&canManage=true/false
Parameters:
{repoId}
Name of the target repository (use default on a standard installation)
format
Defines the export format: xml or atom
workflowRequest
Defines the workflow item attribute to compare for the query. Please refer to the WorkItem Filter.
comparisonType
Defines the type of comparison. Please refer to the WorkItem Filter.
workItemFromUser
If is true add filter that match WorkItem initiated by the user
canManage
If true add filter that match workItems that the participant has a direct action to perform
Sample call:
http://127.0.0.1:8080/nuxeo/restAPI/workflowTasks/default/?format=xml
<nxt:tasks> <nxt:category category="None"> <nxt:task name="review" workflowType="document_review_approbation" author="Administrator" startDate="2007-10-09 11:10:41"/> </nxt:category> </nxt:tasks>
http://localhost:8080/nuxeo/restAPI/queryForWorkflowTask/default/?workflowRequest=author&comparisonType=0&workItemFromUser=true
Get work item tasks that the user initiate and is pending for the next user.
Execute a search via QueryModel and returns DocumenList as XML/RSS/ATOM/JSON
Sample call :
http://127.0.0.1:8080/nuxeo/restAPI/execQueryModel/{queryModelName}
Parameters:
{queryModelName}
Name of the QueryModel to execute
format
Defines the export format: XML, Atom, RSS or JSON. This parameter is set as a QueryString parameter
page
Defines the page number you want in the result. This parameter is set as a QueryString parameter
ascending
Defines ordering ascending: true/false. This parameter is set as a QueryString parameter
criteria
Defines ordering columns used for sorting. This parameter is set as a QueryString parameter
columns
Defines the columns you want to be included in the resultset. This parameter is set as a QueryString parameter
This parameter is a simple string containing schema.fieldName tokens separated by "," . The only special field is url. Default value is : dublincore.title,dublincore.description,url
QueryModel parameters
For stateless QueryModels, you have to specify the parameters via QP1, QP2 ... (only ordering is important)
The value $USER is automatically replaced by the name of the current User :
http://127.0.0.1:8080/nuxeo/restAPI/execQueryModel/USER_DOCUMENTS?QP1=$USER
For stateful QueryModels, you have to specify the parameters as fieldName=FieldValue
Sample call:
http://127.0.0.1:8080/nuxeo/restAPI/execQueryModel/USER_DOCUMENTS?QP1=$USER&format=JSON
[ { "title": "nouveau-fichier", "description": null, "url": "nxdoc/default/452c122d-07de-422b-b448-b0fef9534a62/view_documents", "id": "452c122d-07de-422b-b448-b0fef9534a62" }, { "title": "Setup", "description": null, "url": "nxdoc/default/ae03f7bf-9967-4b5b-b37b-807fd40a6ec7/view_documents", "id": "ae03f7bf-9967-4b5b-b37b-807fd40a6ec7" }, { "title": "cps", "description": null, "url": "nxdoc/default/2bad93ca-188f-4ea0-a585-9540a6ed6581/view_documents", "id": "2bad93ca-188f-4ea0-a585-9540a6ed6581" }, { "title": "testMe", "description": null, "url": "nxdoc/default/e4de81a9-95e8-49ff-9146-e020f99b8bb8/view_documents", "id": "e4de81a9-95e8-49ff-9146-e020f99b8bb8" } ... ]
http://127.0.0.1:8080/nuxeo/restAPI/execQueryModel/USER_DOCUMENTS?QP1=$USER&format=XML&page=1
<results> <pages pages="3" pageNumber="1"/> <document id="a3154f03-6baa-4d7d-8bac-579d52a8d304" title="ssl-uil2-service" url="nxdoc/default/a3154f03-6baa-4d7d-8bac-579d52a8d304/view_documents"/> <document id="e2b26d9a-9140-44f1-ae23-4ad7866911c0" title="build" url="nxdoc/default/e2b26d9a-9140-44f1-ae23-4ad7866911c0/view_documents"/> <document id="bf7de6df-bca1-4d29-8e26-5019ced696fd" title="jboss-service" url="nxdoc/default/bf7de6df-bca1-4d29-8e26-5019ced696fd/view_documents"/> <document id="439a11e8-642d-41f7-ae0f-4ef4d7303d79" title="postgres-jdbc2-service" url="nxdoc/default/439a11e8-642d-41f7-ae0f-4ef4d7303d79/view_documents"/> <document id="467745db-565d-4350-953f-b2fa03733406" title="oil-service" url="nxdoc/default/467745db-565d-4350-953f-b2fa03733406/view_documents"/> <document id="44a2441e-e265-4fee-ad17-9ec24245cccf" title="jbossmq-state" url="nxdoc/default/44a2441e-e265-4fee-ad17-9ec24245cccf/view_documents"/> <document id="8d7e3077-a3be-4d6c-806c-aa97816821e2" title="oracle-jdbc2-service" url="nxdoc/default/8d7e3077-a3be-4d6c-806c-aa97816821e2/view_documents"/> <document id="b431ad04-3439-441e-826b-48b5f0f0c1c8" title="as400-jdbc2-service" url="nxdoc/default/b431ad04-3439-441e-826b-48b5f0f0c1c8/view_documents"/> <document id="e146c6b2-a315-4788-9bbe-5f1fc79c18ac" title="mssql-jdbc2-service" url="nxdoc/default/e146c6b2-a315-4788-9bbe-5f1fc79c18ac/view_documents"/> <document id="b109a672-5ebd-4a01-8a86-79e2430c2f07" title="file-state-service" url="nxdoc/default/b109a672-5ebd-4a01-8a86-79e2430c2f07/view_documents"/> </results>
http://127.0.0.1:8080/nuxeo/restAPI/execQueryModel/USER_DOCUMENTS?QP1=$USER&format=XML&page=1&columns=common.icon,dublincore.title,dublincore.description
<results> <pages pages="3" pageNumber="1"/> <document id="a3154f03-6baa-4d7d-8bac-579d52a8d304" icon="/icons/note.gif" title="ssl-uil2-service"/> <document id="e2b26d9a-9140-44f1-ae23-4ad7866911c0" icon="/icons/note.gif" title="build"/> <document id="bf7de6df-bca1-4d29-8e26-5019ced696fd" icon="/icons/note.gif" title="jboss-service"/> <document id="439a11e8-642d-41f7-ae0f-4ef4d7303d79" icon="/icons/note.gif" title="postgres-jdbc2-service"/> <document id="467745db-565d-4350-953f-b2fa03733406" icon="/icons/note.gif" title="oil-service"/> <document id="44a2441e-e265-4fee-ad17-9ec24245cccf" icon="/icons/note.gif" title="jbossmq-state"/> <document id="8d7e3077-a3be-4d6c-806c-aa97816821e2" icon="/icons/note.gif" title="oracle-jdbc2-service"/> <document id="b431ad04-3439-441e-826b-48b5f0f0c1c8" icon="/icons/note.gif" title="as400-jdbc2-service"/> <document id="e146c6b2-a315-4788-9bbe-5f1fc79c18ac" icon="/icons/note.gif" title="mssql-jdbc2-service"/> <document id="b109a672-5ebd-4a01-8a86-79e2430c2f07" icon="/icons/note.gif" title="file-state-service"/> </results>
WebEngine is a new way to develop Restlets inside Nuxeo using the new specification JAX-RS.
Several restlets powered by WebEngine are already available, lets look at http://doc.nuxeo.org/xwiki/bin/view/Main/WebEngineTutorial to learn how to use them.