Apache Camel (http://camel.apache.org) is an open source Java framework that focuses on making integration easier and more accessible to developers.

This bridge lets Vert.x applications interact with Camel endpoints:

  • the application can send messages to Camel.

  • the application can receive message from Camel.

The bridge relies on the Vert.x event bus and associate an event bus address to a Camel endpoint.

Caution
This component is not polyglot as it requires some classes from Camel that can only be used in Java.

Using vertx-camel-bridge

To use the Vert.x Camel Bridge, add the following dependency to the dependencies section of your build descriptor:

  • Maven (in your pom.xml):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-camel-bridge</artifactId>
  <version>3.3.0.CR2</version>
</dependency>
  • Gradle (in your build.gradle file):

compile 'io.vertx:vertx-camel-bridge:3.3.0.CR2'

Bridge configuration

Before being used, the bridge needs to be configured and started:

var camel = new (Java.type("org.apache.camel.impl.DefaultCamelContext"))();
Java.type("io.vertx.camel.CamelBridge").create(vertx, new (Java.type("io.vertx.camel.CamelBridgeOptions"))(camel).addInboundMapping(Java.type("io.vertx.camel.InboundMapping").fromCamel("direct:stuff").toVertx("eventbus-address")).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("eventbus-address").toCamel("stream:out"))).start();

The bridge requires a CamelContext. It will find the endpoint from the context. The bridge needs to be started before being used. Be aware the the start method is asynchronous. You can use start to be notified when the bridge has been started.

Inbound mapping

Inbound mapping associates a Camel endpoint to an event bus address. Messages received on this endpoint are transformed to event bus messages.

var endpoint = camel.getEndpoint("direct:foo");

Java.type("io.vertx.camel.CamelBridge").create(vertx, new (Java.type("io.vertx.camel.CamelBridgeOptions"))(camel).addInboundMapping(Java.type("io.vertx.camel.InboundMapping").fromCamel("direct:stuff").toVertx("eventbus-address")).addInboundMapping(Java.type("io.vertx.camel.InboundMapping").fromCamel(endpoint).toVertx("eventbus-address")).addInboundMapping(Java.type("io.vertx.camel.InboundMapping").fromCamel(endpoint).toVertx("eventbus-address").withoutHeadersCopy()).addInboundMapping(Java.type("io.vertx.camel.InboundMapping").fromCamel(endpoint).toVertx("eventbus-address").usePublish()).addInboundMapping(Java.type("io.vertx.camel.InboundMapping").fromCamel(endpoint).toVertx("eventbus-address").withBodyType(Java.type("java.lang.String").class)));

The snippet above shows different ways to configure an inbound mapping:

  • you can configure the Camel endpoint either using the Endpoint object or its uri

  • you can disables the header copy (Camel message headers are copied to the event bus message)

  • you can uses publish instead of send to broadcast the message to all event bus consumers

  • you can configures the type of the event bus message body. If not set it uses the Camel message payload. If sets, it looks in the Camel context for a converter between the Camel message payload and the desired type.

Note: org.fusesource.hawtbuf.Buffer are automatically converted to Buffer.

If send is used (so not publish), and when the Camel exchange expect a reply (In Out exchange), the Vert.x code expect as reply to the sent message. When the reply arrives it is propagated to the exchange:

var endpoint = camel.getEndpoint("direct:stuff");

var bridge = Java.type("io.vertx.camel.CamelBridge").create(vertx, new (Java.type("io.vertx.camel.CamelBridgeOptions"))(camel).addInboundMapping(new (Java.type("io.vertx.camel.InboundMapping"))().setAddress("test-reply").setEndpoint(endpoint)));

vertx.eventBus().consumer("with-reply", function (message) {
  message.reply("How are you ?");
});

camel.start();
bridge.start();

var template = camel.createProducerTemplate();
var future = template.asyncRequestBody(endpoint, "hello");
var response = template.extractFutureBody(future, Java.type("java.lang.String").class);
// response == How are you ?

Outbound mapping

Outbound mapping associates an event bus address to a Camel endpoint. Messages received on this event bus address are transformed to Camel messages and sent to the endpoint.

var endpoint = camel.getEndpoint("stream:out");

Java.type("io.vertx.camel.CamelBridge").create(vertx, new (Java.type("io.vertx.camel.CamelBridgeOptions"))(camel).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("eventbus-address").toCamel("stream:out")).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("eventbus-address").toCamel(endpoint)).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("eventbus-address").toCamel(endpoint).withoutHeadersCopy()).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("eventbus-address").toCamel(endpoint)));

The snippet above shows different ways to configure an outbound mapping.

You can connect your outbound mapping to a Camel route:

camel.addRoutes(new (Java.type("org.apache.camel.builder.RouteBuilder"))());

var bridge = Java.type("io.vertx.camel.CamelBridge").create(vertx, new (Java.type("io.vertx.camel.CamelBridgeOptions"))(camel).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("test").toCamel("direct:start")));

camel.start();
bridge.start();


vertx.eventBus().send("test", "hello", function (reply, reply_err) {
  // Reply from the route (here it's "OK")
});

If when you send the message on the event bus you register a reply handler, it configures the Camel exchange to expect a response (it uses the request-reply pattern of the EIP). The response is passed in the reply body. If the route fails, you get a reply failure (recipient failure), with the message as cause:

camel.addRoutes(new (Java.type("org.apache.camel.builder.RouteBuilder"))());

var bridge = Java.type("io.vertx.camel.CamelBridge").create(vertx, new (Java.type("io.vertx.camel.CamelBridgeOptions"))(camel).addOutboundMapping(Java.type("io.vertx.camel.OutboundMapping").fromVertx("camel-route").toCamel("direct:my-route")));

camel.start();
bridge.start();

vertx.eventBus().send("camel-route", "hello", function (reply, reply_err) {
  if (reply_err == null) {
    var theResponse = reply.body();
  } else {
    var theCause = reply_err;
  }
});

Stopping the bridge

Don’t forget to stop the bridge using the stop method. The stop method is asynchronous. You can use stop to be notified when the bridge has been stopped.