= Vert.x Camel Bridge
:toc: left

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`):

[source,xml,subs="+attributes"]
----
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-camel-bridge</artifactId>
  <version>3.3.1</version>
</dependency>
----

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

[source,groovy,subs="+attributes"]
----
compile 'io.vertx:vertx-camel-bridge:3.3.1'
----

== Bridge configuration

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

[source,ruby]
----
camel = Java::OrgApacheCamelImpl::DefaultCamelContext.new()
Java::IoVertxCamel::CamelBridge.create(vertx, Java::IoVertxCamel::CamelBridgeOptions.new(camel).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.from_camel("direct:stuff").to_vertx("eventbus-address")).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("eventbus-address").to_camel("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
`link:unavailable#start-instance_method[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.

[source,ruby]
----
endpoint = camel.get_endpoint("direct:foo")

Java::IoVertxCamel::CamelBridge.create(vertx, Java::IoVertxCamel::CamelBridgeOptions.new(camel).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.from_camel("direct:stuff").to_vertx("eventbus-address")).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.from_camel(endpoint).to_vertx("eventbus-address")).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.from_camel(endpoint).to_vertx("eventbus-address").without_headers_copy()).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.from_camel(endpoint).to_vertx("eventbus-address").use_publish()).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.from_camel(endpoint).to_vertx("eventbus-address").with_body_type(Java::JavaLang::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 `link:../../yardoc/Vertx/Buffer.html[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:

[source,ruby]
----
endpoint = camel.get_endpoint("direct:stuff")

bridge = Java::IoVertxCamel::CamelBridge.create(vertx, Java::IoVertxCamel::CamelBridgeOptions.new(camel).add_inbound_mapping(Java::IoVertxCamel::InboundMapping.new().set_address("test-reply").set_endpoint(endpoint)))

vertx.event_bus().consumer("with-reply") { |message|
  message.reply("How are you ?")
}

camel.start()
bridge.start()

template = camel.create_producer_template()
future = template.async_request_body(endpoint, "hello")
response = template.extract_future_body(future, Java::JavaLang::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.

[source,ruby]
----
endpoint = camel.get_endpoint("stream:out")

Java::IoVertxCamel::CamelBridge.create(vertx, Java::IoVertxCamel::CamelBridgeOptions.new(camel).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("eventbus-address").to_camel("stream:out")).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("eventbus-address").to_camel(endpoint)).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("eventbus-address").to_camel(endpoint).without_headers_copy()).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("eventbus-address").to_camel(endpoint)))

----

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

You can connect your outbound mapping to a Camel route:

[source,ruby]
----
camel.add_routes(Java::OrgApacheCamelBuilder::RouteBuilder.new())

bridge = Java::IoVertxCamel::CamelBridge.create(vertx, Java::IoVertxCamel::CamelBridgeOptions.new(camel).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("test").to_camel("direct:start")))

camel.start()
bridge.start()


vertx.event_bus().send("test", "hello") { |reply_err,reply|
  # 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:

[source,ruby]
----
camel.add_routes(Java::OrgApacheCamelBuilder::RouteBuilder.new())

bridge = Java::IoVertxCamel::CamelBridge.create(vertx, Java::IoVertxCamel::CamelBridgeOptions.new(camel).add_outbound_mapping(Java::IoVertxCamel::OutboundMapping.from_vertx("camel-route").to_camel("direct:my-route")))

camel.start()
bridge.start()

vertx.event_bus().send("camel-route", "hello") { |reply_err,reply|
  if (reply_err == nil)
    theResponse = reply.body()
  else
    theCause = reply_err
  end
}

----

== Stopping the bridge

Don't forget to stop the bridge using the `stop` method. The `stop` method is asynchronous. You can use
`link:unavailable#stop-instance_method[stop]` to be notified when the bridge has been stopped.

