Stitch
Since Camel 3.8
Only producer is supported
Stitch is a cloud ETL service, developer-focused platform for rapidly moving and replicates data from more than 90 applications and databases. It integrates various data sources into a central data warehouse. Stitch has integrations for many enterprise software data sources, and can receive data via WebHooks and an API (Stitch Import API) which Camel Stitch Component uses to produce the data to Stitch ETL.
For more info, feel free to visit their website: https://www.stitchdata.com/
Prerequisites
You must have a valid Stitch account, you will need to enable Stitch Import API and generate a token for the integration, for more info, please find more info here.
Maven users will need to add the following dependency to their pom.xml
for this component:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-stitch</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
Configuring Options
Camel components are configured on two separate levels:
-
component level
-
endpoint level
Configuring Component Options
The component level is the highest level which holds general and common configurations that are inherited by the endpoints. For example a component may have security settings, credentials for authentication, urls for network connection and so forth.
Some components only have a few options, and others may have many. Because components typically have pre configured defaults that are commonly used, then you may often only need to configure a few options on a component; or none at all.
Configuring components can be done with the Component DSL, in a configuration file (application.properties|yaml), or directly with Java code.
Configuring Endpoint Options
Where you find yourself configuring the most is on endpoints, as endpoints often have many options, which allows you to configure what you need the endpoint to do. The options are also categorized into whether the endpoint is used as consumer (from) or as a producer (to), or used for both.
Configuring endpoints is most often done directly in the endpoint URI as path and query parameters. You can also use the Endpoint DSL and DataFormat DSL as a type safe way of configuring endpoints and data formats in Java.
A good practice when configuring options is to use Property Placeholders, which allows to not hardcode urls, port numbers, sensitive information, and other settings. In other words placeholders allows to externalize the configuration from your code, and gives more flexibility and reuse.
The following two sections lists all the options, firstly for the component followed by the endpoint.
Component Options
The Stitch component supports 10 options, which are listed below.
Name | Description | Default | Type |
---|---|---|---|
The component configurations. |
StitchConfiguration |
||
A collection of comma separated strings representing the Primary Key fields in the source table. Stitch use these Primary Keys to de-dupe data during loading If not provided, the table will be loaded in an append-only manner. |
String |
||
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. |
false |
boolean |
|
Stitch account region, e.g: europe. Enum values:
|
EUROPE |
StitchRegion |
|
Autowired A schema that describes the record(s). |
StitchSchema |
||
Autowired ConnectionProvider contain configuration for the HttpClient like Maximum connection limit .. etc, you can inject this ConnectionProvider and the StitchClient will initialize HttpClient with this ConnectionProvider. |
ConnectionProvider |
||
Autowired Reactor Netty HttpClient, you can injected it if you want to have custom HttpClient. |
HttpClient |
||
Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. |
true |
boolean |
|
Autowired Set a custom StitchClient that implements org.apache.camel.component.stitch.client.StitchClient interface. |
StitchClient |
||
Required Stitch access token for the Stitch Import API. |
String |
Endpoint Options
The Stitch endpoint is configured using URI syntax:
stitch:tableName
with the following path and query parameters:
Path Parameters (1 parameters)
Name | Description | Default | Type |
---|---|---|---|
The name of the destination table the data is being pushed to. Table names must be unique in each destination schema, or loading issues will occur. Note: The number of characters in the table name should be within the destination’s allowed limits or data will rejected. |
String |
Query Parameters (8 parameters)
Name | Description | Default | Type |
---|---|---|---|
A collection of comma separated strings representing the Primary Key fields in the source table. Stitch use these Primary Keys to de-dupe data during loading If not provided, the table will be loaded in an append-only manner. |
String |
||
Stitch account region, e.g: europe. Enum values:
|
EUROPE |
StitchRegion |
|
Autowired A schema that describes the record(s). |
StitchSchema |
||
Autowired ConnectionProvider contain configuration for the HttpClient like Maximum connection limit .. etc, you can inject this ConnectionProvider and the StitchClient will initialize HttpClient with this ConnectionProvider. |
ConnectionProvider |
||
Autowired Reactor Netty HttpClient, you can injected it if you want to have custom HttpClient. |
HttpClient |
||
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. |
false |
boolean |
|
Autowired Set a custom StitchClient that implements org.apache.camel.component.stitch.client.StitchClient interface. |
StitchClient |
||
Required Stitch access token for the Stitch Import API. |
String |
Message Headers
The Stitch component supports 6 message header(s), which is/are listed below:
Name | Description | Default | Type |
---|---|---|---|
CamelStitchTableName (producer) Constant: |
The name of the destination table the data is being pushed to. Table names must be unique in each destination schema, or loading issues will occur. Note: The number of characters in the table name should be within the destinations allowed limits or data will rejected. |
String |
|
Constant: |
The schema that describes the Stitch message. |
StitchSchema or Map |
|
CamelStitchKeyNames (producer) Constant: |
A collection of strings representing the Primary Key fields in the source table. Stitch use these Primary Keys to de-dupe data during loading If not provided, the table will be loaded in an append-only manner. |
Collection |
|
Constant: |
HTTP Status code that is returned from Stitch Import HTTP API. |
Integer |
|
Constant: |
HTTP headers that are returned from Stitch Import HTTP API. |
Map |
|
Constant: |
The status message that Stitch returns after sending the data through Stitch Import API. |
String |
Async Producer
This component implements the async Consumer and producer.
This allows camel route to consume and produce events asynchronously without blocking any threads.
Usage
For example in order to produce data to Stitch from a custom processor:
from("direct:sendStitch")
.process(exchange -> {
final StitchMessage stitchMessage = StitchMessage.builder()
.withData("field_1", "stitchMessage2-1")
.build();
final StitchRequestBody stitchRequestBody = StitchRequestBody.builder()
.addMessage(stitchMessage)
.withSchema(StitchSchema.builder().addKeyword("field_1", "string").build())
.withTableName("table_1")
.withKeyNames(Collections.singleton("field_1"))
.build();
exchange.getMessage().setBody(stitchRequestBody);
})
.to("stitch:table_1?token=RAW({{token}})");
Message body type
Currently, the component supports the following types for the body message on the producer side when producing a message to Stitch component:
-
org.apache.camel.component.stitch.client.models.StitchRequestBody
: This represents this Stitch JSON Message. However,StitchRequestBody
includes a type safe builder that helps on building the request body. Please note that,tableName
,keyNames
andschema
options are no longer required if you send the data withStitchRequestBody
, if you still set these options, they override whatever being set in message bodyStitchRequestBody
. -
org.apache.camel.component.stitch.client.models.StitchMessage
: This represents this Stitch message structure. If you choose to send your message asStitchMessage
, you will need to addtableName
,keyNames
andschema
options to either the Exchange headers or through the endpoint options. -
Map
: You can also send the data asMap
, the data structure must follow this JSON Message structure which is similar toStitchRequestBody
but with drawback losing on all the type safety builder that is included withStitchRequestBody
. -
Iterable
: You can send multiple Stitch messages that are aggregated by Camel or aggregated through custom processor. These aggregated messages can be type ofStitchMessage
,StitchRequestBody
orMap
but this Map here is similar toStitchMessage
.
Examples
Here are list of examples of data that can be proceeded to Stitch:
Input body type org.apache.camel.component.stitch.client.models.StitchRequestBody
:
from("direct:sendStitch")
.process(exchange -> {
final StitchMessage stitchMessage = StitchMessage.builder()
.withData("field_1", "stitchMessage2-1")
.build();
final StitchRequestBody stitchRequestBody = StitchRequestBody.builder()
.addMessage(stitchMessage)
.withSchema(StitchSchema.builder().addKeyword("field_1", "string").build())
.withTableName("table_1")
.withKeyNames(Collections.singleton("field_1"))
.build();
exchange.getMessage().setBody(stitchRequestBody);
})
.to("stitch:table_1?token=RAW({{token}})");
Input body type org.apache.camel.component.stitch.client.models.StitchMessage
:
from("direct:sendStitch")
.process(exchange -> {
exchange.getMessage().setHeader(StitchConstants.SCHEMA, StitchSchema.builder().addKeyword("field_1", "string").build());
exchange.getMessage().setHeader(StitchConstants.KEY_NAMES, "field_1");
exchange.getMessage().setHeader(StitchConstants.TABLE_NAME, "table_1");
final StitchMessage stitchMessage = StitchMessage.builder()
.withData("field_1", "stitchMessage2-1")
.build();
exchange.getMessage().setBody(stitchMessage);
})
.to("stitch:table_1?token=RAW({{token}})");
Input body type Map
:
from("direct:sendStitch")
.process(exchange -> {
final Map<String, Object> properties = new LinkedHashMap<>();
properties.put("id", Collections.singletonMap("type", "integer"));
properties.put("name", Collections.singletonMap("type", "string"));
properties.put("age", Collections.singletonMap("type", "integer"));
properties.put("has_magic", Collections.singletonMap("type", "boolean"));
final Map<String, Object> data = new LinkedHashMap<>();
data.put(StitchRequestBody.TABLE_NAME, "my_table");
data.put(StitchRequestBody.SCHEMA, Collections.singletonMap("properties", properties));
data.put(StitchRequestBody.MESSAGES,
Collections.singletonList(Collections.singletonMap("data", Collections.singletonMap("id", 2))));
data.put(StitchRequestBody.KEY_NAMES, "test_key");
exchange.getMessage().setBody(data);
})
.to("stitch:table_1?token=RAW({{token}})");
Input body type Iterable
:
from("direct:sendStitch")
.process(exchange -> {
exchange.getMessage().setHeader(StitchConstants.SCHEMA, StitchSchema.builder().addKeyword("field_1", "string").build());
exchange.getMessage().setHeader(StitchConstants.KEY_NAMES, "field_1");
exchange.getMessage().setHeader(StitchConstants.TABLE_NAME, "table_1");
final StitchMessage stitchMessage1 = StitchMessage.builder()
.withData("field_1", "stitchMessage1")
.build();
final StitchMessage stitchMessage2 = StitchMessage.builder()
.withData("field_1", "stitchMessage2-1")
.build();
final StitchRequestBody stitchMessage2RequestBody = StitchRequestBody.builder()
.addMessage(stitchMessage2)
.withSchema(StitchSchema.builder().addKeyword("field_1", "integer").build())
.withTableName("table_1")
.withKeyNames(Collections.singleton("field_1"))
.build();
final Map<String, Object> stitchMessage3 = new LinkedHashMap<>();
stitchMessage3.put(StitchMessage.DATA, Collections.singletonMap("field_1", "stitchMessage3"));
final StitchMessage stitchMessage4 = StitchMessage.builder()
.withData("field_1", "stitchMessage4")
.build();
final Exchange stitchMessage4Exchange = new DefaultExchange(context);
stitchMessage4Exchange.getMessage().setBody(stitchMessage4);
final StitchMessage stitchMessage5 = StitchMessage.builder()
.withData("field_1", "stitchMessage5")
.build();
final Message stitchMessage5Message = new DefaultExchange(context).getMessage();
stitchMessage5Message.setBody(stitchMessage5);
final List<Object> inputMessages = new LinkedList<>();
inputMessages.add(stitchMessage1);
inputMessages.add(stitchMessage2RequestBody);
inputMessages.add(stitchMessage3);
inputMessages.add(stitchMessage4Exchange);
inputMessages.add(stitchMessage5Message);
exchange.getMessage().setBody(inputMessages);
})
.to("stitch:table_1?token=RAW({{token}})");
Development Notes (Important)
When developing on this component, you will need to obtain your Stitch token in order to run the integration tests. In addition to the mocked unit tests you will need to run the integration tests with every change you make To run the integration tests, on this component directory, run the following maven command:
mvn verify -Dtoken=stitchToken
Whereby token
is your Stitch token that is generated for Stitch Import API integration.
Spring Boot Auto-Configuration
When using stitch with Spring Boot make sure to use the following Maven dependency to have support for auto configuration:
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-stitch-starter</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
The component supports 11 options, which are listed below.
Name | Description | Default | Type |
---|---|---|---|
Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. |
true |
Boolean |
|
The component configurations. The option is a org.apache.camel.component.stitch.StitchConfiguration type. |
StitchConfiguration |
||
ConnectionProvider contain configuration for the HttpClient like Maximum connection limit .. etc, you can inject this ConnectionProvider and the StitchClient will initialize HttpClient with this ConnectionProvider. The option is a reactor.netty.resources.ConnectionProvider type. |
ConnectionProvider |
||
Whether to enable auto configuration of the stitch component. This is enabled by default. |
Boolean |
||
Reactor Netty HttpClient, you can injected it if you want to have custom HttpClient. The option is a reactor.netty.http.client.HttpClient type. |
HttpClient |
||
A collection of comma separated strings representing the Primary Key fields in the source table. Stitch use these Primary Keys to de-dupe data during loading If not provided, the table will be loaded in an append-only manner. |
String |
||
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. |
false |
Boolean |
|
Stitch account region, e.g: europe. |
StitchRegion |
||
Set a custom StitchClient that implements org.apache.camel.component.stitch.client.StitchClient interface. The option is a org.apache.camel.component.stitch.client.StitchClient type. |
StitchClient |
||
A schema that describes the record(s). The option is a org.apache.camel.component.stitch.client.models.StitchSchema type. |
StitchSchema |
||
Stitch access token for the Stitch Import API. |
String |