This content is dedicated to our next version. It is work in progress: its content will evolve until the new version is released.

Before that time, it cannot be considered as official.

Create a connector using the connector maven archetype

Bonita offers the possibility to create and plug custom connectors, to allow you to connect with any needed external system.
We provide a maven archetype to help you bootstrap a connector project. The source code of the archetype is available here.

Pre-requisite

  1. Java 17 must be installed

  2. Maven must be installed

  3. Connector development requires some software development skills. The archetype offers the possibility to develop the connector in Java, Groovy or Kotlin. Make sure that you are comfortable with at least one of those three languages.

Generate the project using the maven archetype

A maven archetype is a maven project templating toolkit. This archetype allows you to bootstrap a Bonita connector project on your file system. A Bonita connector project is a maven project. It can be built, tested and then imported into a Bonita project using Bonita Studio.

To create your connector project, prompt a terminal and enter the following command:

mvn archetype:generate \
  -DarchetypeGroupId=org.bonitasoft.archetypes \
  -DarchetypeArtifactId=bonita-connector-archetype

Make sure that you are not executing the command from an existing maven project.

If you are using Power Shell make sure to use quotes for the parameters : mvn archetype:generate "-DarchetypeGroupId=org.bonitasoft.archetypes" "-DarchetypeArtifactId=bonita-connector-archetype"

You’ll then have to specify interactively the properties of your project:

  • groupId: the group id is specific to your connector.

  • artifactId: the artifact is specific to your connector.

    • Must match the following regex: ^[a-zA-Z0-9\-]$+

      • Example: myConnector-1

  • version: the version of your connector (default value: 1.0-SNAPSHOT) Follow the maven naming convention guide

  • package the package in which the connector source files will be created (default value: the group id of the connector)

  • bonitaVersion: the technical id of the targeted Bonita version

    • A Bonita connector project depends on org.bonitasoft.engine:bonita-common. To avoid potential conflicts / errors at runtime, you should use the technical id of the Bonita version of your runtime environment (ex: 7.13.0 for Bonita 2021.2).

  • className: the class name of your connector

    • Must match the following regex: ^[a-zA-Z_$][a-zA-Z\d_$]$+ (A Java classname valid identifier)

    • Example: MyConnector1

  • language: the language used in the connector project. Available values:

    • java

    • groovy

    • kotlin

  • wrapper (optional): install a Maven wrapper. Available values:

    • true (default)

    • false

A folder named [your artifact id] will then be created, with your Bonita connector project ready to use.

Be sure to use the technical id of your Bonita version.

You can avoid the interactive mode by specifying all properties of your project directly in the command line, but by doing so you’ll bypass the validation performed on the properties content.

Example:

mvn -B archetype:generate \
  -DarchetypeGroupId=org.bonitasoft.archetypes \
  -DarchetypeArtifactId=bonita-connector-archetype \
  -DgroupId=com.acme.bonita.connectors \
  -DartifactId=ACME-bonita-connectors \
  -Dversion=1.0-SNAPSHOT \
  -Dpackage=com.acme.bonita.connectors \
  -DbonitaVersion=7.13.0 \
  -DclassName=SAPMultiFunction \
  -Dlanguage=java \
  -Dwrapper=true

Connector development

In this section we’ll look into the different components of a connector project and how you should use them to develop your connector.

Connector definition

A connector is first defined by its definition. It is an XML file located in src/main/resources/[artifactId].def by default.
A definition contains the inputs and the outputs parameters of a connector. It can be seen as a contract. Then, implementations of this definition can be created, by respecting the inputs / outputs contract of the definition.

The definition XSD is available in schemas/connector-definition-descriptor.xsd (same definition model for Connectors and Actor filters definitions), you can import it in an IDE for completion.

Connector definition xsd overview

Example:

<?xml version="1.0" encoding="UTF-8"?>
<definition:ConnectorDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:definition="http://www.bonitasoft.org/ns/connector/definition/6.1">
    <id>${connector-definition-id}</id> <!-- Id of the definition, retrieved from pom.xml -->
    <version>${connector-definition-version}</version> <!-- Version of the definition, retrieved from pom.xml -->
    <icon>connector.png</icon> <!-- The icon used in the Studio for this definition -->
    <category icon="connector.png" id="Custom"/> <!-- The category of this definition, used in the Studio (e.g: http, script ...) -->

    <!-- Connector inputs -->
    <input mandatory="true" name="defaultInput" type="java.lang.String"/>

    <!-- Connector outputs -->
    <output name="defaultOutput" type="java.lang.String"/>

    <!--
       Pages and widgets to use the connector in the Bonita Studio.
       - Each widget must be bound to an input
       - Page titles must be defined in the properties files
       - Widget labels must be defined in the properties files
       - Page and widget descriptions can be defined in the properties files (optional)
    -->
    <page id="defaultPage">
        <widget xsi:type="definition:Text" id="defaultInputWidget" inputName="defaultInput"/>
    </page>

</definition:ConnectorDefinition>

Connector Inputs

The inputs of a connector are defined in the definition. Those inputs are valued by processes, and are retrieved by the implementation classes of the connector to execute the business logic.
A connector input:

  • Has a name

  • Has a type

  • Has an optional default value

  • Can be mandatory

Connector Outputs

The outputs of a connector are defined in the definition. Those outputs are valued by the implementation classes of the connector, and are used by processes.
A connector output:

  • Has a name

  • Has a type

You can use custom types for connector outputs, the only limitation is that the type has to implement 'Serializable'.

Pages and widgets

A connector definition includes pages and widgets. Those elements define the UI that will appear in the Bonita Studio to configure the connector.

  • A widget is bound to an input

  • A page contains a set of widgets

The idea is to create pages for related inputs, so the person who will configure the connector will easily understand what he has to do.

All the available widgets are defined in the XSD. You must reference the widget type in the tag to create a specific widget:

<widget  xsi:type="definition:[WIDGET TYPE]"  id="[WIDGET ID]"  inputName="[CORRESPONDING INPUT]"/>

The widget id is used in the .properties files to define and translate the widget name and the widget description.
The input name is used to bind this widget to one of the connector inputs.

Some widgets can require additional informations. For example, if you want to create a select widget with a set of item to select, you will have to do something like that:

<widget xsi:type="definition:Select" id="choiceWidget" inputName="choice">
    <items>Choice 1</items>
    <items>Choice 2</items>
    <items>Choice 3</items>
</widget>

As widgets are displayed in a dialog window in the Studio, be careful to not use too many widgets in the same page. Use Group widget if you need to stack a lot of widgets in the same page.

Add multiple definitions

To add a new definition create a .def file in the src/main/resources-filtered/ folder. They will be added to the all zip archive at build time. It is recommended to use the maven properties for definition id and version.

Connector implementation

A connector implementation implements a connector definition. A definition defines a set on inputs / outputs, implementing a definition means use the provided inputs to create the expected outputs.
Several implementations can be created for a given definition.

A connector implementation is made of two elements:

  • An xml file used to explicit the definition implemented, the dependencies required and the location of the implementation sources

  • A set of Java (Groovy or Kotlin) based classes, constituting the implementation sources

The implementation XML file is located in src/main/resources-filtered/[artifactId].impl by default.

The implementation XSD is available in schemas/connector-implementation-descriptor.xsd, you can import it in a IDE to get completion.

Connector implementation xsd overview

Example:

<?xml version="1.0" encoding="UTF-8"?>
<implementation:connectorImplementation xmlns:implementation="http://www.bonitasoft.org/ns/connector/implementation/6.0">
  <implementationId>${connector-impl-id}</implementationId> <!-- Id of the implementation -->
  <implementationVersion>${connector-impl-version}</implementationVersion> <!-- Version of the implementation -->
  <definitionId>${connector-definition-id}</definitionId> <!-- Id of the definition implemented -->
  <definitionVersion>${connector-definition-version}</definitionVersion> <!-- Version of the definition implemented -->
  <implementationClassname>${connector-main-class}</implementationClassname> <!-- Path to the main implementation class -->
  <description>Default ${connector-definition-id} implementation</description>


<!-- retrieved from the pom.xml at build time -->
${connector-dependencies}

</implementation:connectorImplementation>

Filtered Maven properties (${…​}) are defined in the pom.xml file at the root of the project.

Implementation sources

The implementation sources contain all the logic of the connector:

  • The validation of the inputs

  • The connection / disconnection to any external system (if required)

  • The execution of the business logic and the creation of the outputs

The archetype offers the possibility to generate the default sources in Java, Groovy or Kotlin. The build result will always be a Java archive (jar) and some Zip archives (assemblies), no matters the language selected.

The entry point of the implementation sources must either extend the AbstractConnector class or implement Connector interface.

Example (using Groovy):

package myGroupId

import org.bonitasoft.engine.connector.AbstractConnector;
import org.bonitasoft.engine.connector.ConnectorException;
import org.bonitasoft.engine.connector.ConnectorValidationException;

class Connector extends AbstractConnector {

    def defaultInput = "defaultInput"
    def defaultOutput = "defaultOutput"

    /**
     * Perform validation on the inputs defined on the connector definition (src/main/resources/myConnector.def)
     * You should:
     * - validate that mandatory inputs are presents
     * - validate that the content of the inputs is coherent with your use case (e.g: validate that a date is / isn't in the past ...)
     */
    @Override
    void validateInputParameters() throws ConnectorValidationException {
        checkMandatoryStringInput(defaultInput)
    }

    def checkMandatoryStringInput(inputName) throws ConnectorValidationException {
        def value = getInputParameter(inputName)
        if (value in String) {
            if (!value) {
                throw new ConnectorValidationException(this, "Mandatory parameter '$inputName' is missing.")
            }
        } else {
            throw new ConnectorValidationException(this, "'$inputName' parameter must be a String")
        }
    }

    /**
     * Core method:
     * - Execute all the business logic of your connector using the inputs (connect to an external service, compute some values ...).
     * - Set the output of the connector execution. If outputs are not set, connector fails.
     */
    @Override
    void executeBusinessLogic() throws ConnectorException {
        def defaultInput = getInputParameter(defaultInput)
        setOutputParameter(defaultOutput, "$defaultInput - output".toString())
    }

    /**
     * [Optional] Open a connection to remote server
     */
    @Override
    void connect() throws ConnectorException{}

    /**
     * [Optional] Close connection to remote server
     */
    @Override
    void disconnect() throws ConnectorException{}
}

The methods validateInputParameters and executeBusinessLogic must be implemented, and are called by the Bonita engine when the connector is executed.
The methods connect and disconnect can be used to open and close a connection to a remote server. The life cycle of the connection will then be managed by the Bonita Runtime.

If possible, make the connector implementation idempotent. Subsequent executions of the same connector instance should not have additional side effects. This ensures, in rare case of failure when the engine is unable to determine if the connector was executed or not, that not unwanted side effects are produced.

See connectors execution for more information on how failures are handled on connectors.

Add multiple implementations

To add a new implementation create a .impl file in the src/main/resources-filtered/ folder. They will be added to the all zip archive at build time. It is recommended to use the maven properties for implementation id and version.

If you want to build a single zip assembly containing a specific implementation [1], you must create a new assembly file in the src/assembly folder. This assembly must use an id that match the implementation id and include the proper .impl file. You can use the generated impl assembly as an example.

Build a connector project

Build the project by typing the following command at the root of the project:

./mvnw clean package

A connector project is built using Maven, and especially the maven assembly plugin.

The default build output is:

  • target/[artifact id]-[artifact version].jar : This jar can be installed in a Bonita project from the Studio.

  • target/[artifact id]-[artifact version]-impl.zip : An archive containing a single implementation.[1]


1. In Bonita Enterprise edition, implementations can be updated at runtime for a given process, as long as it implements the same definition.