Integrations

Axon Server perfectly works with Axon Framework applications. With minimal configuration, the Axon Framework applications distribute commands and queries through Axon Server and use It as an event store. Sometimes, you want to integrate applications that do not use the Axon Framework, applications that may not be running in a Java virtual machine. This is where the Axon Server Integration option comes in.

Axon Server Integration supports:

  • Sending commands and queries to any application that supports HTTP(s) or RSocket communication.

  • Subscribing to events from these applications.

  • Sending commands and queries to Axon Framework applications through HTTP(s)

  • Publishing events and snapshots to Axon Server through HTTP(s).

  • Reading events and snapshots for an aggregate from Axon Server through HTTP(s).

Endpoints

You must first define an endpoint to forward commands, queries, and events to your application. This endpoint describes your application’s common properties, such as the base address and protocol to reach it. Once you have defined the endpoint, you can register handlers for commands, queries, and events. The endpoint also contains an option for a health operation, which Axon Server uses to check its availability periodically. When the health check fails, Axon Server will no longer route commands and queries to this application and will no longer push events. Once the health check succeeds again, operations will resume.

Endpoints contain the following properties:

name

a logical name for the application

context

the Axon Server context

type

the communication protocol from Axon Server to the application

wrapping type

describes how messages Axon Server delivers to the application

content type

defines the content type of the payload of messages

base URL

the base address of the application, the format depends on the communication protocol

health URL

address of the health check (relative to the base URL)

command URL

the default address for command handlers (relative to the base URL)

query URL

the default address for query handlers (relative to the base URL)

event URL

the default address for event handlers (relative to the base URL)

properties

key/value pairs that Axon Server adds in the communication (dependent on the communication protocol)

The command, query, and event URL can contain placeholder {name} which Axon Server will replace with the registered handler’s actual name.

The wrapping type is one of the following values:

  • Raw, Axon Server sends the message payload in the request body; additional information is provided as headers.

  • Wrapped, Axon Server wraps the payload in a JSON message containing additional information.

Benefits of "Raw" wrapping type:

  • Smaller messages for binary payloads

  • Direct access to the payload

Benefits of "Wrapped" wrapping type:

  • Easier access to the message metadata

  • Support for batches of events

Axon Server does not know anything about the encoding of the request and event payloads. It uses the content-type property of the endpoint to pass the correct content type in the Raw handlers. It also uses the property to form the Wrapped message content. If the content-type is application/json, it embeds the JSON payload as part of the message. For application/xml or text/* content types it adds the payload as a string in the message. For all other content types it embeds the payload as a base64 encoded string.

Currently, Axon Server supports HTTP(s) and RSocket as communication protocols.

HTTP(s)

The URL for HTTP(s) endpoints is the server’s URL. Axon Server adds the custom properties defined on the endpoint as HTTP headers to each request. It expects the health URL to be a GET method, but all handlers must use POST methods.

If the endpoint uses HTTPS with a self-signed certificate, you must configure Axon Server to trust this certificate. You can add trusted certificates by setting the property axoniq.axonserver.integration.trust-manager-files in axonserver.properties.

For example:

axoniq.axonserver.integration.trust-manager-files=certificate-1.pem,certificate-2.pem

RSocket

The URL for RSocket endpoints is <hostname>:<port>. The command, query, and event URL represent the routing key in the RSocket message.

Axon Server adds the custom properties defined on the endpoint as metadata on the RSocket connection. Note that the keys for the custom properties must be media types.

For Raw messages the following additional metadata keys are included:

axonserver/x-PayloadType

The payload type for the Raw message.

axonserver/x-PayloadRevision

The payload revision for the Raw message.

axonserver/x-MessageId

A unique identifier for the message.

axonserver/x-Metadata

Optional metadata for the message.

axonserver/x-Priority

Priority of the request (commands and queries only).

axonserver/x-QueryName

The name of the query.

axonserver/x-CommandName

The name of the command.

axonserver/x-RoutingKey

Routing key for the command.

axonserver/x-EventName

The name of the event.

axonserver/x-DateTime

The date/time that the event was created (event only).

axonserver/x-Index

The global index of the event in the event store (event only).

axonserver/x-AggregateId

The aggregate identifier of the event (optional).

axonserver/x-AggregateType

The aggregate type of the event (optional).

axonserver/x-SequenceNumber

The sequence number of the event within the aggregate (optional).

All messages are request/reply messages.

Command handlers

To receive commands in your application, register a command handler at an endpoint. The registration of a command handler contains the following information:

name

the name of the command.

commandUrl

the (relative) address of the handler (can be omitted to use the default as defined on the endpoint) .

loadFactor

relative weight for this handler, if there are multiple handlers for a command, handlers with a higher load factor get a higher percentage of the requests.

Endpoint types

Axon Server can send requests containing commands in two different ways. Each endpoint that registers as a command handler must support one of them.

Raw

Axon Server serializes a single command directly into the request’s body when interacting with Raw endpoints. It provides all other relevant information in the HTTP headers of the request:

  • Content-Type

  • AxonIQ-MessageId

  • AxonIQ-CommandName

  • AxonIQ-PayloadType

  • AxonIQ-PayloadRevision

  • AxonIQ-Priority

Please refer to the API documentation for detailed information about the HTTP request structure.

Wrapped

When interacting with Wrapped endpoints, Axon Server generates a JSON message that contains the serialized command and all information related to the command. It then sends that JSON message in the request’s body.

Please refer to the API documentation for detailed information about the HTTP request structure.

Query handlers

Query handlers must explicitly register in Axon Server to receive queries. There are two ways to register a query handler - using Axon Server’s Web interface or through the Axon Server HTTP API.

In both cases, Axon Server needs the following information:

name

the name of the query that this handler can handle

query URL

the (relative) address of the handler (can be omitted to use the default as defined on the endpoint) .

Endpoint types

Axon Server can send requests containing queries in two different ways. Each endpoint that registers as a query handler must support one of them.

Raw

Axon Server serializes a single query directly into the request’s body when interacting with Raw endpoints. It provides all other relevant information in the HTTP headers of the request:

  • Content-Type

  • AxonIQ-MessageId

  • AxonIQ-QueryName

  • AxonIQ-PayloadType

Please refer to the API documentation for detailed information about the HTTP request structure.

Wrapped

When interacting with Wrapped endpoints, Axon Server generates a JSON message containing the serialized query and all related information. It then sends that JSON message in the request’s body.

Please refer to the API documentation for detailed information about the HTTP request structure.

Event handlers

Any service available at an accessible HTTP/RSocket address can be an event handler. Axon Server can send events to such services via HTTP/RSocket requests. The service must be able to handle requests containing events.

Event handlers must explicitly register in Axon Server to receive events. There are two ways to register an event handler - using Axon Server’s Web interface or through the Axon Server HTTP API.

In both cases, Axon Server needs the following information:

name

a name for the event handler. This name will be the name of the persistent stream serving the events.

filter

a filter for the events, for instance payloadType = "com.example.events.Event1"

sequencing policy

describes how events will be distributed across events

sequencing policy parameters

optional parameters for the sequencing policy

segments

number of parallel processing segments

start position

where to start processing events (HEAD for the newest event, TAIL for the oldest event)

event URL

the (relative) address of the handler (can be omitted to use the default as defined on the endpoint) .

batch size

the maximum number of events that Axon Server sends in one request to the handler if the endpoint type is Wrapped.

Event handlers are backed by persistent streams. To modify the number of segments, change the number of segments for the related persistent stream.

Endpoint types

Axon Server can send HTTP requests containing events in two different ways. Each endpoint that registers as an event handler must support one of them.

Raw

Axon Server serializes a single event directly into the request’s body when interacting with Raw endpoints. It provides all other relevant information in the headers of the request:

  • Content-Type

  • AxonIQ-MessageId

  • AxonIQ-EventName

  • AxonIQ-DateTime

  • AxonIQ-Index

  • AxonIQ-AggregateId

  • AxonIQ-AggregateType

  • AxonIQ-SequenceNumber

The Raw type supports sending any binary payload directly. Please refer to the API documentation for detailed information about the HTTP request structure.

Wrapped

When interacting with Wrapped endpoints, Axon Server generates a JSON message that contains a list of events. Each element includes a serialized event and all additional information relevant to the event.

Please refer to the API documentation for detailed information about the HTTP request structure.

Integration configuration

Administrators can configure the following properties for integrations:

axoniq.axonserver.integration.command-attempts

Sending commands to an endpoint is retried command-attempts times. Default value is 1.

axoniq.axonserver.integration.command-retry-backoff

The command-retry-backoff property defines the initial waiting time before retrying in milliseconds. After the first retry the retry time is increased exponentially. Default value is 10 milliseconds.

axoniq.axonserver.integration.query-attempts

Sending queries to an endpoint is retried query-attempts times. Default value is 1.

axoniq.axonserver.integration.query-retry-backoff

The query-retry-backoff property defines the initial waiting time before retrying in milliseconds. After the first retry the retry time is increased exponentially. Default value is 10 milliseconds.

axoniq.axonserver.integration.event-retry-backoff

Publishing events to an endpoint is retried as long as the endpoint is healthy and the event handler is registered. The event-retry-backoff property defines the initial waiting time before retrying in milliseconds. After the first retry the retry time is increased exponentially up to a maximum of 30 seconds. Default value is 10 milliseconds.

axoniq.axonserver.integration.trust-manager-files

Comma separated list of files of trusted certificate authorities.

axoniq.axonserver.integration.allow-insecure-trust-manager

Option to allow all insecure events when connecting to an HTTPS endpoint (default false).

Sending messages

You can send messages to Axon Server via HTTP requests. Axon Server supports four types of messages:

  • Commands

  • Queries

  • Events

  • Snapshots

In general, you can use two forms to send these requests to Axon Server:

  • Raw where the HTTP content is the actual payload of the message, and all additional information is in the HTTP headers

  • Wrapped, where the HTTP content is a JSON object containing the message together with all the relevant information

For the operations on the requests to send messages, check the Axon Server Integration API.

Sending commands

Any application that can not connect directly to Axon Server can still send commands through Axon Server’s HTTP APIs. This document explains the two ways to do so.

Axon Server routes commands based on a routing key in the request. If multiple handlers exist for the same command, Axon Server sends requests with the same routing key to the same handler. Command handlers often rely on the routing consistency provided by routing keys to cache data between requests.

The Raw endpoint

The Raw endpoint URL path follows the /v2/commands/[commandName] pattern. The content of the HTTP request is the serialized command. The sender may provide additional information through HTTP headers.

There is one required header:

  • Content-Type: the serialization type for the context

The following headers are optional:

  • AxonIQ-PayloadType: defines the type of the payload (if missing, the command name as the payload type)

  • AxonIQ-Priority: priority of the request (default is 0, a higher value means higher priority)

  • AxonIQ-RoutingKey: the key used for routing (auto-generated if missing) The code below represents a sample request to the http-raw endpoint sending an io.axoniq.demo.giftcard.api.IssueCardCommand.

POST http://axonserver:8024/v2/commands/io.axoniq.demo.giftcard.api.IssueCardCommand?context=context1
Content-Type: application/xml

<io.axoniq.demo.giftcard.api.IssueCardCommand>
  <id>sample-card-5</id>
  <amount>110</amount>
</io.axoniq.demo.giftcard.api.IssueCardCommand>

Axon Server then delegates the command to a command handler registered in the context1 context.

For more details about the Raw endpoint, please refer to the Send Command API docs.

Wrapped endpoint

The Wrapped endpoint URL path follows the /v2commands pattern. The content of the HTTP request is a JSON message containing all the information for a single command. Below is the above request in Wrapped form.

POST http://axonserver:8024/v2/commands?contexts=default
Content-Type: application/json

{
  "payload": "<io.axoniq.demo.giftcard.api.IssueCardCommand><id>sample-card-5</id><amount>110</amount></io.axoniq.demo.giftcard.api.IssueCardCommand>"
  "name": "io.axoniq.demo.giftcard.api.IssueCardCommand"
}

The message may contain additional optional fields like payloadType, routingKey, priority, and metaData.

The serialization format of the query object must match the serialization the query handler expects. Even though the HTTP payload is JSON, if the query handler expects XML, the payload must be XML. If the handler expects a JSON serialized payload, the request would be:

POST http://axonserver:8024/v2/commands?contexts=default
Content-Type: application/json

{
  "payload": {
   "id": "sample-card-5",
   "amount": 110
   },
  "name": "io.axoniq.demo.giftcard.api.IssueCardCommand"
}

For more details about the Wrapped endpoint, please refer to the Send Command Message API docs.

Sending queries

Any application that can not connect directly to Axon Server can still send queries to it through Axon Server’s HTTP APIs. This document explains the two ways to do so.

Axon Server’s HTTP query endpoint only supports request-response queries. It’s unable to take care of subscription queries at this moment.

The Raw endpoint

The Raw endpoint URL path follows the /v1/queries/[queryName]?context=[contextName] pattern. The content of the HTTP request is the serialized query. The sender may provide additional information through HTTP headers.

There is one required header:

  • Content-Type: the serialization type for the context

The following headers are optional:

  • AxonIQ-PayloadType: defines the type of the payload (if missing, the command name is the payload type)

  • AxonIQ-ResponseType: the expected response type (required when the handler uses Axon Framework)

  • AxonIQ-ResponseCount: use MULTIPLE to indicate that the query handler can return multiple instances of the response type

The code below represents a sample request to the Raw endpoint sending an io.axoniq.demo.giftcard.api.FetchCardSummariesQuery.

POST http://axonserver:8024/v2/queries/io.axoniq.demo.giftcard.api.FetchCardSummariesQuery?contexts=default
Content-Type: application/xml
AxonIQ-ResponseType: io.axoniq.demo.giftcard.api.CardSummary
AxonIQ-ResponseCount: MULTIPLE

<io.axoniq.demo.giftcard.api.FetchCardSummariesQuery>
    <offset>0</offset>
    <limit>100</limit>
</io.axoniq.demo.giftcard.api.FetchCardSummariesQuery>

Axon Server then delegates the query to a query handler registered in the default context. When the handler responds with a zero or more io.axoniq.demo.giftcard.api.CardSummary objects, Axon Server serializes the payload and sends it back in the response payload of the HTTP request.

For more details about the Raw endpoint, please refer to the Send Query API docs.

The Wrapped endpoint

The Wrapped endpoint URL path follows the /v2/queries?context=[contextName] pattern. The content of the HTTP request is a JSON message containing all the information for a single query. Below is the above request in Wrapped form.

POST http://axonserver:8024/v2/queries?contexts=default
Content-Type: application/json

{
  "payload": "<io.axoniq.demo.giftcard.api.FetchCardSummariesQuery><offset>0</offset><limit>100</limit></io.axoniq.demo.giftcard.api.FetchCardSummariesQuery>"
  "name": "io.axoniq.demo.giftcard.api.FetchCardSummariesQuery",
  "responseType": "io.axoniq.demo.giftcard.api.CardSummary"
}

The message may contain additional optional fields like payloadType and metaData. You can use the payloadType field to specify the payload type in cases where the query name doesn’t equal the payload type for the query message.

The serialization format of the query object must match the serialization the query handler expects. Even though the HTTP payload is JSON, if the query handler expects XML, the payload must be to XML. If the handler expects a JSON serialized payload, the request would be:

POST http://axonserver:8024/v2/queries?contexts=default
Content-Type: application/json

{
  "payload": {
   "offset": 0,
   "limit": 100
   },
  "name": "io.axoniq.demo.giftcard.api.FetchCardSummariesQuery",
  "responseType": "io.axoniq.demo.giftcard.api.CardSummary"
}

For more details about the Wrapped endpoint, please refer to the Send Query Message API docs.

Sending events

Any application that can not connect directly to Axon Server can still send events to it through Axon Server’s HTTP APIs. This document explains the two ways to do so.

The Raw endpoint

The Raw endpoint URL path follows the /v1/events/[eventName]?context=[contextName] pattern. The content of the HTTP request is the serialized event. The sender may provide additional information through HTTP headers.

There is one required header:

  • Content-Type: the serialization type for the context

The following headers are optional:

  • AxonIQ-AggregateId:

  • AxonIQ-AggregateType:

  • AxonIQ-SequenceNumber:

  • AxonIQ-DateTime:

The code below represents a sample request to the Raw endpoint sending a local.application.client.Event.

POST http://axonserver:8024/v2/events/local.application.client.Event?context=default
Content-Type: application/json
AxonIQ-AggregateId: 901aa5ce-b281-4788-97f2-2be7f236dde6
AxonIQ-AggregateType: Aggregate
AxonIQ-SequenceNumber: 0
AxonIQ-DateTime: 2022-09-22T21:37:00.000+00:00

{
   "id": "901aa5ce-b281-4788-97f2-2be7f236dde6",
   "text": "New customer created"
}

Axon Server stores the event in the default context of the event store as specified in the request’s URL.

For more details about the Raw endpoint, please refer to the Publish Event API docs.

The Wrapped endpoint

The Wrapped endpoint can be used to send multiple events in a single transaction.

The Wrapped endpoint URL path follows the /v1/events?context=[contextName] pattern. The content of the HTTP request is a JSON array of messages, each containing all the information for a single event. Below is the above request in Wrapped form.

POST http://axonserver:8024/v2/events?context=default
Content-Type: application/json

[{
  "payload": {
    "id": "901aa5ce-b281-4788-97f2-2be7f236dde6",
    "text": "New customer created"
  },
  "name": "local.application.client.Event",
  "aggregateId": "901aa5ce-b281-4788-97f2-2be7f236dde6",
  "aggregateType": "Aggregate",
  "sequenceNumber": 0,
  "dateTime": "2022-09-22T21:37:00.000+00:00"
}]

The JSON payload may contain additional optional fields such as metaData.

For more details about the Wrapped endpoint, please refer to the Publish Event Message API docs.

Sending snapshots

Any application that can not connect directly to Axon Server can still send snapshots to it through Axon Server’s HTTP APIs. This document explains the two ways to do so.

The Raw endpoint

The Raw endpoint URL path follows the /v1/snapshots/[aggregeteId]?context=[contextName] pattern. The content of the HTTP request is the serialized snapshot. The sender may provide additional information through HTTP headers.

There are three required headers:

  • Content-Type: the serialization type for the context

  • AxonIQ-AggregateType:

  • AxonIQ-SequenceNumber:

The following headers are optional:

  • AxonIQ-DateTime:

The sequence number of a snapshot must be less than or equal to the last event stored for the aggregate.

The code below represents a sample request to the Raw endpoint sending a local.application.client.Snapshot.

POST http://axonserver:8024/v2/snapshots/my-aggregate-id?context=default
Content-Type: application/json
AxonIQ-AggregateType: Aggregate
AxonIQ-SequenceNumber: 0
AxonIQ-DateTime: 2022-09-22T21:37:00.000+00:00

{
   "id": "my-aggregate-id",
   "name": "Customer name"
}

Axon Server stores the snapshot in the default context of the event store as specified in the request’s URL.

For more details about the Raw endpoint, please refer to the Publish Snapshot API docs.

The Wrapped endpoint

The Wrapped endpoint URL path follows the /v1/snapshots?context=[contextName] pattern. The content of the HTTP request is a JSON message containing all the information for a snapshot. Below is the above request in Wrapped form.

POST http://axonserver:8024/v2/snapshots?context=default
Content-Type: application/json

[{
  "payload": {
   "id": "my-aggregate-id",
   "name": "Customer name"
  },
  "name": "local.application.client.Snapshot",
  "aggregateId": "my-aggregate-id",
  "aggregateType": "Aggregate",
  "sequenceNumber": 0,
  "dateTime": "2022-09-22T21:37:00.000+00:00"
}]

The JSON payload may contain additional optional fields such as metaData.

For more details about the Wrapped endpoint, please refer to the Publish Snapshot Message API docs.

Reading events and snapshots

Next to the API to publish events and snapshots to Axon Server, there is also an HTTP API to read aggregate events and snapshots from the Axon Server event store. The next sections describe the provided operations.

Read aggregate events

The endpoint /v2/aggregates/[aggregate-id]/events?context=[context] returns all the events for the given aggregate. It is possible to reduce the number of events returned by specifying the minSequence parameter. This will only return the events with a sequence number equal to or larger than the given value.

The result of the operation is a list of event messages starting with the event with the lowest sequence number.

Read aggregate events (paged)

The endpoint /v2/aggregates/[aggregate-id]/eventsPaged?context=[context]&pageOffset=[offset]&pageSize=[pageSize] returns one page of events for the given aggregate.

The result of the operation is a list of event messages starting with the event with the lowest sequence number.

Read aggregate snapshots

The endpoint /v2/aggregates/[aggregate-id]/snapshots?context=[context] returns snapshots for the given aggregate. It is possible to reduce the number of snapshots returned by specifying the minSequence and/or maxResults parameter. The maxResults parameter, default value is one, determines how many snapshots will be returned. The minSequence parameter ensures that the operation will only return the snapshots with a sequence number equal to or larger than the given value.

The result of the operation is a list of snapshot messages, starting with the snapshot with the highest sequence number.