Nuxeo Java Client uses several libraries:
- Retrofit and OkHttp to perform HTTP requests.
- Jackson to serialize/deserialize requests/responses
- Guava to cache responses (optional)
The basic flow when you perform a request to Nuxeo Server from Nuxeo Java Client looks like this:
To ease usage and configuration of client we added several notions/objects.
Builder is the entry point of Nuxeo Java Client. It is used to create the client, validate the needed configuration and test connection to Nuxeo Server. After calling
Builder#connect(), you'll get a working
NuxeoClient owning the current user used for further requests.
NuxeoClient is the base client's class. It allows to get managers and to perform arbitrary HTTP request with client configuration. It also owns the cache, the converter factory, the server version and the current user performing requests.
Managers are created each time you get them, we're gonna see why in configuration isolation section.
Cache is given to NuxeoClient during creation with
Converter factory is created during
The server version is fetched from Nuxeo Server in a lazy way. Client will get this information by requesting
Current user is retrieved during
Managers own a set of Nuxeo Server API, for example
UserManager manager owns API to handle user and group. Every manager offers a sync and an async version for each API, the async version leverages
Callback Retrofit class.
Under the hood, they hold the bridge between Nuxeo Java Client API and Retrofit API.
Every sent/received object in Nuxeo Java Client extends one of these types:
Entityfor objects without connectivity needs
ConnectableEntityfor objects with connectivity needs
They both offer a
getEntityType method and handle
entity-type read/write in JSON (used for serialization/deserialization needs).
There're other types for object consume/produce by the client:
Connectableinterface for objects with connectivity needs or holding sub objects with connectivity needs
Entitiesclass for objects holding a list of entities
PaginableEntityclass for objects with pagination capabilities
Let's see each type in detail:
Entityis a basic java class with entity type capabilities.
ConnectableEntityhas the entity type capabilities, implement
Connectableinterface and provide access to client and Retrofit API objects (in order to execute requests). A connectable entity is able to execute requests if object is handle by client. For example,
Documentis a connectable entity, which gives convenient methods:
Document root = nuxeoClient.repository().fetchDocumentRoot(); // here we leverage ConnectableEntity's capabilities Documents children = root.fetchChildren();
Connectableinterface is mainly used to handle connectable entity. Every class implementing this interface and returned by the client will receive a call to
reconnectWith(NuxeoClient)after post treatments. This allows to give client to connectable entity, to reconnect children in collection objects (such as Documents, Users, ...).
Entitiesis an entity with some useful API to handle container such as directories, tasks, workflows, comments...
PaginableEntityis an entity with extra fields for pagination information (such as totalSize, pageIndex, pageCount, isNextPageAvailable, ...). This is mainly used for documents on query API for instance.
Nuxeo Java Client uses some constants internally, we make some of them free to use:
ConstantsV1owning default values for Nuxeo REST API v1
HttpHeadersowning HTTP headers for Nuxeo REST API usage
MediaTypesowning common media types
Operationsowning common Nuxeo operation ids
All serialization/deserialization are made by
NuxeoResponseConverter leveraging Jackson. They are managed by Retrofit and created for each request/response.
Serialization is pretty simple and use Jackson marshalling capabilities.
Deserialization first checks if the return type is given by Retrofit, if so we unmarshall response with this type. If not, we read
entity-type field in the response, get type from registered types and finally unmarshall response. You can register your own entity types with
Nuxeo Java Client offers a built-in cache mechanism relying on
NuxeoResponseCache interface. We provide one implementation based on Guava in
Only GET requests are cached.
You can clean the cache with
Depending on configuration type, you can configure your clients at different moment:
- during creation with
- during use with
- during use with managers - access specific manager configuration
The three kinds of configuration holders all have the common part of configuration.
Builder owns connection, authentication, cache, serialization and common configuration because they are not supposed to change during client life.
NuxeoClient owns only common configuration.
Managers own common and specific configuration, for instance,
Operation owns the
voidOperation configuration besides common ones.
The manager configuration is isolated from the client one.
This means that each configuration made on a manager belongs to this manager instance. For instance:
Repository repository1 = client.repository().schemas("*"); Repository repository2 = client.repository().schemas("dc"); // document containing all schemas Document doc1 = repository1.fetchDocumentRoot(); // document containing only dublincore Document doc2 = repository2.fetchDocumentRoot();
|timeout(long)||Configure connect and read timeout, unit is seconds|
|connectTimeout(long)||Configure connect timeout, unit is seconds|
|readTimeout(long)||Configure read timeout, unit is seconds|
|header(String, boolean)||Replace header of a given name with given value|
|header(String, int, int...)||Replace header of a given name with given values|
|header(boolean, String, int, int...)||Replace or append header of a given name with given values|
|header(String, Serializable, Serializable...)||Replace header of a given name with given values|
|header(boolean, String, Serializable, Serializable...)||Replace or append header of a given name with given values|
|header(String, String, String...)||Replace header of a given name with given values|
|header(boolean, String, String, String...)||Replace or append header of a given name with given values|
|transactionTimeout(long)||Configure transaction timeout on Nuxeo Server|
|enrichers(boolean, String, String, String...)||Replace or append enricher of given type with given values|
|enrichers(String, String, String...)||Replace enricher of given type with given values|
|enrichersForDocument(String, String...)||Replace enricher for document with given values|
|fetchProperties(boolean, String, String, String...)||Replace or append fetch properties of given type with given values|
|fetchProperties(String, String, String...)||Replace fetch properties of given type with given values|
|fetchPropertiesForDocument(String, String...)||Replace fetch properties for document with given values|
|fetchPropertiesForGroup(String, String...)||Replace fetch properties for group with given values|
|depth(String)||Replace the depth header with given value, possible values are
|version(String)||Replace the set versioning option header with given value|
|schemas(boolean, String, String...)||Replace or append schemas to fetch with given values,
|schemas(String, String...)||Replace schemas to fetch with given values,
|authentication(String, String)||Configure basic authentication with user/password|
|authentication(Interceptor)||Configure another kind of authentication|
|cache(NuxeoResponseCache)||Configure a cache for client|
|interceptor(Interceptor)||Add a new OkHttp interceptor|
|registerEntity(String, Class<?>)||Register a new entity type in client marshalling system|
|url(String)||The Nuxeo Server URL|
You must configure authentication and URL at least.
|voidOperation()||Set void operation header for next operation calls on this manager|
Basic example on client:
NuxeoClient client = client.schemas("*") .connectTimeout(30) .readTimeout(60) .header(HttpHeaders.NX_ES_SYNC, true) // same effect than transactionTimeout(long) .header(HttpHeaders.NUXEO_TX_TIMEOUT, 300) .header("source", "FROM_JAVA_CLIENT");
Example on repository manager, configuration will affect only this repository instance:
Repository repository = client.repository() .enrichersForDocument("thumbnail", "breadcrumb") .fetchPropertiesForDocument("dc:creator"); Document doc = repository.fetchDocumentByPath("/default-domain"); User creator = doc.getPropertyValue("dc:creator"); // we get an User object because of fetchProperties Documents breadcrumb = doc.getContextParameter("breadcrumb");