Apache Qpid AMQP 1.0 JMS client
Connection Factory
The Apache Qpid JMS API for AMQP 1.0 has its own connection factory, which is used to resolve the JNDI properties. The properties file has to contain the identification of the context factory:
java.naming.factory.initial=org.apache.qpid.amqp_1_0.jms.jndi.PropertiesFileInitialContextFactory
Connection URI
The connection URI specifies where the AMQP client should connect and what connection parameters should be used. In the JNDI properties, the connection URI should be placed like this:connectionfactory.[jndiname]=<ConnectionURL>
for example:connectionfactory.connection=<ConnectionURL>
For connecting to Eurex Clearing interfaces the connection string needs to specify:
- The correct IP address/hostname of the broker
- The correct port of the broker
- The path to the keystore with the client certificate
- Alias of the member certificate in the keystore
- The path to the truststore with the broker public keys
- Passwords for the keystore and truststore
Example connection string:
amqps://<Username>:<Password>@<Hostname>:<Port>?clientid=<ClientID>&trust-store=<PathToTruststore>&trust-store-password=<TruststorePassword>&key-store=<PathToKeystore>&key-store-password=<KeystorePassword>&ssl-cert-alias=<KeystoreAlias>
The username and password are not mandatory, because the authentication will be based only on the certificate. The client ID is the identifier of a Member application and can be defined according to the Member’s needs. An example connection string for the Eurex Clearing FIXML Interface may then look like this:
amqps://:@ecag-fixml-simu1.deutsche-boerse.com:10170?clientid=my-test-client1&trust-store=truststore.jks&trust-store-password=123456&key-store= ABCFR_ABCFRALMMACC1.keystore&key-store-password=123456&ssl-cert-alias=abcfr_abcfralmmacc1
Unlike the AMQP 0-10 client, the 1.0 client doesn’t support automatic reconnect / failover. It also doesn’t support heartbeat (idle timeout) configuration.
Addresses
Addresses are used to describe the message target or message source.10 The address is a string, which is passed as a parameter to a receiver or a sender, where it is handled. An address always resolves to a node – either queue or topic. This chapter will focus on the specific address strings, which can be used to interact with the Eurex Clearing interfaces.
Every application needs 4 different address string types in order to fully utilize the Eurex Clearing interfaces:
- Receiving broadcasts
- Receiving responses
- Sending requests
- “ReplyTo” address in requests
In the JNDI properties, the type destination should be used for all addresses:
destination.[jndiname]=<Address>
For example:
destination.requestAddress=<Address>
Receiving responses to requests
As described in the Eurex Clearing FIXML/FpML/Margin Calculator Interface Specification, “Volume E: AMQP Setup & Internals”, receiving responses to requests can be done either using an auto-delete response queue which has to be created by the client application and bound to the response exchange or using the predefined response queue. Unlike the AMQP 0-10 client, which receives the responses using the auto-delete response queues, the 1.0 client is already using the predefined response queue.
The following address string can be used as a template:
<ResponseQueueName>
The placeholders in this template have to be replaced with the appropriate values:
response.ABCFR_ABCFRALMMACC1
Sending requests
The request messages should be sent to the request exchange, which is specific for each Member. Since the request exchange is already predefined, the address string is simpler than the address string for receiving responses:
<RequestExchange>
The placeholders in this template have to be replaced with the appropriate values:
request.ABCFR_ABCFRALMMACC1
“ReplyTo” address in requests
The “ReplyTo” address is assigned as a property to the request message. It encodes both the reply to exchange as well as the reply to routing key:
<ResponseExchange>/<ResponseRoutingKey>
The placeholders in this template have to be replaced with the appropriate values:
response/response.ABCFR_ABCFRALMMACC1
The response to a request message sent with the reply to address above can be received by a receiver created using the example address from chapter 3.4.3.1.
Receiving broadcasts
To receive broadcast messages, it is necessary to create a receiver on the broadcast queues predefined during the technical maintenance. The following address string can be used as a template:
<PredefinedBroadcastQueue>
The <PredefinedBroadcastQueue> placeholder has to be replaced by the real name of the Members’ broadcast queue. The address string corresponding to the queue for the trade confirmation broadcast stream of Member ABCFR, account ABCFR_ABCFRALMMACC1 will be as follows:
broadcast.ABCFR_ABCFRALMMACC1.TradeConfirmation
Performance
Receive pre-fetching
AMQP brokers typically push messages to client consumers without explicit client requests (asynchronously, in the background) up to a certain number of unsettled messages. The next time a message would be passed on to the application code, it is usually taken from this buffer (avoiding synchronous I/O). This buffering capacity of a client is configurable and it is typically set to hundreds of messages by default. Setting it too low can have a negative impact on message throughput (less overlap of message processing and background I/O). Setting it too high can have a negative impact on client memory consumption (pre-fetch buffers need to hold many messages). Also, all messages pre-fetched by one consumer are “locked” to that consumer (and will not be delivered to any other consumer reading the same queue) until the consumer releases/rejects them. This can lead to a less than ideal load balancing in case of parallel consumption and processing of messages from a single broker queue.
In Apache Qpid AMQP 1.0 client, the pre-fetch capacity can be specified in the connection address string, e.g.:
amqps://:@ecag-fixml-simu1.deutsche-boerse.com:10170?clientid=my-test-client1&trust-store=truststore&trust-store-password=123456&key-store= ABCFR_ABCFRALMMACC1.keystore&key-store-password=123456&ssl-cert-alias=abcfr_abcfralmmacc1&max-prefetch=1000
Sender synchronization
When sending messages (as shown in section 3.2.6.2), the send call is asynchronous by default. This means that a message being sent is not guaranteed to arrive at a broker by the time the send call returns in a client application.
Send calls in JMS can be made synchronous (i.e. return only after message delivery was confirmed by the broker) via the “sync-publish” connection parameter, e.g.:
amqps://:@ecag-fixml-simu1.deutsche-boerse.com:10170?clientid=my-test-client1&trust-store=truststore&trust-store-password=123456&key-store= ABCFR_ABCFRALMMACC1.keystore&key-store-password=123456&ssl-cert-alias=abcfr_abcfralmmacc1&sync-publish=true
However, this can have a significant negative impact on performance in case of a significant network latency between the client and the server. Unlike in C++, it is not possible to invoke explicit session synchronization in JMS (to achieve block or batch sending and mitigate the negative impact of network latency).
Logging
The Apache Qpid JMS AMQP 1.0 client libraries use Java Logging API (java.util.logging). More information about using and configurint the Java Logging framework can be found on:
http://docs.oracle.com/javase/8/docs/technotes/guides/logging/overview.html
To enable the logging of AMQP frames sent / received by the client, the Frame logger can be used:
FRM.level=ALL
Additionally, Raw logger can be used to display the RAW AMQP data which the client sends / receives:
RAW.level=ALL
10. Client APIs from other providers will use a different approach for defining message targets and sources. Please refer to the documentation of the used API for more details. ↩