Implementing Operation
(Mandatory implementation)
Implement the com.boomi.connector.api.Operation interface (refer to Javadocs) for a connector to execute the defined action (corresponding to the connector operation type) against the service.
The Operation implementation runs the Connector operation on a service. The operation is processed when you execute the Connector Shape in a process. The semantics of each operation will vary, but generally, the documents provided to the operation pass into the Connector Shape as input, and the operation responds to every input.
The Operation implementations need not be thread safe.
The Connector SDK artifacts from the public repository contain a connector-sdk-samples-sources JAR file containing source code for some connector samples you can reference when building a connector. You will find sample JSON Operation classes, sample Listener classes, and more. Refer to the Connector SDK artifacts topic for more information.
Code Sample
This code sample illustrates the implementation of the Update operation.
Code sample for a basic Operation
package com.boomi.connector.sdk.edu;
import java.util.Date;
import com.boomi.connector.api.ObjectData;
import com.boomi.connector.api.OperationContext;
import com.boomi.connector.api.OperationResponse;
import com.boomi.connector.api.OperationStatus;
import com.boomi.connector.api.Payload;
import com.boomi.connector.api.PayloadUtil;
import com.boomi.connector.api.UpdateRequest;
import com.boomi.connector.util.BaseUpdateOperation;
/*
* This code defines a class `SampleExecuteOperation` that extends `BaseUpdateOperation`.
* It has three private fields `_connectionId`, `_operationId`, and `_includePayload`.
* The constructor initializes these fields using properties from the `OperationContext`.
*/
public class SampleExecuteOperation extends BaseUpdateOperation {
private final String _connectionId;
private final String _operationId;
private final boolean _includePayload;
protected SampleExecuteOperation(OperationContext context) {
super(context);
_connectionId = context.getConnectionProperties().getProperty("id");
_operationId = context.getOperationProperties().getProperty("id");
_includePayload = context.getOperationProperties().getBooleanProperty("includePayload", false);
}
/*
* The `executeUpdate` method logs the connection id and operation id, processes each input object in the request,
* and adds a result to the response with a success status, message, and optional payload based on the `_includePayload` flag.
*/
@Override
protected void executeUpdate(UpdateRequest request, OperationResponse response) {
response.getLogger().info("connection id: " + _connectionId);
for (ObjectData input : request) {
input.getLogger().info("operation id: " + _operationId);
Payload payload = (_includePayload ? PayloadUtil.toPayload(new Date().toString()) : null);
response.addResult(input, OperationStatus.SUCCESS, "200", "great success!", payload);
}
}
}
Supported operations (Actions)
Connector actions represent the base operations executed on the resources located in the application endpoint. Boomi recommends that these actions names are verbs. Examples of Action names are Create, Retrieve, Update, etc.
Ensure that you mention all connector actions in title case, except for the LISTEN action, which must be in uppercase.
Depending on the service’s API, you can implement some or all of the following types of operations in a connector:
-
Get — retrieves an object from the service based on an object ID. Get requests are commonly used to test for an object's existence, and hence, a request for an object that does not exist should return an "empty" success instead of a failure.
-
Create — creates a new object in the service.
-
Update — updates an existing object in the service.
-
Upsert — a combination of Update/Insert that either updates an object if it exists or creates a new object if it does not.
-
LISTEN — listens for and retrieves messages from a message queue.
-
Delete — deletes objects from the service based on an object ID.
-
Query — retrieves objects from the service based on user-defined search criteria.
All operations support field selection so you can designate the fields returned in the response. To learn how to add field selection annotation to your schemas, refer to Query operation field selection, filtering, and sorting topic.
Configuring connector-descriptor.xml file
You must configure the required operation types in your connector-descriptor.xml file to appear in your connector on the Boomi Enterprise Platform.
Example: Connector actions configuration
connector-descriptor.xml configuration
<?xml version="1.0" encoding="UTF-8"?>
<GenericConnectorDescriptor
dateTimeFormat="yyyy-MM-dd'T'HH:mm:ss.SSSZZ"
requireConnectionForBrowse="true">
<field />
<field />
...
<operation types="EXECUTE" customTypeId="GET" customTypeLabel="Get"> ... </operation>
<operation types="QUERY" allowFieldSelection="true" fieldSelectionLevels="10" fieldSelectionNone="true"> ... </operation>
<operation types="EXECUTE" customTypeId="POST" customTypeLabel="Create"> ... </operation>
<operation types="EXECUTE" customTypeId="PATCH" customTypeLabel="Update/Patch/Merge"> ... </operation>
<operation types="EXECUTE" customTypeId="DELETE" customTypeLabel="Delete"> ... </operation>
</GenericConnectorDescriptor>
How it appears on the Boomi Enterprise Platform

Operation responses
Connector operations receive input documents as tracked data and must add a result to each document's OperationResponse instance.
Adding a result to an input document
There are various methods in OperationResponse to add a result to an input document.
addResult(),addPartialResult(), andaddCombinedResult()accept a payload that becomes the output document for the specified input.addEmptyResult()andaddErrorResult()do not generate any output documents.
Operations can receive multiple input documents that need to be processed, and a single input document can generate multiple output documents. The number of input and output documents depends on the operation.
Operations receiving single and multiple input documents
Some operations (Get, Query) only receive a single input document. If multiple documents pass to a connector shape for one of these operations, each document invokes a corresponding execute method (executeGet, executeQuery) separately. All other operations can receive multiple documents.
You can invoke the execute methods for operations only once, even if multiple documents pass into the connector. The operation request instance (UpdateRequest, DeleteRequest) passed to these methods can be iterated multiple times to access all documents.
The operation must process all the documents. Failure of one document does not mean the other documents have also failed.
Operations generating single and multiple output documents
Certain operations (Get, Create, Update, Upsert, Delete) typically only generate a single output document for each input document. You can accomplish this using the addResult method.
Other operations (Query, Execute) often generate multiple output documents for a single input document. You can accomplish this using the addPartialResult method. This method must have a payload for each output document. After adding all the output documents, you must call the finishPartialResult for each input document.
While you can return multiple documents for one of the single output operations, avoid doing so, as it is a sign that the operation is misused. When you want to reuse the same output document for several input documents, use the addCombinedResult method instead of making multiple calls to addResult.
You can invoke a connector operation with "zero" documents. But remember that the scope of this issue goes beyond a single connector, and you cannot expect connectors to guard against it.
Operation status
When adding a result to the operation response, you must assign an operation status.
-
SUCCESS — This status indicates a successful operation execution for a document and is assigned for the following common use cases:
- Any successful operation.
- A GET operation that fails because the ID does not exist.
noteThis may not honor the intent of the underlying system, but should be strictly followed for consistency within the platform.
- A DELETE operation where the ID does not exist, but the underlying system does not return an error.
-
FAILURE — This status indicates a document-related failure which is unknown or some indication of a communication failure with the underlying service. For example, an authentication failure or a network failure. Also use this when your connector cannot communicate with the underlying service.
-
APPLICATION_ERROR — This status indicates a document-related failure where communication with the service was successful, but the document cannot be processed for some reason. For example, the document is in the incorrect format or is missing required information. This status is assigned for the following common use cases:
-
The system returns an error.
-
The system does not return a response but one is expected/required.
-
The system returns a response but it is not in the expected format and cannot be processed.
-
The input document is formatted incorrectly or is missing required information.
noteThis assumes that up-front validation of the document was required, includes Query filters, and when a payload is not required if no call is made to the underlying system.
-
A DELETE operation where the ID does not exist and the underlying system returns an error.
-
Get
The Get operation allows retrieving objects and records, downloading and reading files, etc.
Example: Implementing Get Operation
// This code defines a Java class named `SampleGetOperation` that extends `BaseGetOperation`.
// It overrides the `executeGet` method to log information, retrieve an object ID from the request,
// and add an empty result to the response with a success status and message.
public class SampleGetOperation extends BaseGetOperation {
protected SampleGetOperation(OperationContext context) {
super(context);
}
@Override
protected void executeGet(GetRequest request, OperationResponse response) {
response.getLogger().info("Shared Field: " + getContext().getOperationProperties().getProperty("shared"));
ObjectIdData input = request.getObjectId();
input.getLogger().info(getContext().getObjectTypeId() + ":" + input.getObjectId());
response.addEmptyResult(input, OperationStatus.SUCCESS, "404", "not found");
}
}
Create
The Create operation allows the creation of objects and folders, uploading documents and files, and inserting data into an account.
Example: Create operation
//This code defines a class `SampleExecuteOperation` that extends `BaseUpdateOperation`.
//It has three private fields `_connectionId`, `_operationId`, and `_includePayload`.
//The constructor initializes these fields using the `OperationContext` properties.
//The `executeUpdate` method logs the connection id and operation id, then iterates over input objects in a request, logs the operation id for each object, creates a payload if `_includePayload` is true, and adds a result to the response with a success status and optional payload.
//The `createPayload` method generates a payload based on the object
public class SampleExecuteOperation extends BaseUpdateOperation {
private final String _connectionId;
private final String _operationId;
private final boolean _includePayload;
protected SampleExecuteOperation(OperationContext context) {
super(context);
_connectionId = context.getConnectionProperties().getProperty("id");
_operationId = context.getOperationProperties().getProperty("id");
_includePayload = context.getOperationProperties().getBooleanProperty("includePayload", false);
}
@Override
protected void executeUpdate(UpdateRequest request, OperationResponse response) {
response.getLogger().info("connection id: " + _connectionId);
for (ObjectData input : request) {
input.getLogger().info("operation id: " + _operationId);
Payload payload = (_includePayload ? createPayload() : null);
response.addResult(input, OperationStatus.SUCCESS, "200", "great succues!", payload);
}
}
private Payload createPayload() {
return PayloadUtil.toPayload(getContext().getObjectTypeId() + ":" + new Date().toString());
}
}
Update
The Update operation allows the updating of objects, records, and data.
Example: Implementing Update operation
// This code is defining a class `ExampleUpdateOperation` that extends `BaseUpdateOperation`.
// It contains a constructor that takes an `ExampleConnection` object as a parameter and
// calls the superclass constructor with this connection object.
public class ExampleUpdateOperation extends BaseUpdateOperation
{
public ExampleUpdateOperation(ExampleConnection conn)
{
super(conn);
}
@Override
protected void executeUpdate(UpdateRequest request, OperationResponse response)
{
// ... get user credentials (same as GET example) ...
for(ObjectData requestData : request) {
// ... parse objectId from request data ...
String objectId = ...;
String requestUrl = "http://www.example.com/service/type/" +
getContext().getObjectTypeId() + "/value/" + objectId;
// ... Make POST request to requestUrl using given credentials ...
// ... grab returned status code ...
int httpStatusCode = ...;
// indicate status of the operation
OperationStatus status = ((httpStatusCode == HttpURLConnection.HTTP_OK) ?
OperationStatus.SUCCESS : OperationStatus.FAILURE);
response.addEmptyResult(requestData, status, String.valueOf(httpStatusCode), null);
}
}
@Override
public ExampleConnection getConnection()
{
return (ExampleConnection) super.getConnection();
}
}