Introduction
Update: March 2021
This article is intended for anyone who is interested in using Enterprise Message API (EMA - formerly known as Elektron Message API) - Java in Scala language to consume real-time data i.e. Market Price, level 2 data i.e. Market By Order, Market By Price and Market Maker including Symbol List from the server e.g. Advanced Distribution Server (ADS), Real-Time Host or any OMM Provider application. EMA is one part of the Real-Time Software Development Kit or RTSDK (formerly known as ESDK). EMA is an easy-to-use API providing access to OMM and RWF data, high-performance open source API that operates at the Message Layer. Therefore, the developers generally only need to deal with data and status messages. For more details of EMA and the resource e.g. Overview, Quick Start, Documentation, Downloads and Tutorials, please refer to Real-Time SDK - Java. This article also demonstrates how to request a snapshot and streaming request and apply the Views feature and Batches feature. For more details of these, you can find them in the API Concepts Guide.
EMA Overview
EMA Consumer Life Cycle
Developing a consumer application with EMA is simple. The general process can be summarized by the following steps
- Establish network communication to the server
- Log in to the server
- Obtain feeds/services information e.g. the supported domain types, each service’s status(up/down)
- Load or download dictionary information e.g. all field ids, field name, and their type. This info is used when processing data
- Issue item requests and process responses e.g. data or status messages
- Logout from the server and shut down
However, EMA makes things simpler by further reduce the coding needed. The API will automatically perform the first four steps with minimal coding. Hence, the application just issues item requests, process responses, logout and shutdown as shown in the figure below:
Processing Responses from the Server
In order to process the responses, the consumer applications need to implement the following callback methods of OmmConsumerClient interface:
- onRefreshMsg() for the processing of refresh messages. A refresh message contains all the data for the requested instrument.
- onUpdateMsg() for the processing of update messages. An update message contains the changed data values for the instrument being subscribed.
- onStatusMsg() for the processing of status messages. A status message contains the health information on the status of the feed and delivery infrastructure and data subscriptions themselves.
Moreover, The interface also provide onGenericMsg(),onAckMsg() and onAllMsg() for the processing of generic messages, ack messages and all messages respectively. Normally the consumer applications can ignore these methods; put an empty body for each of them. Since all messages the consumer applications receive are from onRefreshMsg() , onUpdateMsg() and onStatusMsg() already.
Scala Overview
Scala was developed specifically with the aim of being a better language than Java. Scala is a modern multi-paradigm programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages. Scala is designed to interoperate well with the popular Java Runtime Environment (JRE). In particular, the interaction with the mainstream object-oriented Java programming language is as smooth as possible. Hence, you can write a Scala application to call any Java interfaces e.g. EMA Java. Scala syntax is also closed to the Java language so the learning curve for the Java developers is minimized. Therefore, you can develop EMA Java application in Scala within minimum time to create a better Java application e.g. extremely compact and easier to write. For more details of Scala including Documentation, Download, Online Courses, please refer to Scala page.
Solution
This section explains how to develop an EMA Consumer application written by Scala language. It shows the snipped Scala source code which uses EMA to consume, process data, use Views, and Batches feature. The complete application source code can be found at Article.EMA.Scala.Consumer GitHub. The section also explains how to build and run the application by Scala command line.
Prerequisites
- JDK8
- Scala binaries or IDE. For more details, please refer to Scala Download Page
- Real-Time SDK Java Package which provides EMA, it's dependency libraries which are required to develop EMA consumer applications.
Source Code
This section demonstrates how to develop an EMA Consumer according to EMA Consumer Life Cycle section. The application is simple. There is only one file named Consumer.scala which contains the following part:
- Consumer object: It contains the main (args:Array[String]) method which performs:
- Extract the following program parameters from the command line.
- -server <server_host_port>. The Server host and port. The default is localhost:14002.
- -serviceName <service_name>. The Service name. The default is DIRECT_FEED.
- -username <name>. The Name of the application user. The default is user.
- -domainType <domain_type>. The Domain Type of the requested item(s). The default is MARKET_PRICE. The other Domain Types are MARKET_BY_ORDER, MARKET_BY_PRICE, MARKET_MAKER, and SYMBOL_LIST.
- -itemNames <list_of_RICs>. The List of RICs separated by ','. The default is IBM.N.
- -fieldIds <list_of_FieldIds>. The List of field Ids separated by ','. The default is all fields.
- -streamingReq <true or false>. Are all streaming requests?. If it is true, the application receives a Refresh follow by Update messages. Otherwise, only a Refresh is received. The default is true.
- -runTime <seconds>. How long (in seconds) application should run before exiting. The default is 60.
- Initialize AppClient object containing the callback methods which process all responses from the server.
- Create OmmConsumer object which connects and logs in to the server, obtains services information, loads or downloads dictionary information automatically.
- Call OmmConsumer to subscribe the item(s) according to the program parameters e.g. request streaming or snapshot. If there are more than one items, the Batches feature is applied. If the field id(s) is/are specified, the Views feature is applied instead of receiving all fields available on the item(s).
- Sleep the application till the runtime parameter (seconds) elapses. This is to wait for EMA receives responses from the server and call the callback methods i.e. onRefreshMsg() , onUpdateMsg() and onStatusMsg()
- Before shutdown the application, uninitialized OmmConsumer object. This is to log out and disconnect from the server, at which time all open item streams are closed.
- Extract the following program parameters from the command line.
The snipped source code in the main (args:Array[String]) method:
The snipped source code to apply Batches and Views feature:
2. AppClient class: This class processes responses EMA receives i.e. data or the status of item streams. It implements the callback methods of OmmConsumerClient interface.
- onRefreshMsg() to process refresh messages
- onUpdateMsg() to process update messages.
- onStatusMsg() for process status messages.
The snipped source code in AppClient class:
Process update messages source code:
Process status messages:
You can notice that the class calls the utility method named decode(fieldList: FieldList) to decode level 1 data which is Market Price. The class also calls the method decode(map: com.refinitiv.ema.access.Map) to decode level 2 data i.e. Market By Order, Market By Price and Market Maker and including Symbol List.
The decode(fieldList: FieldList) method source code to process level 1 data:
The decode(map: com.refinitiv.ema.access.Map) source code to process level 2 data and Symbol List.
Build and Run the Consumer
To build and run the Consumer, the library files i.e. EMA, ETA, and EMA's dependency are required. All files are shipped with the Real-Time SDK Java Package. Thus, you just set the classpath to all of them before building and running the application.
The following show how to build and run the application using the commands in Scala binaries software on Windows:
- Set the classpath to EMA, ETA, and EMA's dependency library files. For example:
2. Compile the application using scalac command:
3. Run the application:
- Include the path containing the Consumer class files generated from step 2 to the classpath
- Run the application using scala command. For example, log in with the user named pimchaya to requests data with updates(streaming request) of field TIMACT, BID and ASK (field id is 5,22 and 25 respectively) of a market price item named JPY= from the service named ELEKTRON provided by server IP 192.168.27.49 port 14002.
The Example Result
Troubleshooting
Q: The application shows "Error - exceeded initialization timeout (5 s)".
A: The server IP or/and port number is incorrect, the server went down or unreachable due to network or firewall. Please contact your infrastructure or network administrator or the Account team to verify.
Q: The application shows "Error initializing channel: errorId=-1 text=Connection refused: no further information".
A: The server process e.g. ADS, Real-Time host went down or the port number is incorrect. Please contact your infrastructure administrator or the Account team to verify.
Q: The application shows "Error initializing channel: errorId=-1 text=Handshake failed with far end. No more Protocols to try."
A: The consumer application is trying to reach to the server on SSL (Source Sink library) connection; which default port is 8101. EMA supports only RSSL (Source Sink Layer) connection. Please change the port to be 14002 which is the default RSSL port. If your application can still not connect to the server, contact your infrastructure administrator or the Account team to confirm the correct server and port providing RSSL connection.
Q: The application shows "<user>, unknown to system."
A: The consumer application logs in with the user who does not have the permission to access the server. Please contact your infrastructure administrator or the Account team to ask for a valid username of the server.
Q: The application shows "Service not up" error
A: The consumer application request items from the down service. Please contact your infrastructure administrator or the Account team who can help you to bring the service up.
Q: The application shows "Service name of <service_name> is not found." error
A: The consumer application request items from the service which does not provide the item or the service name is wrong. Please contact your infrastructure administrator or the Account team to ask for the correct service name.
Q: The application shows "Capability not supported" error
A: The consumer application requests an item from the service which does not support the domain type of the item. In the example above, the service named DIRECT_FEED does not support MARKET_BY_PRICE domain type of the item named VOD.L. Please contact your infrastructure administrator or the Account team to ask for the service which supports the requested domain type.
Q: The application shows "The record could not be found" error
A: The requested item/RIC named is not available by the system. In the example above, the item named IBM.M which domain type is Market Price is not found on the service named ELEKTRON. The name of RIC may be incorrect. The user should verify the subscribed RIC name or contact the data support team via LSEG Support in order to find the correct RICs which can provide the data required.
Q: The application shows "Access Denied: <permission info>" error
A: The logged in user does not have the permission to access data. In the example above, the user does not have the permission to access data of IBM.N due to the lack of NYS Exchange permission. Please contact your infrastructure administrator or the Account team who can help you to grant the permission.
Summary
After finishing this article, you will understand more about Enterprise Message API. It shows how easier and faster to leverage EMA in Scala language to consume data according to your business requirements. This article also includes the solutions for the common problems. If you do not have a server where your application can consume data from, please contact the Account team for the process and details.