= Azure Event Hubs Component
:doctitle: Azure Event Hubs
:shortname: azure-eventhubs
:artifactid: camel-azure-eventhubs
:description: Send and receive events to/from Azure Event Hubs using AMQP protocol.
:since: 3.5
:supportlevel: Stable
:component-header: Both producer and consumer are supported
//Manually maintained attributes
:group: Azure
:camel-spring-boot-name: azure-eventhubs

*Since Camel {since}*

*{component-header}*

The Azure Event Hubs used to integrate https://azure.microsoft.com/en-us/services/event-hubs/[Azure Event Hubs] using https://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol[AMQP protocol].
Azure EventHubs is a highly scalable publish-subscribe service that can ingest millions of events per second and stream them to multiple consumers.

NOTE: Besides AMQP protocol support, Event Hubs as well supports Kafka and HTTPS protocols. Therefore, you can use as well xref:components::kafka-component.adoc[Camel Kafka] component to produce and consume to Azure Event Hubs. You can lean more https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-quickstart-kafka-enabled-event-hubs[here].


Prerequisites

You must have a valid Windows Azure Event Hubs account. More information is available at
https://docs.microsoft.com/azure/[Azure Documentation Portal].

Maven users will need to add the following dependency to their `pom.xml`
for this component:

[source,xml]
------------------------------------------------------------
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-azure-eventhubs</artifactId>
    <version>x.x.x</version>
  <!-- use the same version as your Camel core version -->
</dependency>
------------------------------------------------------------

== URI Format

[source,text]
------------------------------
azure-eventhubs://[namespace/eventHubName][?options]
------------------------------

In case you supply the `connectionString`, `namespace` and `eventHubName` are not required as these options already included
in the `connectionString`


// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END


== Authentication Information

To use this component, you have 3 options in order to provide the required Azure authentication information:

- Provide `sharedAccessName` and `sharedAccessKey` for your Azure Event Hubs account. The sharedAccessKey can
be generated through your Event Hubs Azure portal.
- Provide `connectionString` string, if you provide the connection string, you don't supply `namespace`, `eventHubName`, `sharedAccessKey` and `sharedAccessName`
as these data already included in the `connectionString`, therefore is the simplest option to get started. Learn more https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-get-connection-string[here] on how to generate the connection string.
- Provide a https://docs.microsoft.com/en-us/java/api/com.azure.messaging.eventhubs.eventhubproducerasyncclient?view=azure-java-stable[EventHubProducerAsyncClient] instance which can be
provided into `producerAsyncClient`. However, this is *only possible for camel producer*, for the camel consumer, is not possible to inject the client due to some design constraint by the `EventProcessorClient`.
- Provide an implementation of `com.azure.core.credential.TokenCredential` into the Camel's Registry, e.g. using the `com.azure.identity.DefaultAzureCredentialBuilder().build();` API.
See the documentation https://docs.microsoft.com/en-us/azure/active-directory/authentication/overview-authentication[here about Azure-AD authentication].

== Checkpoint Store Information
A checkpoint store stores and retrieves partition ownership information and checkpoint details for each partition in a given consumer group of an event hub instance. Users are not meant to implement an CheckpointStore.
Users are expected to choose existing implementations of this interface, instantiate it, and pass it to the component through `checkpointStore` option.
Users are not expected to use any of the methods on a checkpoint store, these are used internally by the client.

Having said that, if the user does not pass any `CheckpointStore` implementation, the component will fallback to use https://docs.microsoft.com/en-us/javascript/api/@azure/eventhubs-checkpointstore-blob/blobcheckpointstore?view=azure-node-latest[`BlobCheckpointStore`] to store the checkpoint info in Azure Blob Storage account.
If you chose to use the default `BlobCheckpointStore`, you will need to supply the following options:

- `blobAccountName`: It sets Azure account name to be used for authentication with azure blob services.
- `blobAccessKey` : It sets access key for the associated azure account name to be used for authentication with azure blob services.
- `blobContainerName` : It sets the blob container that shall be used by the BlobCheckpointStore to store the checkpoint offsets.


== Async Consumer and 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 consume event from EventHub, use the following snippet:

[source,java]
--------------------------------------------------------------------------------
from("azure-eventhubs:/camel/camelHub?sharedAccessName=SASaccountName&sharedAccessKey=SASaccessKey&blobAccountName=accountName&blobAccessKey=accessKey&blobContainerName=containerName")
  .to("file://queuedirectory");
--------------------------------------------------------------------------------

// component headers: START
include::partial$component-endpoint-headers.adoc[]
// component headers: END

=== Message body type
The component's producer expects the data in the message body to be in `byte[]`. This allows the user to utilize Camel TypeConverter to marshal/unmarshal data with ease.
The same goes as well for the component's consumer, it will set the encoded data as `byte[]` in the message body.


=== Automatic detection of EventHubProducerAsyncClient client in registry

The component is capable of detecting the presence of an EventHubProducerAsyncClient bean into the registry.
If it's the only instance of that type it will be used as client and you won't have to define it as uri parameter, like the example above.
This may be really useful for smarter configuration of the endpoint.

=== Consumer Example
The example below will unmarshal the events that was originally produced in JSON:

[source,java]
----
from("azure-eventhubs:?connectionString=RAW({{connectionString}})"&blobContainerName=containerTest&eventPosition=#eventPosition"
    +"&blobAccountName={{blobAccountName}}&blobAccessKey=RAW({{blobAccessKey}})")
.unmarshal().json(JsonLibrary.Jackson)
.to(result);
----

=== Producer Example
The example below will send events as String to EventHubs:

[source,java]
----
from("direct:start")
.process(exchange -> {
        exchange.getIn().setHeader(EventHubsConstants.PARTITION_ID, firstPartition);
        exchange.getIn().setBody("test event");
})
.to("azure-eventhubs:?connectionString=RAW({{connectionString}})"
----

Also, the component supports as well *aggregation* of messages by sending events as *iterable* of either Exchanges/Messages or normal data (e.g: list of Strings). For example:

[source,java]
----
from("direct:start")
.process(exchange -> {
        final List<String> messages = new LinkedList<>();
        messages.add("Test String Message 1");
        messages.add("Test String Message 2");

        exchange.getIn().setHeader(EventHubsConstants.PARTITION_ID, firstPartition);
        exchange.getIn().setBody(messages);
})
.to("azure-eventhubs:?connectionString=RAW({{connectionString}})"
----

=== Azure-AD Authentication example
The example below makes use of the Azure-AD authentication. See https://docs.microsoft.com/en-us/java/api/overview/azure/identity-readme?view=azure-java-stable#environment-variables[here]
about what environment variables you need to set for this to work:

[source,java]
----
@BindToRegistry("myTokenCredential")
public com.azure.core.credential.TokenCredential myTokenCredential() {
    return com.azure.identity.DefaultAzureCredentialBuilder().build();
}

from("direct:start")
.to("azure-eventhubs:namespace/eventHubName?tokenCredential=#myTokenCredential)"
----

=== Development Notes (Important)

When developing on this component, you will need to obtain your Azure accessKey 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 or even client upgrade as the Azure client can break things even on minor versions upgrade.*
To run the integration tests, on this component directory, run the following maven command:

[source,bash]
----
mvn verify -DconnectionString=string -DblobAccountName=blob -DblobAccessKey=key
----

Whereby `blobAccountName` is your Azure account name and `blobAccessKey` is the access key being generated from Azure portal and `connectionString` is the eventHub connection string.



include::spring-boot:partial$starter.adoc[]
