Programming Guide
- Programming Guide
- Introduction
- Supported Eurex T7 Release
- Typical Usage
- Settings
- Initialization
- Connection Establishment
- User Logon
- Sending Messages
- User Logout
- Connection Termination
- Shutdown
- Performance Tuning
- Message Observability
- Retransmission
- Threads and Callbacks
- Message Thread Safety
- Error and Warning Listeners
- Incoming Message Event Listeners
Introduction
Onix Solutions Eurex ETI Handler is a Java library that provides access to the Eurex ETI service. The Eurex Enhanced Trading Interface is a system that provides the necessary functionality to effectively trade and post markets with Eurex trading systems and provides users with the basic information suitable for formulating trading decisions. The Eurex ETI API allows third parties to develop their own applications that use the Eurex system.
Below are the key features of the Eurex ETI Handler:
- Full access to the Eurex ETI functionality
- Easy-to-use API
It's highly recommended to read the “Eurex Enhanced Trading Interface - Manual Simulation” document before reading this guide to get familiar with the core aspects of Eurex ETI service. It's also highly recommended to review the source code of the sample project, which comes as part of the library's distributive package alongside reading this guide.
It's also important to become familiar with the concept of message identification. Each ETI message is identified by a unique template ID, represented by the biz.onixs.eurex.eti.handler.message.value.TemplateId enum. Understanding how messages are identified is essential for correctly handling incoming messages and constructing outgoing ones.
Supported Eurex T7 Release
OnixS Eurex T7 ETI Trading Handler supports Enhanced Trading Interface Derivatives Message Reference Release 15.0.
Typical Usage
The typical way of using the handler follows.
- Adjust handler settings.
- Initialize the handler.
- Register error and warning listeners.
- Register listeners for incoming messages.
- Establish the connection.
- Make user logon request.
- Start sending messages.
- Make user logout request.
- Terminate the connection.
- Shutdown the handler.
Here is a small example of how to get started with the Handler:
final HandlerSettings settings = new HandlerSettings();
settings.getConnectionSettings().setRemoteAddress("localhost", 10000);
final Handler handler = new Handler();
handler.init(settings);
try {
handler.setErrorListener(this);
handler.setWarningListener(this);
final MyHandlerStateListener stateListener = new MyHandlerStateListener();
handler.setHandlerStateListener(stateListener);
final LogonRequest logonRequest = new LogonRequest();
logonRequest.setDefaultCstmApplVerId(Handler.getDefaultCstmApplVerId());
// setting other logon request fields
handler.connect(logonRequest);
// connect() only accepts the request; wait for the session before sending anything
if (!stateListener.awaitState(HandlerState.CONNECTED, 10000)) {
throw new HandlerException("The handler did not connect");
}
final UserLoginRequest userLoginRequest = new UserLoginRequest();
// setting user login request fields
handler.send(userLoginRequest);
final NewOrderRequest newOrderRequest = new NewOrderRequest();
// setting order fields
handler.send(newOrderRequest);
final UserLogoutRequest userLogoutRequest = new UserLogoutRequest();
// setting user logout request fields
handler.send(userLogoutRequest);
handler.disconnect();
if (!stateListener.awaitState(HandlerState.DISCONNECTED, 10000)) {
System.out.println("The session did not end within 10 s; shutting down anyway.");
}
} finally {
// In a finally block: a handler that is not shut down keeps its threads alive, and
// cannot be initialized again.
handler.shutdown();
}
Settings
Settings can be configured programmatically (via API) or via a properties file.
Programmatic Configuration
Any available option can be set via API.
final HandlerSettings settings = new HandlerSettings();
settings.getConnectionSettings().setRemoteAddress("localhost", 10000);
Properties File Configuration
Settings can be loaded from the properties file:
final HandlerSettings settings = new HandlerSettings();
settings.init("site/handler.properties");
The sample properties file follows. Not all available options are mentioned.
Host = 193.29.89.65
Port = 19508
SslEnabled = true
Timeout = 5
LogonTimeout = 30
RSAKeyPath = /path/to/eurex-public-key.pem
HeartbeatInterval = 30000
ReconnectionSettings.Number = 3
ReconnectionSettings.Interval = 30
Property List
The configuration parameter (key) is case-sensitive. The list of available parameters follows.
| Property Name | Type | Default Value | Description |
|---|---|---|---|
| Host | String | Sets the remote host to connect to. | |
| Port | int | Sets the remote port to connect to. | |
| SslEnabled | boolean | false | Enables TLS/SSL for the connection. |
| Timeout | int | 1 | Sets the connect/disconnect timeout in seconds, and the socket read timeout used while waiting for data. Allowed values are from 1 till 2147483. |
| LogonTimeout | int | 30 | Seconds to wait for the exchange to answer a logon before the connection attempt is abandoned. Allowed values are from 1 till 86400. |
| RSAKeyPath | String | Sets the path to the RSA public key file used for encrypted password (see LogonRequestEncrypted). | |
| LicenseFile | String | “OnixS.lic” | Sets the license file. |
| LicenseDirectory | String | “.” | Sets the license directory. |
| LicenseContent | String | Sets the license file content explicitly. | |
| ReconnectionSettings.Number | int | 3 | Number of retries per connection attempt run. The handler makes Number + 1 total attempts (1 initial + Number retries). Set to 0 to disable automatic reconnection. |
| ReconnectionSettings.Interval | int | 30 | Seconds to wait between failed connection attempts within a single reconnect run. |
| HeartbeatInterval | int | 30000 | Sets the heartbeat interval in milliseconds. Allowed values are from 100 till 60000. |
| ReasonableTransmissionTime | int | 20 | Sets the reasonable transmission time as a percentage of the heartbeat interval. Used to compute the socket read timeout: HeartbeatInterval + HeartbeatInterval × RTT / 100. |
| LocalAddress.Host | String | Sets the local host to use for connection. | |
| LocalAddress.Port | int | Sets the local port to use for connection. | |
| AddressMapping.N.From.Host | String | Source host of the Nth address mapping rule (N starts at 1). | |
| AddressMapping.N.From.Port | int | Source port of the Nth address mapping rule. | |
| AddressMapping.N.To.Host | String | Target host of the Nth address mapping rule. | |
| AddressMapping.N.To.Port | int | Target port of the Nth address mapping rule. |
Initialization
The handler is initialized with the settings.
// Handler initialization
handler = new Handler();
handler.init(settings);
Initialization validates the license, applies the settings and starts the handler's threads. The
handler moves from NOT_INITED to DISCONNECTED and is then ready to connect.
The same handler instance can be initialized again after a shutdown - that is the
supported way to reuse it. init() throws a
has not finished, which in practice means a shutdown() that has not been called or a listener
callback that has not returned. Call shutdown() and let it return before initializing again.
Connection Establishment
For connection establishment, do the following.
LogonRequest logonRequest = new LogonRequest();
logonRequest.setDefaultCstmApplVerId(Handler.getDefaultCstmApplVerId());
// fill `logonRequest` with other credentials
handler.connect(logonRequest);
// connect() is asynchronous: wait for the handler to report CONNECTED before sending.
final boolean connected = stateListener.awaitState(HandlerState.CONNECTED, 10000);
if (!connected) {
LOG.error("The handler did not connect within 10 s");
}
connect() is asynchronous: it accepts the request and returns, and the handler establishes the
session on its own thread. The handler is not connected when the call returns - watch the
state to learn when it is. A connect request that cannot reach the exchange is
retried according to biz.onixs.eurex.eti.handler.core.ReconnectionSettings
before the handler settles on DISCONNECTED.
The call throws a biz.onixs.eurex.eti.handler.core.HandlerException when the request cannot be accepted at all:
- the handler is already connected - call
disconnect()first; - the handler has been shut down - call
init()to reopen it; - a
shutdown()is in progress, so the request could not be queued.
A connect() issued immediately after a disconnect() is not refused. The disconnect is
asynchronous, so the handler is often still CONNECTED when the connect arrives; the two requests
take effect in the order they were issued, leaving the handler connected on the new session.
Address Mapping and Failover
The handler does not implement gateway failover directly. Instead, it provides an biz.onixs.eurex.eti.handler.core.AddressMapping mechanism that transparently redirects a configured address to a different physical endpoint at connect time.
Mappings can be added programmatically via biz.onixs.eurex.eti.handler.core.ConnectionSettings.addAddressMapping(String, int, String, int):
settings.getConnectionSettings().addAddressMapping(
"10.8.0.1", 19542,
"10.8.0.1", 19547);
Alternatively, mappings can be defined in the properties file using the AddressMapping.N.*
keys listed in the Property List:
AddressMapping.1.From.Host = 10.8.0.1
AddressMapping.1.From.Port = 19542
AddressMapping.1.To.Host = 10.8.0.1
AddressMapping.1.To.Port = 19547
User Logon
To do user logon create the corresponding message object, set the field values and send it.
final UserLoginRequest userLoginRequest = new UserLoginRequest();
userLoginRequest.setUsername(111);
userLoginRequest.setPassword("password");
handler.send(userLoginRequest);
Sending Messages
To send application level message create the message object, set the field values and send it.
final NewOrderRequest newOrderRequest = new NewOrderRequest();
// setting order fields
// send() returns false when the outbound queue is full: production code checks it.
handler.send(newOrderRequest);
send() queues the message for the current session and returns as soon as it is queued - a true
return means the message was accepted onto the outbound queue, not that it has reached the exchange.
It returns false when the queue is full, and throws when the connection is down, which is what a
caller sees while a session is being re-established.
Queuing is bound to the session in place at the time of the call: a message still queued when that session ends is discarded and reported to the error listener rather than sent on the next session. See Connection Termination.
There is one documented exception. A send() that is descheduled between its internal connection
check and the enqueue, and stays off-CPU across an entire teardown and reconnect, can have its
message picked up by the new session instead of discarded. It is not reachable at normal scheduling
latencies, and it is the only case in which a message crosses a session boundary - but an application
that must never send an order against a session it did not intend should key on its own state rather
than rely on this binding alone.
User Logout
To do user logout create the corresponding message object, set the fields values and send it.
final UserLogoutRequest userLogoutRequest = new UserLogoutRequest();
userLogoutRequest.setUsername(111);
handler.send(userLogoutRequest);
Connection Termination
For connection termination, do the following.
handler.disconnect();
// disconnect() is asynchronous too: wait for DISCONNECTED to know the session has ended.
// Nothing is published when the handler was not connected, so do not treat a timeout here
// as a failure on its own.
if (!stateListener.awaitState(HandlerState.DISCONNECTED, 10000) && connected) {
LOG.error("The session did not end within 10 s");
}
disconnect() is asynchronous, like connect(): it accepts the request and returns, and the
session is torn down on the handler's own thread. Watch for DISCONNECTED to learn when the session
has ended. Calling it on a handler that is already DISCONNECTED is harmless and publishes no
transition at all, so code that waits for DISCONNECTED after every disconnect() should tolerate a
handler that was not connected in the first place. Calling it while a connect is still in flight does
end that attempt, and DISCONNECTED is published when it does.
The handler publishes DISCONNECTING and then ends the session gracefully where it can: it sends a
LogoutRequest and waits for the exchange's LogoutResponse. When a graceful logout is not possible
(the outbound queue is full, or the connection has already gone), it closes the connection instead,
and the same applies when the logout handshake does not complete in time. DISCONNECTING is
published either way; what differs is whether a logout reaches the exchange, and how long the
teardown takes.
Messages still queued for the session when it ends are discarded, not carried over to a later session, and each one is reported to the error listener.
Automatic Disconnection
The handler terminates the session on its own in the following cases:
- Remote close (EOF): the exchange closes the TCP connection; the inbound stream signals end-of-stream and the receiver exits cleanly.
- I/O error: any unrecoverable exception on the receive path triggers an immediate disconnect.
- Failed outbound send: when a message cannot be written to the connection, the handler treats
it as a connection loss: the session is torn down and, if reconnection is enabled, re-established.
Any other failure on the sending path, for example a message whose
toString()throws, is treated the same way.
In each of these the connection is already closed by the time the session is torn down, so no
graceful logout is attempted. The teardown is still observable in the usual way: the handler
publishes CONNECTED → DISCONNECTING → DISCONNECTED, exactly as it does for an application
disconnect().
One case that looks like it belongs on that list does not: an unexpected logoff. A
LogoutResponse arriving outside a disconnect() stops the receiving thread, but on its own it
neither closes the connection nor changes the handler state, so the handler stays CONNECTED and no
reconnection is triggered. Treat an unsolicited LogoutResponse - delivered to the
signal to call disconnect() yourself.
Note on heartbeat timeout: a socket read timeout (derived from HeartbeatInterval and
ReasonableTransmissionTime) is used only as an anti-hang guard on the read loop and does not
close the connection by itself. Only an actual TCP close or hard I/O error triggers a disconnect.
Note on the logon timeout: an exchange gateway that accepts the TCP connection and then does not
answer the logon would otherwise leave the handler in CONNECTING for as long as it stayed silent.
LogonTimeout bounds that wait. When it elapses the attempt is abandoned like any other failed
attempt - the connection is closed, DISCONNECTED is published, and ReconnectionSettings decides
whether and when to try again. It is distinct from Timeout, which bounds establishing the
connection rather than the logon that follows it, and it holds whether the gateway stays silent or
sends part of an answer and then stops. Setting Timeout higher than LogonTimeout does not weaken
it.
Reconnection
Reconnection behavior is controlled via biz.onixs.eurex.eti.handler.core.ReconnectionSettings, configured as part of biz.onixs.eurex.eti.handler.core.HandlerSettings.
When ReconnectionSettings.Number > 0 and an unexpected connection loss is detected, the handler:
- Ends the lost session:
CONNECTED → DISCONNECTING → DISCONNECTED. The connection is already gone at that point, so noLogoutRequestis sent and the teardown completes without waiting for one. - Discards anything still queued for that session and reports it to the error listener.
- Resets the outbound
MsgSeqNumto 1 (a fresh session is started on each reconnect). - Makes up to
Number + 1total connection attempts (1 initial attempt plus up toNumberretries), waitingIntervalseconds between failed attempts (default: 3 retries, 30 s apart).
The handler reconnects with the same logon message that established the lost session. To reconnect
with different credentials, call connect() explicitly with the new logon - an application
connect() takes precedence, and the handler does not add an automatic attempt alongside it.
If all attempts fail the handler stays DISCONNECTED. If a later reconnect succeeds and the
connection is lost again, the same cycle repeats with a fresh attempt budget. There is no cumulative
cap on reconnect cycles. Set ReconnectionSettings.Number = 0 to disable automatic reconnection.
A disconnect() or shutdown() issued while a reconnect is in flight takes effect promptly: it ends
the attempt in progress, including one waiting out the Interval backoff, and the handler does not
try again.
The relevant properties are listed in the Property List.
State Monitoring
Implement the biz.onixs.eurex.eti.handler.core.event.HandlerStateListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setHandlerStateListener(HandlerStateListener) to be notified of every state transition.
final MyHandlerStateListener stateListener = new MyHandlerStateListener();
handler.setHandlerStateListener(stateListener);
public class MyHandlerStateListener implements HandlerStateListener {
private static final Logger LOG = LoggerFactory.getLogger(MyHandlerStateListener.class);
private final Object lock = new Object();
// Until the first transition arrives. A listener registered after init() has therefore not seen
// the DISCONNECTED that init() published; seed this from handler.getState() if that matters.
private HandlerState state = HandlerState.NOT_INITED;
public void onStateChange(HandlerState oldState, HandlerState newState) {
LOG.info("Handler state changed: {} -> {}", oldState, newState);
// Runs on whichever thread made the transition: a handler thread, or the application's own
// thread for the transitions init() and shutdown() publish. Return promptly either way.
synchronized (lock) {
state = newState;
lock.notifyAll();
}
}
/**
* Waits for the handler to reach {@code expected}, which is how an application learns that an
* asynchronous connect() or disconnect() has taken effect.
*
* <p>This tracks the latest state rather than every transition, so a state the handler enters and
* leaves again before this is scheduled is not observed. That is enough for the connect and
* disconnect waits shown in the guide; an application that must not miss a transition should
* record what it needs inside {@code onStateChange()} instead.
*
* @return true if the handler reached the state within the timeout
*/
public boolean awaitState(HandlerState expected, long timeoutMs) throws InterruptedException {
final long deadline = System.currentTimeMillis() + timeoutMs;
synchronized (lock) {
while (state != expected) {
final long remaining = deadline - System.currentTimeMillis();
if (remaining <= 0) {
return false;
}
lock.wait(remaining);
}
return true;
}
}
}
The handler moves through the following states: NOT_INITED → DISCONNECTED → CONNECTING → CONNECTED → DISCONNECTING → DISCONNECTED.
DISCONNECTING is published whenever an established session is being torn down, whether the
application asked for it or the connection was lost, and whether or not a graceful logout was
possible. A connect attempt that never established a session settles from CONNECTING instead, so
CONNECTING → DISCONNECTED is the trace of a failed attempt rather than of a session ending.
The callback runs on the handler thread that performed the transition, and on the calling thread for
the transitions init() and shutdown() publish. It is invoked synchronously, so a listener that
blocks holds up the operation in progress. A listener may call back into the handler - reconnecting
on DISCONNECTED is a normal thing to write - but it should check getState() first rather than
assume the request will be accepted, because an exception thrown out of a callback is logged rather
than propagated to the application.
Each individual reconnect attempt produces its own observable state-transition pair. With
ReconnectionSettings.Number = N and all attempts failing after an unexpected drop:
DISCONNECTED → CONNECTING → CONNECTED initial logon succeeded
CONNECTED → DISCONNECTING → DISCONNECTED unexpected drop detected
DISCONNECTED → CONNECTING → DISCONNECTED reconnect attempt 1 of N+1 failed
...
DISCONNECTED → CONNECTING → DISCONNECTED reconnect attempt N+1 of N+1 failed
The number of CONNECTING → DISCONNECTED transitions equals the number of failed attempts.
If a reconnect attempt succeeds the last pair becomes DISCONNECTED → CONNECTING → CONNECTED
and the handler resumes normal operation.
End-of-Day
The handler does not perform end-of-day cleanup automatically. The exchange signals the end of the
trading session via a biz.onixs.eurex.eti.handler.message.TradingSessionStatusBroadcast message
with tradSesEvent equal to TradSesEvent.END_OF_DAY_SERVICE, delivered to the biz.onixs.eurex.eti.handler.core.event.OtherListener.onTradingSessionStatusBroadcast(TradingSessionStatusBroadcast) callback.
The application should react to this event by performing any required cleanup and calling disconnect().
Shutdown
// Releases the handler's threads, and is reached even when the connect above failed, because
// a handler that is not shut down cannot be initialized again. Production code should call
// it from a finally block, as the getting-started sample does, so an exception cannot skip it.
handler.shutdown();
shutdown() ends any session the handler still has and releases its threads, leaving it
NOT_INITED. Unlike disconnect() it waits for the teardown - up to 5 seconds - so it is safe to
call from a finally block or a JVM shutdown hook.
It does not throw when the teardown does not finish in time. What is reported to the
error listener is the handler being left in a state NOT_INITED cannot be reached
from - the wait expiring is the usual reason for that, but a teardown that overruns the wait and then
completes still ends up NOT_INITED and is not reported. Reporting rather than throwing is what
keeps a shutdown() in a finally block from masking the exception being propagated. The handler
stays shut down either way, and a connect() racing the call is refused or abandoned rather than
left to establish a session afterwards.
A listener callback that has not returned can outlive shutdown(). Until it does, the thread it
occupies is still running and a following init() is refused.
To use the handler again, call init().
Performance Tuning
The handler uses a dedicated sender thread and a dedicated receiver thread per session, plus one thread for the connection lifecycle. No built-in benchmarks are provided; performance characteristics depend on the deployment environment and workload.
Thread Affinity
To reduce CPU cache misses the sender and receiver threads can be pinned to specific cores via biz.onixs.eurex.eti.handler.core.HandlerSettings.setSendingThreadAffinity(int[]) and biz.onixs.eurex.eti.handler.core.HandlerSettings.setReceivingThreadAffinity(int[]). Pass an array of zero-based CPU indices:
settings.setSendingThreadAffinity(new int[]{0});
settings.setReceivingThreadAffinity(new int[]{1});
Message Observability
While the handler logs all messages internally for debugging purposes (see Logging), these logs are not intended as a programmatic observability interface. To intercept messages - for auditing, persistence, or custom processing - implement the following listener interfaces that fire for every message flowing through the session, regardless of message type.
Inbound Messages
Implement the biz.onixs.eurex.eti.handler.core.event.InboundMessageListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setInboundMessageListener(InboundMessageListener) to receive a callback for every message received from the exchange.
handler.setInboundMessageListener(new MyInboundMessageListener());
public class MyInboundMessageListener implements InboundMessageListener {
private static final Logger LOG = LoggerFactory.getLogger(MyInboundMessageListener.class);
public void onInboundMessage(Message message) {
LOG.debug("Received {} seq={}: {}", message.getTemplateId(), message.getMsgSeqNum(), message);
}
}
Outbound Messages
Implement the biz.onixs.eurex.eti.handler.core.event.OutboundMessageListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setOutboundMessageListener(OutboundMessageListener) to receive a callback for every message sent to the exchange.
handler.setOutboundMessageListener(new MyOutboundMessageListener());
public class MyOutboundMessageListener implements OutboundMessageListener {
private static final Logger LOG = LoggerFactory.getLogger(MyOutboundMessageListener.class);
public void onOutboundMessage(Message message) {
LOG.debug("Sent {} seq={}: {}", message.getTemplateId(), message.getMsgSeqNum(), message);
}
}
Persistence and Querying
The handler does not persist messages internally. The listener callbacks above are the integration point for application-level persistence: write messages to a database, append them to a file, or publish them to a message bus as the application requires.
Note that the Message object passed to onInboundMessage is reused across callbacks for
performance - see Message Thread Safety if you need to hold a
reference beyond the callback.
Retransmission
The handler does not automatically detect gaps in the inbound sequence. The application is
responsible for tracking received sequence numbers - available via Message.getMsgSeqNum() in the biz.onixs.eurex.eti.handler.core.event.InboundMessageListener callback -
and requesting retransmission when a gap is detected.
Requesting Retransmission
Use biz.onixs.eurex.eti.handler.message.RetransmitRequest to request
retransmission of a missed sequence range. Set the refApplId to identify the stream (e.g.
RefApplId.TRADE), the partitionId, and the begin/end sequence numbers of the gap.
void requestRetransmit(Handler handler, int partitionId, long firstMissing, long lastMissing) {
RetransmitRequest request = new RetransmitRequest();
request.setRefApplId(RefApplId.TRADE);
request.setPartitionId(partitionId);
request.setApplBegSeqNum(firstMissing);
request.setApplEndSeqNum(lastMissing);
handler.send(request);
}
For Matching Engine messages (order and quote events) use biz.onixs.eurex.eti.handler.message.RetransmitMEMessageRequest instead, which identifies the range by message ID rather than sequence number.
Handling the Response
The exchange acknowledges the request and begins retransmission. The acknowledgement is delivered to the biz.onixs.eurex.eti.handler.core.event.AdminListener callbacks:
- biz.onixs.eurex.eti.handler.core.event.AdminListener.onRetransmitResponse(RetransmitResponse) for broadcast stream retransmission
- biz.onixs.eurex.eti.handler.core.event.AdminListener.onRetransmitMEMessageResponse(RetransmitMEMessageResponse) for Matching Engine message retransmission
The retransmitted messages themselves arrive through the same typed listeners as regular inbound messages.
Threads and Callbacks
The public methods of biz.onixs.eurex.eti.handler.core.Handler may be called from any thread. The handler runs its own threads and invokes the application's listeners on them:
| Callback | Thread it runs on |
|---|---|
| Inbound message, administrative and typed message listeners | the receiving thread, except for the LogonResponse of a session being established, which arrives on the thread carrying out the connect |
| Outbound message listener | the sending thread, except for the LogonRequest of a session being established, which is reported on the thread carrying out the connect |
| Handler state listener | the thread that made the transition - the handler's own lifecycle thread, or the calling thread for the transitions init() and shutdown() publish |
| Error and warning listeners | whichever thread produced the report, including the thread that called init() or shutdown() |
Two consequences matter in practice:
- A listener that blocks holds up the handler. A slow inbound listener stalls message receiving; a slow error or state listener stalls the connect or disconnect that is dispatching it. Do the work on an application thread and return promptly.
- An exception thrown by a listener is logged, not propagated. It never reaches the application
code that called
connect()orshutdown(), so a listener that calls back into the handler should checkgetState()rather than rely on catching a refusal.
Message Thread Safety
Message Receiving
For each message type the Handler has a static object that is used for deserialization and calling a user code callback. This means that you can't use reference to the message from the callback and need to create your own copy if you want to process the message later in a separate thread.
Message Sending
The Handler uses message objects passed to send method even after the user returns control from this method. There is a queue to which the Handler adds these objects and until they are serialized to bytes and sent over the network the user should not make any changes to these objects.
Error and Warning Listeners
Error Listener
The handler uses exceptions to report errors that occurred while performing a certain action. For example, the handler will raise a regular exception to report the inability to find an actual license for the product. However, the handler processes data asynchronously; therefore, the handler is not able to report any further errors since the data processing is started. For this reason, the handler exposes the
biz.onixs.eurex.eti.handler.core.event.ErrorListener interface and the biz.onixs.eurex.eti.handler.core.Handler.setErrorListener(ErrorListener)method to subscribe to error events.
handler.setErrorListener(new MyErrorListener());
Once an instance of error listener is assigned to the handler, it will invoke the
biz.onixs.eurex.eti.handler.core.event.ErrorListener.onError(ErrorCode, String)method each time an error occurs.
public class MyErrorListener implements ErrorListener {
private static final Logger LOG = LoggerFactory.getLogger(MyErrorListener.class);
public void onError(ErrorCode errorCode, String description) {
LOG.error("onError(): errorCode={}, description={}", errorCode, description);
}
}
Among the events reported this way, the following concern the session lifecycle and are worth
handling explicitly. All of them use ErrorCode.GENERAL.
- Outbound messages discarded because their session ended. When a session ends - on
disconnect(), on an unexpected loss, or on a connect attempt that never established one - the messages still queued for it are discarded. The handler reports a summary carrying the count and then one event per message, including its rendered content, so an order-management application can reconcile from the callback rather than from the exchange. - An outbound message dropped because the session was replaced. Reported when a message reaches the sending thread after the session it was queued for has been superseded.
- A connect request that was not carried out. Reported when a
connect()the handler accepted could not be started - for example when a secondconnect()arrives while the first is still establishing its session. - A
shutdown()that left the handler somewhere unexpected. Reported whenshutdown()could not reachNOT_INITED, naming the state it was left in. A teardown that overruns the wait and then completes is not reported.
These callbacks are dispatched on whichever thread produced the report - a handler thread, or the
thread that called init() or shutdown() - so keep them short. Note also that send() will not
accept a message while the connection is down: the discards reported when a session's queue is
drained are dispatched with the connection already closed, so calling send() from that callback
throws. Record what was lost and resubmit once the handler reports CONNECTED again.
Warning Listener
Miscellaneous non-critical issues may occur while the handler is being executed. The handler will process such issues by itself; thus, no special steps are required for such cases. However, sometimes it's reasonable to be notified about such events. For this reason, the handler exposes the
biz.onixs.eurex.eti.handler.core.event.WarningListener interface and the biz.onixs.eurex.eti.handler.core.Handler.setWarningListener(WarningListener)method to subscribe to warning events.
handler.setWarningListener(new MyWarningListener());
When an instance of warning listener is assigned to the handler, it will invoke the
biz.onixs.eurex.eti.handler.core.event.WarningListener.onWarning(String)method each time a warning occurs.
public class MyWarningListener implements WarningListener {
private static final Logger LOG = LoggerFactory.getLogger(MyWarningListener.class);
public void onWarning(String description) {
LOG.warn("onWarning(): description={}", description);
}
}
Incoming Message Event Listeners
Once the handler is started, it listens to messages from the Eurex ETI message flow, processes it, and invokes client code for further processing.
The handler processes messages asynchronously and uses the concept of events and event listeners to notify client code about a particular occasion, like the reception of a message.
Administrative Message Events
To be notified about administrative message events, implement the
biz.onixs.eurex.eti.handler.core.event.AdminListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setAdminListener(AdminListener).handler.setAdminListener(new MyAdminListener());
The sample interface implementation demonstrates available message events to receive.
public class MyAdminListener implements AdminListener {
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.Reject} message received.
* @param message message
*/
public void onReject(Reject message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.RetransmitMEMessageResponse} message received.
* @param message message
*/
public void onRetransmitMEMessageResponse(RetransmitMEMessageResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.RetransmitResponse} message received.
* @param message message
*/
public void onRetransmitResponse(RetransmitResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.SubscribeResponse} message received.
* @param message message
*/
public void onSubscribeResponse(SubscribeResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.UnsubscribeResponse} message received.
* @param message message
*/
public void onUnsubscribeResponse(UnsubscribeResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.UserLoginResponse} message received.
* @param message message
*/
public void onUserLoginResponse(UserLoginResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.UserLogoutResponse} message received.
* @param message message
*/
public void onUserLogoutResponse(UserLogoutResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.InquireSessionListResponse} message received.
* @param message message
*/
public void onInquireSessionListResponse(InquireSessionListResponse message) {
}
/**
* Notifies about the outgoing message.
* @param message message
*/
public void onOutboundMessage(Message message) {
}
/**
* Notifies about the inbound message.
* @param message message
*/
public void onInboundMessage(Message message) {
}
}
Order Handling Message Events
To be notified about order handling message events, implement the
biz.onixs.eurex.eti.handler.core.event.OrderHandlingListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setOrderHandlingListener(OrderHandlingListener).handler.setOrderHandlingListener(new MyOrderHandlingListener());
The sample interface implementation demonstrates available message events to receive.
class MyOrderHandlingListener implements OrderHandlingListener {
/**
* * Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteAllOrderNRResponse} message received.
* @param message message
*/
public void onDeleteAllOrderNRResponse(DeleteAllOrderNRResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteAllOrderBroadcast} message received.
* @param message message
*/
public void onDeleteAllOrderBroadcast(DeleteAllOrderBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteAllOrderResponse} message received.
* @param message message
*/
public void onDeleteAllOrderResponse(DeleteAllOrderResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteOrderBroadcast} message received.
* @param message message
*/
public void onDeleteOrderBroadcast(DeleteOrderBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteOrderNRResponse} message received.
* @param message message
*/
public void onDeleteOrderNRResponse(DeleteOrderNRResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteOrderResponse} message received.
* @param message message
*/
public void onDeleteOrderResponse(DeleteOrderResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.ModifyOrderNRResponse} message received.
* @param message message
*/
public void onModifyOrderNRResponse(ModifyOrderNRResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.ModifyOrderResponse} message received.
* @param message message
*/
public void onModifyOrderResponse(ModifyOrderResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.NewOrderNRResponse} message received.
* @param message message
*/
public void onNewOrderNRResponse(NewOrderNRResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.NewOrderResponse} message received.
* @param message message
*/
public void onNewOrderResponse(NewOrderResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.MassOrderAck} message received.
* @param message message
*/
@Override
public void onMassOrderAck(MassOrderAck message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.OrderExecNotification} message received.
* @param message message
*/
public void onOrderExecNotification(OrderExecNotification message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.OrderExecReportBroadcast} message received.
* @param message message
*/
public void onOrderExecReportBroadcast(OrderExecReportBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.OrderExecResponse} message received.
* @param message message
*/
public void onOrderExecResponse(OrderExecResponse message) {
}
}
Quote Handling Message Events
To be notified about quote handling message events, implement the
biz.onixs.eurex.eti.handler.core.event.QuoteHandlingListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setQuoteHandlingListener(QuoteHandlingListener).handler.setQuoteHandlingListener(new MyQuoteHandlingListener());
The sample interface implementation demonstrates available message events to receive.
public class MyQuoteHandlingListener implements QuoteHandlingListener {
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteAllOrderQuoteEventBroadcast} message received.
* @param message message
*/
public void onDeleteAllOrderQuoteEventBroadcast(DeleteAllOrderQuoteEventBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteAllQuoteBroadcast} message received.
* @param message message
*/
public void onDeleteAllQuoteBroadcast(DeleteAllQuoteBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.DeleteAllQuoteResponse} message received.
* @param message message
*/
public void onDeleteAllQuoteResponse(DeleteAllQuoteResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.InquireMMParameterRequest} message received.
* @param message message
*/
public void onInquireMMParameterRequest(InquireMMParameterRequest message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.InquireMMParameterResponse} message received.
* @param message message
*/
public void onInquireMMParameterResponse(InquireMMParameterResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.MMParameterDefinitionResponse} message received.
* @param message message
*/
public void onMMParameterDefinitionResponse(MMParameterDefinitionResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.MassQuoteResponse} message received.
* @param message message
*/
public void onMassQuoteResponse(MassQuoteResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.QuoteActivationNotification} message received.
* @param message message
*/
public void onQuoteActivationNotification(QuoteActivationNotification message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.QuoteActivationResponse} message received.
* @param message message
*/
public void onQuoteActivationResponse(QuoteActivationResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.QuoteExecutionReport} message received.
* @param message message
*/
public void onQuoteExecutionReport(QuoteExecutionReport message) {
}
}
Quote and Cross Request Message Events
To be notified about quote and cross request message events, implement the
biz.onixs.eurex.eti.handler.core.event.QuoteAndCrossRequestListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setQuoteAndCrossRequestListener(QuoteAndCrossRequestListener).handler.setQuoteAndCrossRequestListener(new MyQuoteAndCrossRequestListener());
The sample interface implementation demonstrates available message events to receive.
public class MyQuoteAndCrossRequestListener implements QuoteAndCrossRequestListener {
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.CrossRequestResponse} message received.
* @param message message
*/
public void onCrossRequestResponse(CrossRequestResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.RFQResponse} message received.
* @param message message
*/
public void onRFQResponse(RFQResponse message) {
}
}
Strategy Creation Message Events
To be notified about strategy creation message events, implement the
biz.onixs.eurex.eti.handler.core.event.StrategyCreationListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setStrategyCreationListener(StrategyCreationListener).handler.setStrategyCreationListener(new MyStrategyCreationListener());
The sample interface implementation demonstrates available message events to receive.
public class MyStrategyCreationListener implements StrategyCreationListener {
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.AddComplexInstrumentResponse} message received.
* @param message message
*/
public void onAddComplexInstrumentResponse(AddComplexInstrumentResponse message) {
}
}
Other Message Events
To be notified about other message events, implement the
biz.onixs.eurex.eti.handler.core.event.OtherListener interface and register it via biz.onixs.eurex.eti.handler.core.Handler.setOtherListener(OtherListener).handler.setOtherListener(new MyOtherListener());
The sample interface implementation demonstrates available message events to receive.
public class MyOtherListener implements OtherListener {
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.BroadcastErrorNotification} message received.
* @param message message
*/
public void onBroadcastErrorNotification(BroadcastErrorNotification message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.NewsBroadcast} message received.
* @param message message
*/
public void onNewsBroadcast(NewsBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.RiskNotificationBroadcast} message received.
* @param message message
*/
public void onRiskNotificationBroadcast(RiskNotificationBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.LegalNotificationBroadcast} message received.
* @param message message
*/
public void onLegalNotificationBroadcast(LegalNotificationBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.ServiceAvailabilityBroadcast} message received.
* @param message message
*/
public void onServiceAvailabilityBroadcast(ServiceAvailabilityBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.TMTradingSessionStatusBroadcast} message received.
* @param message message
*/
public void onTMTradingSessionStatusBroadcast(TMTradingSessionStatusBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.TradeBroadcast} message received.
* @param message message
*/
public void onTradeBroadcast(TradeBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.TradingSessionStatusBroadcast} message received.
* @param message message
*/
public void onTradingSessionStatusBroadcast(TradingSessionStatusBroadcast message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.PartyEntitlementsUpdateReport} message received.
* @param message message
*/
public void onPartyEntitlementsUpdateReport(PartyEntitlementsUpdateReport message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.InquireMarginBasedRiskLimitResponse} message received.
* @param message message
*/
public void onInquireMarginBasedRiskLimitResponse(InquireMarginBasedRiskLimitResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.UpdateRemainingRiskAllowanceBaseResponse} message received.
* @param message message
*/
public void onUpdateRemainingRiskAllowanceBaseResponse(UpdateRemainingRiskAllowanceBaseResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.TradingActionResponse} message received.
* @param message message
*/
public void onTradingActionResponse(TradingActionResponse message) {
}
/**
* Notifies about {@link biz.onixs.eurex.eti.handler.message.UpdateReferencePricesResponse} message received.
* @param message message
*/
public void onUpdateReferencePricesResponse(UpdateReferencePricesResponse message) {
}
}
Java Eurex ETI Handler