Update 0.1 to 0.2
The following sections explain which adjustments must be made to migrate from Connector SDK 0.1.x to 0.2.0.
Be aware that the update from 0.1 to 0.2 requires manual migration steps as described below.
Connector function
With SDK version 0.2.0, we introduce the following structural changes:
- Input validation and secret replacement move from writing imperative code to declaratively using annotations.
- The Outbound aspect of APIs is more explicit. Classes have been moved to more explicit packages and have been renamed.
- New required annotation for outbound Connectors.
Declarative validation and secrets
Input objects previously had to implement the ConnectorInput
interface to participate in validation and secret replacement
initiated from the ConnectorContext
using its validate
and replaceSecrets
methods respectively.
With version 0.2.0, we remove the imperative approach for validation and secret replacement from the SDK. Instead, you can use annotations to describe the constraints of input attributes and mark those that can contain secrets.
These are two input objects written with the SDK version 0.1.x:
import io.camunda.connector.api.ConnectorInput;
import io.camunda.connector.api.SecretStore;
import io.camunda.connector.api.Validator;
public class MyConnectorRequest implements ConnectorInput {
private String message;
private Authentication authentication;
@Override
public void validateWith(final Validator validator) {
validator.require(message, "message");
validator.require(authentication, "authentication");
validateIfNotNull(authentication, validator);
}
@Override
public void replaceSecrets(final SecretStore secretStore) {
replaceSecretsIfNotNull(authentication, secretStore);
}
}
import io.camunda.connector.api.ConnectorInput;
import io.camunda.connector.api.SecretStore;
import io.camunda.connector.api.Validator;
public class Authentication implements ConnectorInput {
private String user;
private String token;
@Override
public void validateWith(final Validator validator) {
validator.require(user, "user");
validator.require(token, "token");
if (token != null && !(token.startsWith("xobx") || token.startsWith("secrets."))) {
validator.addErrorMessage("Token must start with \"xobx\" or be a secret");
}
}
@Override
public void replaceSecrets(final SecretStore secretStore) {
token = secretStore.replaceSecret(token);
}
}
You can express the same input objects with SDK version 0.2.0 as follows:
import io.camunda.connector.api.annotation.Secret;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
public class MyConnectorRequest {
@NotEmpty
private String message;
@NotNull
@Valid
@Secret
private Authentication authentication;
}
import io.camunda.connector.api.annotation.Secret;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
public class Authentication {
@NotEmpty
private String user;
@NotEmpty
@Pattern("^(xobx-|secret).+")
@Secret
private String token;
}
As a result, you have to remove the ConnectorInput
interface implementation and the imperative code that comes with validateWith
and replaceSecrets
. You can now concisely describe the constraints of attributes rather then expressing them in imperative code.
In order to use annoation-based validation out of the box, you can include the new artifact connector-validation
that
comes with the SDK.
- Maven dependency
- Gradle dependency
<dependency>
<groupId>io.camunda.connector</groupId>
<artifactId>connector-validation</artifactId>
<version>0.2.0</version>
</dependency>
implementation 'io.camunda.connector:connector-validation:0.2.0'
You can read more about validation and secret replacement in our SDK Guide.
Explicit Outbound aspect
With version 0.2.0 of the SDK, we make the Outbound aspect of those components specific to oubound connectivity more visible. This separates those SDK components that are tightly coupled to Outbound from those that will be reusable for Inbound.
With this change, the names of the following classes need to be adjusted:
- Rename
io.camunda.connector.api.ConnectorContext
toio.camunda.connector.api.outbound.OutboundConnectorContext
- Rename
io.camunda.connector.api.ConnectorFunction
toio.camunda.connector.api.outbound.OutboundConnectorFunction
- Rename
io.camunda.connector.api.SecretProvider
toio.camunda.connector.api.secret.SecretProvider
- Rename
io.camunda.connector.api.SecretStore
toio.camunda.connector.api.secret.SecretStore
- Rename
io.camunda.connector.test.ConnectorContextBuilder
toio.camunda.connector.test.outbound.OutboundConnectorContextBuilder
As a result, you must replace all occurrences of the old class names and imports with the new ones. This includes the
SPI for the connector function itself. Therefore, rename the file META-INF/services/io.camunda.connector.api.ConnectorFunction
to
META-INF/services/io.camunda.connector.api.outbound.OutboundConnectorFunction
.
@OutboundConnector
annotation
For best interoperability, Connectors provide default meta-data (name
, type
, inputVariables
) via the @OutboundConnector
annotation:
@OutboundConnector(
name = "PING",
inputVariables = {"caller"},
type = "io.camunda.example.PingConnector:1"
)
public class PingConnector implements OutboundConnectorFunction {
...
}
Connector runtime environment
If using the pre-packaged runtime environment that comes with the SDK does not fit your use case, you can create a custom runtime environment.
With version 0.2.0 of the job worker runtime environment, you need to make the following changes:
- Rename
io.camunda.connector.runtime.jobworker.ConnectorJobHandler
toio.camunda.connector.runtime.jobworker.api.outbound.ConnectorJobHandler
- Rename connector related env variables from
ZEEBE_
toCONNECTOR_
. Zeebe configuration properties remain unchanged
As a general change in behavior the module will now pick up connectors from classpath unless it is explicitly configured via environment variables.
Also take the name changes in the SDK core into account.
Implementing your own Connector wrapper you need to provide a Connector context specific to
your environment. Consider extending the io.camunda.connector.impl.outbound.AbstractConnectorContext
instead of implementing the io.camunda.connector.api.ConnectorContext
yourself. Most of the commonly needed functionality
is already provided in there.