Introduction
- Introduction
CME Drop Copy Handler for Java is a Java library that provides access to the CME Group Drop Copy services using FIX Protocol.
High-level Java API allows to build applications rapidly to get drop copy data without much involving into raw protocol specifics.
CME Drop Copy Handler implementations features include:
- CME AutoCert+ Drop Copy 4.0 pre-certified.
- Easy-to-use API.
- Low latency, low CPU load.
- Flexible logging.
Note It's highly recommended to read the Drop Copy 4.0 Service for iLink to get familiar with core aspects of CME Drop Copy Service.
By reading this Guide, we also recommend to review a source code of the sample project which comes as a part of the library distributive package.
System Requirements
Java 1.8+
Getting Started
All Handler classes are encapsulated into the
biz.onixs.cme.dropcopy.handler.Handler package.The typical way of using the Handler is as follows:
- Set path to license storage using biz.onixs.cme.dropcopy.handler.Handler.setLicenseDirectory(String value) static method.
- Set path to log storage using biz.onixs.cme.dropcopy.handler.Handler.setLogDirectory(String value) static method.
- Create an instance of biz.onixs.cme.dropcopy.handler.Handler class.
- Register error listener using biz.onixs.cme.dropcopy.handler.Handler.setErrorListener(ErrorListener listener) method.
- Register warning listener using biz.onixs.cme.dropcopy.handler.Handler.setWarningListener(WarningListener listener) method.
- Register Handler's events listener using biz.onixs.cme.dropcopy.handler.Handler.setHandlerListener(HandlerListener listener) method.
- Start Handler by invoking biz.onixs.cme.dropcopy.handler.Handler.logon(String host, int port, String accessKeyID, String secretKey) method.
- Process data of the events for which listeners were previously registered.
- Stop Handler by invoking biz.onixs.cme.dropcopy.handler.Handler.logout() method.
- Clean up resources by invoking biz.onixs.cme.dropcopy.handler.Handler.dispose() method.
Secure Logon
CME Globex implemented secure authentication for Drop Copy sessions on Convenience Gateway (CGW) and Market Segment Gateway (MSGW). The new logon procedure secures the client system logon with:
- Customer identity verification - a client system logon request will be signed with security credentials issued and validated by CME Group.
- Message confidentiality and integrity - to credential the logon message, the client system sends a keyed-hash message authentication code (HMAC) generated from a combination of the logon FIX tag values. When CME Globex receives the logon message, it uses the identical inputs to calculate the HMAC value to validate against the logon request. If the values do not match, CME Globex rejects the logon.
Secure keys
Customers must create secure key pairs for iLink and Drop Copy Sessions in the CME Customer Center.
Implementation details
Secure Logon procedure was implemented inside DropCopy Handler. To provide secure keys to DropCopy Handler please call one of Handler.logon() methods, which accepts accessKeyID and secretKey parameters
Connecting to Multiple Segments
Handler instance allows connecting to a single segment only. To connect to multiple segments, create one handler instance for each segment. Please see the multisegment sample from the installation package.
Note Segment id is specified as session TargetSubID. SenderCompId and SenderSubId will be same for all segments.
The following example demonstrates how to connect to multiple segments.
final String senderCompId = "SenderCompId";
final String targetCompId = "TargetCompId";
final String targetSubId1 = "TargetSubId1";
final String senderSubId = "SenderSubId";
final String senderLocationId= "SenderLocationId";
Handler handler1 = new Handler(senderCompId, targetCompId, senderSubId, targetSubId1, senderLocationId);
handler1.setErrorListener(this);
handler1.setWarningListener(this);
handler1.setHandlerListener(this);
final String host1 = "host";
int port1 = 4500;
final String accessKey1 = "key";
final String secretKey1 = "secretKey";
handler1.logon(host1, port1, accessKey1, secretKey1);
// Same SenderCompId and SenderSubId, but different TargetSubID
final String targetSubId2 = "TargetSubId2";
Handler handler2 = new Handler(senderCompId, targetCompId, senderSubId, targetSubId2, senderLocationId);
handler2.setErrorListener(this);
handler2.setWarningListener(this);
handler2.setHandlerListener(this);
final String host2 = "host";
int port2 = 4500;
final String accessKey2 = "key";
final String secretKey2 = "secretKey";
handler2.logon(host2, port2, accessKey2, secretKey2);
//etc.
Connecting to Backup Sessions
If connection to primary host has been dropped, CME allows to connect to a backup host:
- CME Globex initiates failover by electing the ranking inactive designated backup Drop Copy Gateway to assume the primary role.
- The client application should connect to the newly promoted primary Drop Copy Gateway.
- If the primary connection fails and the client system connects to the newly promoted primary Drop Copy Gateway, that instance will begin with the next available outbound sequence number to the client (outbound sequence number could be higher due to unprocessed in-flight messages).
- Once connected to the new instance, sequence numbers on outbound messages from the client system to Drop Copy must begin with the next available sequence number from tag 34-MsgSeqNum of the previously available Drop Copy gateway instance.
- After failover, Drop Copy may resend previously transmitted messages with tag 97-PossResend=Y on real time messages.
Backup host can be connected by providing new IP address.
The following example demonstrates how to switch to a backup host.
Handler handler = new Handler(senderCompId, targetCompId, senderSubId, targetSubId, senderLocationId);
handler.setErrorListener(this);
handler.setWarningListener(this);
handler.setHandlerListener(this);
handler.logon(primary_host, port, accessKey, secretKey);
// Some network or gateway failure occurs, so there is need to switch to backup host
handler.logon(backup_host, port, accessKey, secretKey);
Using Handler with the Scheduler
Handler supports using the Session Scheduler to connect to CME host automatically. The Scheduler support switching between primary and backup hosts.
Note It's important to register Handler as InitiatorConnectionListener, to process host switching correctly. If the only primary host is used, this step can be omitted.
The following example demonstrates how to configure the Scheduler to connect to CME hosts.
Handler handler = new Handler(senderCompId, targetCompId, senderSubId, targetSubId, senderLocationId);
final SessionScheduler sessionScheduler = new SessionScheduler();
sessionScheduler.start();
final SessionSchedule schedule = createSchedule();
final InitiatorConnection connection = new InitiatorConnection();
// This is required to process switching between primary and backup hosts correctly.
connection.setInitiatorConnectionListener(handler);
final InetSocketAddress primaryAddress = InetSocketAddress.createUnresolved(host, port);
connection.addAddress(primaryAddress);
final InetSocketAddress backupAddress = InetSocketAddress.createUnresolved(backupHost, backupPort);
connection.addAddress(backupAddress);
Message customLogon = handler.createLogonMessage(accessKey, secretKey);
connection.setCustomLogonMessage(customLogon.toString());
sessionScheduler.register(handler.getSession(), schedule, connection);
Controlling Handler Logging
Controlling Logging in the Handler
By default, Handler logs all important aspects of its activity while processing market data. The SLF4J (Simple Logging Facade for Java) is used by Handler internally. The SLF4J detects and uses the concrete logging implementation configured by user. By default, the Logback logging implementation is recommended.
The Logback (or any other logging implementation) must be configured at the beginning of the application. The examples of Logback configuration can be found in the Handler samples. The details of Logback configuration can be found here.
By default, logging is configured to log only errors and warnings. This is an example of logback.xml where detailed logging was switched on:
<logger name="biz.onixs.cme.stp.handler.sample" level="INFO"/>
<logger name="biz.onixs.cme.stp.handler" level="INFO"/>
Error Reporting
An exception is used as a fundamental error-reporting mechanism. In the event of any error the
biz.onixs.cme.dropcopy.handler.Handler.ErrorListener.onError(Object sender, ErrorEventArgs args)is triggered once exception is thrown while processing inbound/outbound messages.
Licensing
The pre-defined license file name is “OnixS.lic”. The license file is loaded during handler initialization as described in the Unified Resource Loading.
The default license file name can be changed using LicenseFile parameter in
the biz.onixs.cme.dropcopy.handler.Handler.setLicenseFile(String) method.
The following table explains different options to keep the license file.
| License File Location | License File Name | LicenseFile Property | Note |
|---|---|---|---|
| application classpath | OnixS.lic | no change required | |
| current directory | *.lic | no change required | Any file with the “.lic” extension in the current directory is checked automatically. |
| user home directory | *.lic | no change required | Any file with the “.lic” extension in the user home is checked automatically. |
| application classpath | AltName.ext | AltName.ext | |
| absolute path “/foo/bar” | AltName.ext | /foo/bar/AltName.ext | |
| relative path “foo/bar” | AltName.ext | foo/bar/AltName.ext |
Unified Resource Loading
By default, any external resource is looked for at the following places and in the following order (if other is not set explicitly):
- Classpath
- Absolute file path
- Current directory
- User home directory
If it can't be found at the 1st location then the 2nd one is checked, etc.
Events and Listeners
The events and their listeners of the biz.onixs.cme.dropcopy.handler.Handler class are listed below:
- Application message is received and parsed: biz.onixs.cme.dropcopy.handler.Handler.HandlerListener
- Warning is detected: biz.onixs.cme.dropcopy.handler.Handler.WarningListener
- Error condition is detected: biz.onixs.cme.dropcopy.handler.Handler.ErrorListener
Example
import biz.onixs.cme.dropcopy.handler.ErrorEventArgs;
import biz.onixs.cme.dropcopy.handler.Handler;
import biz.onixs.cme.dropcopy.handler.MessageEventArgs;
import biz.onixs.fix.parser.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ListenerExample implements Handler.ErrorListener, Handler.WarningListener, Handler.HandlerListener{
String senderCompId = "SenderCompID";
String targetCompId = "TargetCompID";
String senderSubId = "SenderSubID";
String targetSubId = "TargetSubID";
String senderLocationId = "SenderLocationID";
private static final Logger LOG = LoggerFactory.getLogger(ListenerExample.class);
private void run() throws Exception {
Handler handler = new Handler(senderCompId, targetCompId, senderSubId, targetSubId, senderLocationId);
handler.setErrorListener(this);
handler.setWarningListener(this);
handler.setHandlerListener(this);
}
@Override
public void onError(Object sender, ErrorEventArgs args) {
LOG.error("{}", args);
}
@Override
public void onExecutionReportReceived(Object sender, MessageEventArgs args) {
final Message report = args.getMessage();
System.out.printf("Execution Report received: %s.\n", report);
}
@Override
public void onMassOrderCancelReportReceived(Object sender, MessageEventArgs args) {
final Message orderMassActionReport = args.getMessage();
System.out.printf("Mass Order Cancel Report received: %s.\n", orderMassActionReport);
}
@Override
public void onWarning(Object sender, ErrorEventArgs args) {
LOG.warn("{}", args);
}
}
Support
OnixS provides online support resources to customers and development partners.
Jira
Jira is an issue logging and tracking system with release version control, records of issues/fixes and enhancements, and access to useful resource and FAQ information.
We recommend using Jira for issue logging/tracking. Registration requests for Jira access and technical support are also available via email at support@onixs.biz.
CME Drop Copy for Java