# Vert.x Camel Bridge

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</version>
    </dependency>

- Gradle (in your `build.gradle` file):

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

## 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.