ETA Tutorial 1 - Creating a starter consumer application

Download tutorial source code

Click here to download

Last update Dec 2020
Environment Windows, Linux
Compilers JDK 1.7 or greater
Prerequisite Quick Start Guide

Introduction

The goal of this tutorial is to define a basic ETA shell interface to be used in subsequent tutorials allowing us to consume real-time market data. Based on our shell interface, we will walk through the general steps within subsequent tutorials to properly establish communication to our real-time server allowing us to log in, query services, and ultimately request for real-time data. To support these goals, we must first establish an appropriate Java build environment to successfully build and run our series of tutorials.

Description

For these tutorials, it is important to familiarize yourself with the contents of the ETA package. The ETA components are packaged as part of the Real-Time SDK bundle for Java. Included within this component, are value-added libraries that enable the developer to leverage OMM-based APIs with more ease and simplicity. These series of tutorials will utilize these value-added libraries.

ValueAdd Package

Located under the Applications/Examples directory contain a series of examples to demonstrate many powerful features available to the developer. The examples have been broken out into 2 main categories as identified by the sub-directories: examples and valueadd. The examples contain feature-rich and highly configurable examples of ETA functionality. However, they are extremely low-level and require a significant amount of code to achieve the desired result. While there are reasons why a developer may choose to go to this level of coding, it is beyond the scope of these tutorials. Instead, these series of tutorials will utilize some very useful, and powerful, capabilities packaged under the valueadd directory.

It is worth noting that although we will be utilizing the ValueAdd ETA components, the amount of code is still somewhat significant. As a result, these tutorials will highlight the relevant sections to give the developer a sense of operation.

Steps

As previously outlined, the goal of this tutorial is to define a build environment, implement a shell that performs basic ETA ValueAdd initialization, build and run the example successfully. The steps include:

Establish an ETA Java build environment

The series of tutorials come packaged with 2 convenient scripts: buildConsmer and runConsumer - see Build and Run below for more details. Because Real-Time SDK Java can be installed anywhere within your environment, our build and run scripts make an assumption about how to resolve the location of ETA's JAR packages. While there are multiple ways to configure the setup, this project assumes the following:

  • Real-Time SDK Home directory
    The environment variable RTSDK_JAVA_HOME is used within build and run scripts to resolve the location of your Real-Time SDK Java installation. Defined for both the Windows and Linux scripts, this will allow developers to easily copy/duplicate projects to other members and to themselves without having to re-define directory locations within their own projects.
  • Java build environment
    The build and run scripts assume the Java compiler and runtime executables are defined within your path.

Once you have set this up, future tutorials will work without further configuration.

Implementation Overview - Shell code for ETA setup

The basic shell utilizes a single source file basicConsumer.java. The basicConsumer class represents the main interface for our consumer. The class implements the ETA ValueAdd interface ConsumerCallback which manages all communication events we will define in subsequent tutorials. ETA utilizes an asynchronous model when communicating with external servers or Providers, such as Real-Time servers. As such, we have set up the basic framework to prepare our communication:

 

    	
            

public class basicConsumer implements ConsumerCallback

{

    ...

 

    //****************************************************************************************************

    // ConsumerCallback interfaces

    //

    // The following methods are required to capture the consumer-related events that typically occur 

    // during a normal consumer role life cycle.  Specifically:

    //

    // reactorChannelEventCallback - capture all conneciton/channel communication events

    // rdmLoginMsgCallback   - capture the result of our login

    // rdmDirectoryMsgCallback  - capture the result of the service directory retrieval

    // rdmDictionaryMsgCallback - capture the result of the dictionary retrieval, if requested

    // defaultMsgCallback   - capture all other events, such as data events.

    //****************************************************************************************************

 

    // reactorChannelEventCallback

    // Capture all connection-related channel events to our provider.  At startup, we initiate an 

    // synchronous connection to the provider.  The ValueAdd layer will manage connection failure, 

    // connection retry, disconnect automatically. In the event we successfully connect, we will receive 

    // the connected channel file descriptor required for us to register interest within our own event 

    // polling.  The ValueAdd layer will begin the normal cycle of submitting the RDM requests (login, 

    // directory, dictionary) to the provider and once successfully completed will present a ready event 

    // (CHANNEL_READY) which is our notification we can begin requesting for real-time data.

    @Override

    public int reactorChannelEventCallback(ReactorChannelEvent event)

    {

        return ReactorCallbackReturnCodes.SUCCESS;

    }

    // rdmLoginMsgCallback

    // Report the results of the login request.  Because the ValueAdd layer is managing the session 

    // establishment on our behalf, it will decide if it needs to continue with the normal life cycle or 

    // not.  We simply report the results.

    @Override

    public int rdmLoginMsgCallback(RDMLoginMsgEvent event)

    {

        // Process the login response placeholder

        return( ReactorCallbackReturnCodes.SUCCESS );

    }

 

    // rdmDirectoryCallback

    // Once we have successfully logged in, the ValueAdd layer will submit the service directory request 

    // on our behalf.  The response is captured here and we off-load the processing within a separate 

    // module.

    @Override

    public int rdmDirectoryMsgCallback(RDMDirectoryMsgEvent event)

    {

        // Process the directory response placeholder

        return( ReactorCallbackReturnCodes.SUCCESS );

    }

 

    // rdmDictionaryMsgCallback

    // If we decided we wanted to request for the field definition dictionaries from the provider, the 

    // ValueAdd layer will request once we have completed our service directory processing.  We manage the 

    // response within a separate module.

    @Override

    public int rdmDictionaryMsgCallback(RDMDictionaryMsgEvent event)

    {

        // Process the dictionary details placeholder

        return(ReactorCallbackReturnCodes.SUCCESS);

    }

 

    // defaultMsgCallback

    // Once we receive our channel is ready event within the 'reactorChannelEventCallback', we can begin to 

    // submit data requests to our provider.  All responses are captured here and off-loaded within a separate 

    // module.

    @Override

    public int defaultMsgCallback(ReactorMsgEvent event)

    {

        // Process the data msg details placeholder

        return(ReactorCallbackReturnCodes.SUCCESS);

    }

}

​The above structure outlines 5 mandatory interfaces that will manage a typical ETA consumer life cycle. As we move through the series of tutorials, each interface will be implemented with the goal of connecting, establishing a session and requesting and receiving data.

Within our initization routine below, we establish the main ETA Reactor component which drives the logic flow and dispatching of events that we will utilize in later tutorials. For now, we simply create it.

    	
            

// Supporting variables 

private Reactor reactor; 

private ReactorOptions reactorOptions = ReactorFactory.createReactorOptions(); 

... 

private void init()

{

    ... 

    // Create reactor - the reactor drives the logic flow and dispatching of events to our defined callbacks 

    reactor = ReactorFactory.createReactor(reactorOptions, errorInfo);

    if (errorInfo.code() != ReactorReturnCodes.SUCCESS) 

    { 

        System.out.println("createReactor() failed: " + errorInfo.toString()); 

        System.exit(ReactorReturnCodes.FAILURE); 

    } 

}

While our tutorial is designed to be simple, the ValueAdd components will hide a lot of complexity, such as multiple threads, to handle its work. Following tutorials will go into greater depth the details of the ValueAdd components we will be using.

Build and run

The package includes convenient scripts to build and run the tutorials with any ETA versions:

  • The ETA libraries’ names contain the version. Hence, each script file (the buildConsumer.bat/.ksh and runConsumer.bat/.ksh) set the VERSION variable to be 3.6.0.0 to use eta-3.6.0.0.jar shipped with RTSDK 2.0.0. If you would like to use ETA/UPA in another RTSDK version, you need to modify the VERSION variable in each script file to correspond with eta-<VERSION>.jar shipped with the RTSDK package you set in RTSDK_JAVA_HOME variable. For example, to build the tutorial using RTSDK version 2.0.0 containing eta-3.6.0.0.jar, modify VERSION in each script file to be 3.6.0.0:

-  buildConsumer.bat and runConsumer.bat:

    	
            set VERSION=3.6.0.0
        
        
    

 - buildConsumer.ksh and runConsumer.ksh:

    	
            VERSION=3.6.0.0
        
        
    

For this series of tutorials:

To Build:

  • > buildConsumer.bat [<1|2|3|4|5|6>] - Windows (Build a specific tutorial)
  • > sh buildConsumer.ksh [<1|2|3|4|5|6>] - Linux (Build a specific tutorial)

To Run:

  • > runConsumer.bat <1|2|3|4|5|6> - Windows (Run a specific tutorial)
  • > sh runConsumer.ksh <1|2|3|4|5|6> - Linux (Run a specific tutorial)

Eg (Windows):

> buildConsumer 1 
> runConsumer 1

When we run this tutorial, we want to see that we have displayed some general startup details, initialized our reactor then exit gracefully by uninitializing without error. If so, we have successfully built and executed our ETA application

    	
            

Enterprise Transport API (ETA), Java Edition, LibraryVersionInfo

        productVersion: 3.6.0.0

        productInternalVersion: etaj3.6.0.L1.all.rrg

        productDate: Fri Oct 16 12:25:01 CDT 2020

basicConsumer initializing...

Uninitializing basicConsumer and exiting...

References

For more information, refer to the ETA Java Development Guides.