Programming Guide

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.

  1. Adjust handler settings.
  2. Initialize the handler.
  3. Register error and warning listeners.
  4. Register listeners for incoming messages.
  5. Establish the connection.
  6. Make user logon request.
  7. Start sending messages.
  8. Make user logout request.
  9. Terminate the connection.
  10. 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

biz.onixs.eurex.eti.handler.core.HandlerException while the previous use

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

biz.onixs.eurex.eti.handler.core.event.InboundMessageListener - as a

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:

  1. Ends the lost session: CONNECTED → DISCONNECTING → DISCONNECTED. The connection is already gone at that point, so no LogoutRequest is sent and the teardown completes without waiting for one.
  2. Discards anything still queued for that session and reports it to the error listener.
  3. Resets the outbound MsgSeqNum to 1 (a fresh session is started on each reconnect).
  4. Makes up to Number + 1 total connection attempts (1 initial attempt plus up to Number retries), waiting Interval seconds 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:

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() or shutdown(), so a listener that calls back into the handler should check getState() 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 second connect() arrives while the first is still establishing its session.
  • A shutdown() that left the handler somewhere unexpected. Reported when shutdown() could not reach NOT_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) {
    }
}