Elektron SDK - Java

API Family: Elektron

EMA NI Provider - Listening to the connection state

Download tutorial source code

Click here to download

Last update January 2017
Compilers

JDK 1.7.x, JDK 1.8.x

Prerequisites

EMA NI Provider - Connecting to the ADH

Declare the NI_PUB and TEST_NI_PUB services in your TREP (see Before you start).

Tutorial purpose

In the previous tutorial we demonstrated how to connect a NI Provider application to a TREP infrastructure. In order to verify if the provider was actually connected, we used a manual procedure that involved running a TREP consumer application, eg: Eikon. In this tutorial step, we will see how the NI Provider application can directly receive the connection status from the EMA library.

To this aim we will go through the following sections:

Introduction

In order for our NI Provider application to successfully publish data to TREP, we must ensure we have successfully connected and logged in.  The manual procedure we used in the previous tutorial to verify our connection status was tedious and not very practical. We manually checked the connection state by using a consuming application we connected into the TREP infrastructure.  While this allowed us to visually determine connection status, this obviously doesn't help our Provider application.

In this tutorial we demonstrate how the NI Provider application can leverage EMA to capture our connection status, decode it and determine if we can successfully publish data.

Listening to login messages

When your application creates the OmmProvider object, the EMA library takes care of initiating the connection to the infrastructure. Once the provider is connected and properly logged in, the EMA library also takes care of automatically reconnecting and logging in upon connection failure. All this happens under the hood and makes your developer’s life a lot easier. Naturally, your NI Provider application may need to know when these connections and disconnections actually happen. To do so, it has to register for messages of the MMT_LOGIN domain type:

  • MMT_LOGIN refresh messages are returned by the infrastructure in response to the Login request that the EMA library sends when you create an OmmProvider object. 
  • MMT_LOGIN status messages are sent when the state of the connection changes, due to disconnections and automatic reconnections.

These messages convey information that indicates if the connection stream has been successfully established or if the stream state has changed. This information may also indicate that the login request has been accepted, rejected or closed.

For more details about Login messages, please consult the RDM Usage Guide in References.

In order to receive these messages, the NI Provider application must register to the MMT_LOGIN domain messages by calling the OmmProvider::registerClient() method in this way:

 

// Register the connectionStateListener to receive login messages from EMA
provider.registerClient(
                EmaFactory.createReqMsg()
                    .domainType(EmaRdm.MMT_LOGIN)
                    .name(userName), 
                connectionStateListener);
  • The first parameter (the ReqMsg) indicates the domain type you want to register to (MMT_LOGIN in our case) and the user name used to login your application.
  • The second parameter is an object that will be called by the EMA library when a new message is received. The class of this object must inherit from the com.thomsonreuters.ema.access.OmmProviderClient interface and define the onRefreshMsg() and onStatusMsg() callback methods.

    Note: The OmmProviderClient interface declares other methods that also must be defined by your listener. However, they will not be needed for the purpose of this tutorial. Their bodies can be left empty.  

Note: The method returns a handle that can be preserved for later use. For example to unregister our interest for the MMT_LOGIN messages. In our case we want to receive these messages during the whole life time of the application. As there’s no real need to unregister, we do not preserve the handle. The unregistration will be done automatically when the OmmProvider is uninitialized. 

In the tutorial source code, we added the registerClient() method call to the NIProvider::connect() method, just after the OmmProvider is created. 

Decoding login messages

The MMT_LOGIN messages will be received by the onRefreshMsg() and onStatusMsg() callback methods of a ConnectionStateListener class that we added to the project. An instance of this class has been made a member of the NiProvider class so that the NiProvider can delegate login messages listening and decoding.

The onRefreshMsg() method just extracts the OmmState object embedded in the message it receives, and sends it to the decodeConnectionState() method for decoding.

 

public void onRefreshMsg(RefreshMsg refreshMsg, OmmProviderEvent providerEvent)
{
    decodeConnectionState(refreshMsg.state());
}

The onStatusMsg() method tests if the received message transports an OmmState object. No state means that the connection is ok. If there is a state, onStatusMsg() extracts it and sends it to the decodeConnectionState() method for decoding.

public void onStatusMsg(StatusMsg statusMsg, OmmProviderEvent providerEvent)
{
    if (statusMsg.hasState())
    {
        decodeConnectionState(statusMsg.state());
    }
    else
    {
        System.out.println("  Provider is connected");
        isConnected = true;
    }        
}

decodeConnectionState() is a helper method that we defined in the ConnectionStateListener class to factorize the decoding of the connection states. The OmmState actually holds two states, the stream state and the data state. If the stream state is open, and the data state is ok, the provider is properly connected and logged in. Any other combination means the connection is not correct. Based on this information, the decodeConnectionState() method prints the connection state on the console.

private void decodeConnectionState(OmmState state)
{
    
    if (state.streamState() == OmmState.StreamState.OPEN
        &&
        state.dataState() == OmmState.DataState.OK)
    {
        System.out.println("  Provider is connected. OmmState:" + state);
        isConnected = true;
    }
    else
    {
        System.out.println("  Provider is disconnected. OmmState:" + state);
        isConnected = false;
    }        
}  

The connection state is preserved in the isConnected member of the ConnectionStateListener class. This state can be retrieved thanks to the isConnected() methods we added to the ConnectionStateListener and NiProvider classes as shown below:

public boolean isConnected()
{
    return isConnected;
}
public boolean isConnected()
{
    if(connectionStateListener == null)
    {
        return false;
    }

    return connectionStateListener.isConnected();
}

Stop listening to login messages

Your application will stop receiving MMT_LOGIN messages, as soon as you uninitialize the OmmProvider object. So basically, we do not do anything explicit to unregister our interest in these messages. However, if for any reason you want to stop receiving MMT_LOGIN messages but you want to keep your provider connected, you must call the OmmProvider.unregisterClient() method with the handle that was returned by the OmmProvider.registerClient() method. Obviously, you have to preserve this handle somewhere in your application.

public void disconnect()
{
    // Exit the method if already disconnected
    if (provider == null)
        return;

    System.out.println("  Disconnecting...");

    // Disconnect from the infrastructure and automatically unregister the 
    // connectionStateListener we registered in the connect() method to 
    // receive login messages from EMA
    provider.uninitialize();
    provider = null;
}  

The main workflow

The main workflow did not really change as the connection messages management does not impact it. We just removed the 10 seconds wait that happened after the disconnection. 

public static void main(String[] args)
{
    .
    .
    .
        NiProvider provider = new NiProvider(); 

        provider.connect();

        waitFor(60);

        provider.disconnect();
    .
    .
    .
} 

Build and run the application

Build the application and start it. Please refer to the Build and Run section within the first tutorial of this series (A barebones EMA NIP application shell) for detailed instructions.

This is what the application should display: 

    -------------------------------------------------------------------------------
    |                    Non Interactive Provider EMA Tutorial                    |
    |                                                                             |
    |                Tutorial 3 - Listening to the connection state               |
    -------------------------------------------------------------------------------
      Provider created
      Connecting Provider to ADH 10.2.43.49:14003 as nip-user
      Waiting for 60 seconds...
      Provider is connected. OmmState:Open / Ok / None / 'Refresh Completed'
      Disconnecting...
      Exiting the application
    

    Troubleshooting

    Q: When I build or run the tutorial, it fails with an error like:

    The system cannot find the path specified

    A: The JAVA_HOME environment variable is not set, or set to the wrong path. See Setup the development environment section of the first tutorial.

     

    Q: When I build the tutorial, I get ”<path>/javac: No such file or directory” or when I run the tutorial, I get  ”<path>/java: No such file or directory” error like

    line 59: /home/user/jdk/bin/javac: No such file or directory
    

    A: The JAVA_HOME environment variable is not set, or set to the wrong path. See Setup the development environment.

     

    Q: When I build or run the tutorial, I get "Finding Jar files in <path>” and “The system cannot find the path specified.” errors like

    Build the NIP application with Elektron SDK Java version 1.2.x or higher.
    
    Finding Jar files in C:\Elektron-SDK\Java\Ema\Libs\
    The system cannot find the path specified.
    

    A: There are 2 possible causes:

     

    Q: When I build or run the tutorial, I get "<path to /*jar> : No such file or directory” error like

    /home/user/Elektron-SDK1.1.1.E2.java.eload/Java/Ema/Libs/*.jar: No such file or directory
    

    A: There are 2 possible causes:

     

    Q: When I build the tutorial, I get "package ... does not exist" and "cannot find symbol" errors like:

    Main.java:20: error: package com.thomsonreuters.ema.access does not exist
    import com.thomsonreuters.ema.access.OmmException;
                                        ^
    Main.java:56: error: cannot find symbol
                    catch (OmmException exception)
                           ^
      symbol:   class OmmException
      location: class Main

    A: The ELEKTRON_JAVA_HOME environment variable is not set, or set to the wrong path. See Setup the development environment section of the first tutorial.

     

    Q: When I run the tutorial, I get a JNI error with a NoClassDefFoundError exception like:

    Error: A JNI error has occurred, please check your installation and try again
    Exception in thread "main" java.lang.NoClassDefFoundError: com/thomsonreuters/ema/access/OmmException
            at java.lang.Class.getDeclaredMethods0(Native Method)
            at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
            at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
            at java.lang.Class.getMethod0(Class.java:3018)
            at java.lang.Class.getMethod(Class.java:1784)
            at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
            at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
    Caused by: java.lang.ClassNotFoundException: com.thomsonreuters.ema.access.OmmException
            at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
            ... 7 more

    A: The ELEKTRON_JAVA_HOME environment variable is not set, or set to the wrong path. See Setup the development environment section of the first tutorial.

     

    Q: The application is stuck after the "Connecting Provider to ADH…" message is displayed.

    After a while the application displays an error like: 

    login failed (timed out after waiting 45000 milliseconds) for 10.2.43.149:14003)
    

    A: Verify that the ADH of your TREP infrastructure is up, and that you properly set the host variable of the connect() method. You can also use the telnet command tool to verify that your NIP application machine can connect to the ADH (telnet <ADH host> <port>). If the telnet succeeds but you still can’t connect, verify that you don’t have any firewall blocking the messages sent/received by the application.  

    Ultimately, ask your TREP administrator to help you to investigate with TREP monitoring tools like adhmon.

    Tutorial Group: 
    EMA NI Provider