Elektron SDK - Java

API Family: Elektron

EMA Consumer - Posting data to TR Contribution Channel

Download tutorial source code    Click here to download
Last update November 2018
Compilers JDK 1.7 or greater
Prerequisite Downloaded, installed, compiled and ran an EMA consumer example

Introduction

In this tutorial we will explain and use the EMA Java SDK, to contribute data to Thomson Reuters Contribution Channel (TRCC) directly, without using the TREP infrastructure. The reader must have an understanding of an Elektron Message API and be familiar with consuming OMM Market Price data. You should also have a basic understanding of EMA Configuration. To understand the contribution concepts, please refer to this article.

Contributing Data to Thomson Reuters Elektron Feed

Currently clients wishing to Contribute data to Thomson Reuters, typically do so using on-site contribution systems such as MarketLinkIP. In order to meet the evolving needs of the market, Thomson Reuters have developed a new Contribution service - the Thomson Reuters Contribution Channel (TRCC). Contributions Channel is provided through a cluster of virtual servers that can provide data optimization & conflation capabilities as well as a much higher rate of content onto Elektron.

There are two key mechanisms through which an API developer can contribute data to Thomson Reuters head-end. Once contributed, this data can be delivered to other customers who have been permissioned to view it. This service is commonly used by banks and funds to make their data available to trading community.

The first option is to use and configure the Thomson Reuters Enterprise Platform (TREP), to take care of contribution specific connection and login details.

The second option, which is discussed in this tutorial, is for clients who do not have an onsite TREP installation and will connect to TRCC through the Internet. To contribute directly to TRCC, an EMA application undertakes following four steps:

  1. Establish an encrypted connection to the server
  2. Open a Tunnelstream
  3. Perform a client login
  4. Contribute data using post messages

Lets look at the EMA Java code starting with application configuration. This tutorial source code is based on EMA sample: series400\example440__System__TunnelStream which ships with the SDK distribution, in the Examples directory.

Establish an encrypted connection to the server

EMA SDK undertakes all the work required to establish an encrypted connection. All an application developer needs to do, is define the <Consumer> and set its <Channel> type to RSSL_ENCRYPTED, in the EMA configuration file EmaConfig.xml. The hostname and the port of the destination TRCC server will have to be specified in the configuration as well.

<Channel>
    <ChannelType value="ChannelType::RSSL_ENCRYPTED"/>
    <Host value="TRCC_HOST_NAME"/>
    <Port value="TRCC_PORT"/>
</Channel>

Now, when an OMMConsumer is created with this configuration, EMA will start an encrypted connection. EMA Java uses security and encryption framework provided by the Java SDK, and uses the Sun JDK's default TLS. The Java standard way is to store the security certificate and private keys required for encryption, in a password protected keystore file. This filename and password has to be specified, when creating the OMMConsumer.

// Create an OMM consumer
OmmConsumer consumer = EmaFactory.createOmmConsumer(EmaFactory.createOmmConsumerConfig()
    .tunnelingKeyStoreFile("KEYSTORE_FILE_NAME")
    .tunnelingKeyStorePasswd("KEYSTORE_PASSWORD"));

Open a Tunnelstream

After establishing an encrypted connection, open the tunnel stream to the service which allows contribution.

// Create a request for a tunnel stream
TunnelStreamRequest tsr = EmaFactory.createTunnelStreamRequest()
    .classOfService(cos)
    .domainType(EmaRdm.MMT_SYSTEM)
    .name("TUNNEL1")
    .serviceName("CONTRIBUTION_SERVICE_NAME");

// Send the request and register for events from tunnel stream    
long tunnelStreamHandle = consumer.registerClient(tsr, appClient);

Here, we used the OMMConsumer defined earlier (which is connected to TRCC server by now), and open a tunnel stream to contribution service using the system domain. The tunnel stream handle will be used in the next step to login.

For production applications, it is recommended to establish two simultaneous connections, to two different servers. An application should only contribute to a single stream at any given time. The second stream is for redundancy purposes, and should only be used if there are issues with the first one.

Perform a client login

A successful opening of tunnel stream is followed by a status event callback: onStatusMsg, with state OmmState.StreamState.OPEN. The application should then perform a client login using the provided contribution user's username and password. The password field is obfuscated before sending. Use the obfuscation tool provided with TREP, or download it from here.

// create a login request message
ElementList elementList = EmaFactory.createElementList();
elementList.add(EmaFactory.createElementEntry().ascii("Password", "OBFUSCATED_PASSWORD"));

ReqMsg rMsg = EmaFactory.createReqMsg()
    .domainType(EmaRdm.MMT_SYSTEM)
    .name("LOGIN_USERNAME")
    .attrib(elementList)
    .privateStream(true)
    .serviceId(statusMsg.serviceId())
    .streamId(statusMsg.streamId());

// get events from login substream    
_subStreamHandle = _ommConsumer.registerClient(rMsg, this, 1, _tunnelStreamHandle);

If the login is accepted by the TRCC server, application will receive a refresh callback: onRefreshMsg with state OmmState.StreamState.OPEN. At this point, the application should store the stream handle, and is ready to contribute data.

Contribute data using post messages

To contribute, application can use off-stream posting - i.e. send post messages on the login stream. Application begins by creating the field list for the FID's it intends to contribute to; packs the field list into an update message, and sends this update message as a PostMessage payload. Following snippet shows how to send an update message containing a BID (FID 22) and an ASK (FID 25).

// populate the contributed FIDs and values 
FieldList nestedFieldList = EmaFactory.createFieldList();
nestedFieldList.add(EmaFactory.createFieldEntry().real(22, _bid++, OmmReal.MagnitudeType.EXPONENT_NEG_1));
nestedFieldList.add(EmaFactory.createFieldEntry().real(25, _ask++, OmmReal.MagnitudeType.EXPONENT_NEG_1));

// create an update message for our item
UpdateMsg nestedUpdateMsg = EmaFactory.createUpdateMsg()
    .streamId(_postStreamID)
    .name("CONTRIBUTION_RIC")
    .payload(nestedFieldList);

// post this market price message
_ommConsumer.submit(EmaFactory.createPostMsg()
    .streamId(_postStreamID)
    .postId(_postID++)
    .domainType(EmaRdm.MMT_MARKET_PRICE)
    .solicitAck(true)
    .complete(true)
    .payload(nestedUpdateMsg), _subStreamHandle);

Here, the application is also requesting, that the contributions be acknowledged by the system, by setting solicitAck(true). Setting this flag will cause the application to receive acknowledgment callbacks: onAckMsg. The callback acknowledgment message AckMsg, will contain attributes nackCode and text reason if the contribution is denied.

AckMsg
    streamId="5"
    domain="MarketPrice Domain"
    ackId="1"
    nackCode="SymbolUnknown"
    text="Symbol posted has not been recognised"
AckMsgEnd

Build

Since this tutorial is based on EMA Example: series400\example440__System__TunnelStream, follow the same build process, to compile this source code.

Run

  1. The sample EmaConfig.xml provided, assumes that the data dictionary files are present in the local directory. So copy the RDMFieldDictionary and enumtype.def from EMA /etc directory.
  2. Provide your existing keystore file or create a new one. Use the keytool provided with Java SDK to create a new keystore file in the JKS format:
    keytool -genkey -alias mydomain -keyalg RSA -keystore KeyStore.jks -keysize 2048
    
  3. Add the Comodo certificate authority to the keystore, if its not trusted. Refer to troubleshooting section on how to enable Java SSL logging and add Comodo CA.
  4. Modify the source code to reflect this keystore file name and the keystore password.
  5. Run output:
    Contributing to TR Contributions Channel
    Starting encrypted connection...
    Starting tunnel stream...
    ----- Status message ----
    StatusMsg
        streamId="5"
        domain="System Domain"
        privateStream
        state="Open / Ok / None / ''"
        name="TUNNEL1"
        serviceId="10"
        serviceName="DDS_TRCE"
    StatusMsgEnd
    
    Sending client login request...
    ----- Refresh message ----
    RefreshMsg
        streamId="5"
        domain="System Domain"
        solicited
        RefreshComplete
        privateStream
        state="Open / Ok / None / 'Login accepted by host c226fmrdbcata'"
        itemGroup="00 00"
        name="******"
        serviceId="10"
        Attrib dataType="ElementList"
            ElementList
                ElementEntry name="Password" dataType="Ascii" value="******"
            ElementListEnd
        AttribEnd
    RefreshMsgEnd
    
    System refresh, starting posting...
    ----- Ack message ----
    AckMsg
        streamId="5"
        domain="MarketPrice Domain"
        ackId="1"
    AckMsgEnd
    
    Continue posting...
    ----- Ack message ----
    AckMsg
        streamId="5"
        domain="MarketPrice Domain"
        ackId="2"
    AckMsgEnd
    
    Continue posting...
    ----- Ack message ----
    AckMsg
        streamId="5"
        domain="MarketPrice Domain"
        ackId="3"
    AckMsgEnd
    

Data which is contributed to the production TRCC, can be viewed by subscribing to that RIC in either Eikon or any other consumer application, like EMA Consumer sample. If however, you are using the development network for testing purposes, the contributed data is only available by configuring an Elektron Connect to connect to development feed, and then using an EMA consumer application. Please contact your account manager to get the EZD application, license and connection parameters.

Troubleshooting

Enable Logging

EMA SDK uses Java logging package for logging the API messages. The detail, format and destination of the logger messages can be controlled by configuring the Java logger properties.

Sample logging.properties file for storing log files in /log subdirectory:

.level=FINEST
# write logs in console and in file
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# dump warning messages on console
java.util.logging.ConsoleHandler.level=WARNING
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
# capture debug trace in the file
java.util.logging.FileHandler.level=FINEST
java.util.logging.FileHandler.pattern=logs/emaj.log
# Write 100000 bytes before rotating this file
java.util.logging.FileHandler.limit=50000000
# Number of rotating files to be used
java.util.logging.FileHandler.count=20
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# Format timestamp as date/time with millisecond
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s %2$s %n%5$s

EMA Java logging can be enabled, by passing above properties file to JVM at run time. In addition, it might be helpful to turn on the JDK network logging, to view the security and encryption handshake messages, between the API and the server. Following command line parameters to JVM will enable verbose network and EMA logs.

set LOGGING_CONFIG=-Djava.util.logging.config.file=logs\logging.properties
set NET_DEBUGGING=-Djavax.net.debug=all
java -cp %CLASSPATH% %LOGGING_CONFIG% %NET_DEBUGGING% Contributor

Verify Comodo CA

For an encrypted tunneling connection type, you might encounter trust issues with Comodo certificates. If you encounter this issue, manually download and import the certificate to your keystore file.

  1. Verify that your keystore does not have this certificate using command keytool -v -list -keystore KeyStore.jks and look for Comodo.
    Alias name: comodo
    Creation date: 23-Oct-2018
    Entry type: trustedCertEntry
    
    Owner: CN=COMODO RSA Organization Validation Secure Server CA, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
    Issuer: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
    Serial number: 36825e7fb5a481937ef6d1736bb93ca6
    Valid from: Tue Feb 11 19:00:00 EST 2014 until: Sun Feb 11 18:59:59 EST 2029
    Certificate fingerprints:
             MD5:  91:29:73:32:12:D5:F5:65:18:64:D8:6B:7B:AE:0B:98
             SHA1: 10:4C:63:D2:54:6B:80:21:DD:10:5E:9F:BA:5A:8D:78:16:9F:6B:32
             SHA256: 11:10:06:37:8A:FB:E8:E9:9B:B0:2B:A8:73:90:CA:42:9F:CA:27:73:F7:4D:7F:7E:B5:74:4F:5D:DF:68:01:4B
    Signature algorithm name: SHA384withRSA
    Subject Public Key Algorithm: 2048-bit RSA key
    Version: 3
    
  2. Backup your keystore file in case there is a problem importing the certificate.
  3. Download the Comodo certificate: http://crt.comodoca.com/COMODORSAOrganizationValidationSecureServerCA.crt
  4. Import into your keystore file: keytool -import -alias comodo -keystore KeyStore.jks -file COMODORSAOrganizationValidationSecureServerCA.crt

For more information on the use of keystores or understanding encryption in Java language, please refer to this article.

References

TRCC Article

Java Keystore file for Encryption - Article

Tutorial Group: 
EMA Consumer