|
|
|
|
@@ -0,0 +1,101 @@
|
|
|
|
|
[[camel]]
|
|
|
|
|
== Apache Camel Support
|
|
|
|
|
|
|
|
|
|
Spring Integration provides an API and configuration to communicate with https://camel.apache.org[Apache Camel] endpoints declared in the same application context.
|
|
|
|
|
|
|
|
|
|
You need to include this dependency into your project:
|
|
|
|
|
|
|
|
|
|
====
|
|
|
|
|
[source, xml, subs="normal", role="primary"]
|
|
|
|
|
.Maven
|
|
|
|
|
----
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>org.springframework.integration</groupId>
|
|
|
|
|
<artifactId>spring-integration-camel</artifactId>
|
|
|
|
|
<version>{project-version}</version>
|
|
|
|
|
</dependency>
|
|
|
|
|
----
|
|
|
|
|
[source, groovy, subs="normal", role="secondary"]
|
|
|
|
|
.Gradle
|
|
|
|
|
----
|
|
|
|
|
compile "org.springframework.integration:spring-integration-camel:{project-version}"
|
|
|
|
|
----
|
|
|
|
|
====
|
|
|
|
|
|
|
|
|
|
Spring Integration and Apache Camel implement Enterprise Integration Patterns and provide a convenient way to compose them, but the projects use a different approach for their API and abstractions implementation.
|
|
|
|
|
Spring Integration fully relies on a dependency injection container from Spring Core.
|
|
|
|
|
It uses many other Spring projects (Spring Data, Spring AMQP, Spring for Apache Kafka etc.) for its channel adapter implementations.
|
|
|
|
|
It also uses the `MessageChannel` abstraction as a first class citizen of which developers need to be aware of, when composing their integration flows.
|
|
|
|
|
Apache Camel, on the other hand, does not provide a first class citizen abstraction of a message channel and proposes to compose its routes via internal exchanges, hidden from the API.
|
|
|
|
|
In addition, it requires some extra https://camel.apache.org/components/3.18.x/spring-summary.html[dependencies and configurations] for it to be used in a Spring application.
|
|
|
|
|
|
|
|
|
|
Even if it doesn't matter for the final enterprise integration solution how its parts are implemented, a developer experience and high productivity are taken into account.
|
|
|
|
|
Therefore, developers may choose one framework over another for many reasons, or both if there is a gap in some target systems support.
|
|
|
|
|
Spring Integration and Apache Camel applications can interact with each other through many external protocols for which they implement channel adapters.
|
|
|
|
|
For example, a Spring Integration flow may publish a record to an Apache Kafka topic which is consumed by an Apache Camel endpoint on the consumer side.
|
|
|
|
|
Or, an Apache Camel route may write data into an SFTP file the directory, which is polled by a SFTP Inbound Channel Adapter from Spring Integration.
|
|
|
|
|
Or, within the same Spring application context they can communicate via an `ApplicationEvent` https://camel.apache.org/components/3.18.x/spring-event-component.html[abstraction].
|
|
|
|
|
|
|
|
|
|
To make a development process easier, and to avoid unnecessary network hops, Apache Camel provides a https://camel.apache.org/components/3.18.x/spring-integration-component.html[module] to communicate with Spring Integration via message channels.
|
|
|
|
|
All that is needed is a reference to a `MessageChannel` from the application context, to send or consume messages.
|
|
|
|
|
This works well when Apache Camel routes are initiators of the message flow and Spring Integration plays only a supporting role as a part of the solution.
|
|
|
|
|
|
|
|
|
|
For a similar developer experience, Spring Integration now provides a channel adapter to call an Apache Camel endpoint and, optionally, wait for a reply.
|
|
|
|
|
There is no inbound channel adapter because subscribing to a `MessageChannel` for consuming Apache Camel messages is enough from the Spring Integration API and abstractions perspective.
|
|
|
|
|
|
|
|
|
|
[[camel-channel-adapter]]
|
|
|
|
|
=== Outbound Channel Adapter for Apache Camel
|
|
|
|
|
|
|
|
|
|
The `CamelMessageHandler` is an `AbstractReplyProducingMessageHandler` implementation and can work in both one-way (default) and request-reply modes.
|
|
|
|
|
It uses an `org.apache.camel.ProducerTemplate` to send (or send and receive) into an `org.apache.camel.Endpoint`.
|
|
|
|
|
An interaction mode can be controlled by the `ExchangePattern` option (which can be evaluated at runtime against the request message via a SpEL expression).
|
|
|
|
|
The target Apache Camel endpoint can be configured explicitly or as a SpEL expression to be evaluated at runtime.
|
|
|
|
|
Otherwise, it falls back to the `defaultEndpoint` provided on the `ProducerTemplate`.
|
|
|
|
|
Instead of specifying the endpoint, an in-line, explicit `LambdaRouteBuilder` can be provided, for example to make a call into an Apache Camel component for which there is no channel adapter support in Spring Integration.
|
|
|
|
|
|
|
|
|
|
In addition, a `HeaderMapper<org.apache.camel.Message>` (the `CamelHeaderMapper` is a default implementation) can be provided, to determine which headers to map between the Spring Integration and Apache Camel messages.
|
|
|
|
|
By default, all headers are mapped.
|
|
|
|
|
|
|
|
|
|
The `CamelMessageHandler` supports an `async` mode calling `ProducerTemplate.asyncSend()` and producing a `CompletableFuture` for reply processing (if any).
|
|
|
|
|
|
|
|
|
|
The `exchangeProperties` can be customized via a SpEL expression, which must evaluate to a `Map`.
|
|
|
|
|
|
|
|
|
|
If a `ProducerTemplate` is not provided, it is created via a `CamelContext` bean resolved from the application context.
|
|
|
|
|
|
|
|
|
|
====
|
|
|
|
|
[source, java]
|
|
|
|
|
----
|
|
|
|
|
@Bean
|
|
|
|
|
@ServiceActivator(inputChannel = "sendToCamel")
|
|
|
|
|
CamelMessageHandler camelService(ProducerTemplate producerTemplate) {
|
|
|
|
|
CamelHeaderMapper headerMapper = new CamelHeaderMapper();
|
|
|
|
|
headerMapper.setOutboundHeaderNames("");
|
|
|
|
|
headerMapper.setInboundHeaderNames("testHeader");
|
|
|
|
|
|
|
|
|
|
CamelMessageHandler camelMessageHandler = new CamelMessageHandler(producerTemplate);
|
|
|
|
|
camelMessageHandler.setEndpointUri("direct:simple");
|
|
|
|
|
camelMessageHandler.setExchangePatternExpression(spelExpressionParser.parseExpression("headers.exchangePattern"));
|
|
|
|
|
camelMessageHandler.setHeaderMapper(headerMapper);
|
|
|
|
|
return camelMessageHandler;
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
====
|
|
|
|
|
|
|
|
|
|
For Java DSL flow definitions this channel adapter can be configured with a few variants provided by the `Camel` factory:
|
|
|
|
|
|
|
|
|
|
====
|
|
|
|
|
[source, java]
|
|
|
|
|
----
|
|
|
|
|
@Bean
|
|
|
|
|
IntegrationFlow camelFlow() {
|
|
|
|
|
return f -> f
|
|
|
|
|
.handle(Camel.gateway().endpointUri("direct:simple"))
|
|
|
|
|
.handle(Camel.route(this::camelRoute))
|
|
|
|
|
.handle(Camel.handler().endpointUri("log:com.mycompany.order?level=WARN"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void camelRoute(RouteBuilder routeBuilder) {
|
|
|
|
|
routeBuilder.from("direct:inbound").transform(routeBuilder.simple("${body.toUpperCase()}"));
|
|
|
|
|
}
|
|
|
|
|
----
|
|
|
|
|
====
|