Content Automation is a Nuxeo service that exposes common actions you do on a Nuxeo application as atomic operations so that one can assemble them to create complex business rules and logic, without writing any Java code.
In other words, content automation provides a high level API over Nuxeo services - an API made of operations that can be assembled in complex automation chains (or macro operations). These operations can be called locally in Java, or remotely as being exposed via the REST API.The main goal of automation is to enable end users to rapidly build complex business logic without writing any Java code — just by assembling the built-in set of atomic operations into complex chains and then plugging these chains inside Nuxeo as UI actions, event handlers, REST bindings, etc.
You can also create new atomic operations (write a Java class that defines an operation) and contribute them to the set of built-in operations. To define an automation chain, you just need to write an XML contribution that describes the chain by listing each operation in the chain along with the parameter values that will be used to execute the operation. Since 5.7.2, you can define parameters for this chain, injected into the automation context to be fetched at execution time. If you need to define dynamic operation parameters (whose value will be computed at runtime when the operation is executed) you can use scripting (e.g. EL syntax) to fetch the actual parameter value at execution time.
What is an Operation?
From an end-user point of view: an operation is an action that can be triggered by the user either directly through the user interface, or by responding to an event, or by a REST call to a remote server.
The operations an user can invoke usually deal with the document repository (like creating or updating documents), but they can also do some other tasks like sending emails, converting blobs, etc.
The automation service already provides tens of frequent operations that you may need to build your business logic. More operations can be contributed using a Nuxeo extension point. This involves of course writing the right Java code to implement the operation logic.
From a developer point of view: an operation is a Java class annotated using the right annotations and providing a one or more methods that are doing the actual work.
For more information about how to write and contribute a new operation, see Contributing an operation.
What is an Automation Chain?
The power of operations is that operations can be chained into a sort of macro operation that is composed of atomic operations and which executes each operation in turn by using an operation output as the input of the next operation. This way you can for example construct an automation chain that creates a document, then attaches a blob to the document, then publishes it and so on. Each operation in the chain does the required step by working on the input of the previous operation and when finished outputs a result that will be used by the next operation as its input.
Since 5.7.2, all chains can contain parameters as operation to be used from the automation context along their execution.
This is called in Nuxeo Automation an automation chain. Automation chains give you the possibility to build complex business logic only by assembling atomic operations that are provided by the server. Thus, you can script your business logic using automation chains which, thank to Nuxeo Studio, can be done by using drag and drop (without coding anything or even writing XML extension files).
If you are a developer and don't want to use Contributing an Automation Chain page to see how you can define and contribute a new operation chain using Nuxeo extension points., you can check the
Working with Operations
This section is more about how operations work and how they can be chained to obtain working automation chains.
We've seen that an operation works on an input object by doing something (like updating this object or creating new objects) and at the end it outputs the operation result. When you are constructing a chain of operations, this result will be used as the input of the next operation. The last output in the chain will be the output of the chain itself. As you noticed, an operation works on an input so you should provide an initial input to start an operation (or an operation chain).
More, as there is an Run Chain atomic operation which takes as the argument the name of the chain to execute, you can create very complex chains that can call sub-chains to execute some particular steps in the chain.
In a chain, every operation has a cause and an effect. The effect of one operation in a chain is the cause of the next event. The initial cause is the user action (doing something with a document for example), the final effect is what the chain is assumed to do.
An atomic operation can be viewed as a finite automation chain with an initial cause (the action that triggered it) and having the effect of the execution of the operation itself. This way you can chain as many causes and effects you want. You can actually create your ECM universe using operations.
Now, let's discuss about the bricks that compose an operation:
- An operation has an input (provided by the cause).
- An operation may have zero or more parameters (used to parametrize the way an operation is behaving).
- An operation has an output (that can be used by the next operation in the chain as the input).
The Operation Input
The operation input can be a Document or a Blob (i.e. a file).
The input is provided by the execution context, either by getting the input from the user action (in the case of a single operation or for the first operation in the chain), or from the output of the previous operation when executing a chain.
There are some special operations that don't need any input. For example you may want to run a query in the repository. In this case, you don't need an input for your query operation. Thus, operations can accept void inputs (or nothing as input). To pass a void input to an operation, just use a null value as the input. If an operation doesn't expect any input (i.e, void input) and an input is given, the input will be ignored.
The Operation Parameters
An operation can define parameters to be able to modify its execution at runtime depending on those parameter values.
Any parameter value can be expressed as a string. The string will be converted to the right type at runtime if possible. If not possible an exception is thrown.
There are several types of predefined parameters:
- string: any string,
- boolean: a boolean parameter,
- integer: an integer number,
- float: a floating point number,
- date: a date (in W3C format if is specified as a string),
- resource: an URL to a resource,
- properties: a Java properties content (key=value pairs separated by new lines),
- document: a Nuxeo Document (use its absolute PATH or its UID when expressing it as a string),
- blob: a Nuxeo blob (the raw content of the blob in the case of a REST invocation),
- documents: a list of documents,
- bloblist: a list of blobs,
- any other object that is convertible from a string: you can register new object converters trough the
adaptersextension point of the
an expression: this represents a MVEL expression (which is compatible with basic EL expressions) that can output dynamic values. When using expressions you must prepend it with the prefix _expr:_.
For the complete list of objects and functions available in an expression, see Nuxeo Studio.
an expression template: this is the same as an expression but it will be interpreted as a string (by doing variable substitution). This is very useful when you want to create expressions like this:
mytitleis a variable name that will be substituted with its string form.
You can notice that you still need to prepend your template string with an
The Operation Output
The operation output is either a Document, a Blob or void (as the input).
In some rare cases you may want your operation to not return anything (a void operation). For example your operation may send an email without returning anything. When an operation is returning void (i.e. nothing), then a null Java object will be returned .
As said before, the output of an operation is the input of the next operation when running in a chain.
Contributing New Input/Output Types
Since 5.4.2, you can extend the input/output types by contributing the new marshalling logic to automation.
Marshalling and operation binding logic is selected client and server side using the JSON type name. At this stage, we're always using the Java type simple name in lowercase. This makes the operation binding logic being happy.
The logic you need to provide is as follow :
- the JSON type name,
- the POJO class,
- a writing method that puts data extracted from the POJO object into the JSON object,
- a reading method that gets data from the JSON object and builds a POJO object from it,
- a reference builder that extracts the server reference from a POJO object,
- a reference resolver that provides access to a POJO object giving a server reference.
Server and client do not share classes, so you need to provide two marshalling implementation class.
Server side, you should provide a codec. The implementation class is to be contributed to the automation server component using the
codecs extension point.
MyObjectCodec class should extend
org.nuxeo.ecm.automation.server.jaxrs.io.ObjectCodec . Most common codecs provided by default into Nuxeo server are implemented into
Client side, you should implement the
org.nuxeo.ecm.automation.client.jaxrs.spi.JsonMarshaller<T> interface. The implementation class is to be registered to the automation client marshalling framework by invoking the static method
Here is an example of the org.nuxeo.ecm.automation.client.jaxrs.spi.marshallers.BooleanMarshaller.
Using Scripting Expression in Operations
Operations can be parametrized using MVEL scripting expressions. For more details about scripting you can look at Use of MVEL in Automation Chains.
Related topics in this documentation