question

Upvotes
Accepted
3 0 1 3

How can I detect a failure to connect to RFA?

I see a lot of example code that checks to see if the session == null when an attempt is made to acquire it. But the session always seems to come back with an object, even if the Config is bogus. It is only when sending a message that it seems to find out that it cant connect to RFA. Can someone verify that?

Is there anyway to query the Context or Session for their state?

When I do send a message, whether it be a login or some other message, there is no event sent to my handler to tell me that it cannot connect to RFA. So for example if I purposely change the port to a wrong one, the logging shows there are errors but the event handler never gets any messages. All of my code is modelled after the examples in the API kit.

Here is a portion of my test code in cased that is useful.

@Test(groups={"unit"})
public void testFailToConnect() throws Exception {

    Logger logger = Logger.getLogger("com.reuters.rfa");
    Level level = Level.FINEST;
    logger.setLevel(level);
    Handler[] handlers = logger.getHandlers();

    if(handlers.length == 0)
    {
        Handler handler = new ConsoleHandler();
        handler.setLevel(level);
        logger.addHandler(handler);
    }


    // purposely configure it so the port is wrong
    ConfigDb configProvider = (ConfigDb) getTestConfig();
    configProvider.addVariable("Convx.Connections.p2psCon.portNumber", "14001");

    Context.initialize(configProvider);
    try {

        Session session = Session.acquire("Convx::p2ps");

        Assert.assertNotNull(session,"could not acquire session");

        EventQueue eventQueue = EventQueue.create("myEventQueue");
        OMMConsumer consumer = (OMMConsumer) session.createEventSource(EventSource.OMM_CONSUMER,"myOMMConsumer",true);

        //Create a OMMPool.
        OMMPool pool = OMMPool.create();

        //Create an OMMEncoder
        OMMEncoder encoder = pool.acquireEncoder();

        OMMMsg ommmsg = encodeLoginReqMsg(pool,encoder);
        OMMItemIntSpec ommItemIntSpec = new OMMItemIntSpec();
        ommItemIntSpec.setMsg(ommmsg);

        System.out.println(" Sending login request...");

        EventHandler eventHandler = new EventHandler();
        Handle loginHandle = consumer.registerClient(eventQueue,
                ommItemIntSpec, eventHandler, null);


        Thread.sleep(5000);

        // we need some way to know that the session could not acquire a connection to Reuters.

        session.release();

    } finally {
        Context.uninitialize();
    }

}

I have set breakpoints in the processEvent of the event handler (that implements Client) and I don't get any hits.

The log looks like this:

Feb 13, 2017 9:41:07 AM com.reuters.rfa.internal.session.SessionImpl processEventQueueDispatchThreadStarted FINE: com.reuters.rfa.session.Convx.p2ps Session initialization: Dispatch thread "Convx::p2ps Session EventQueueGroup" started Sending login request... Feb 13, 2017 9:41:12 AM com.reuters.rfa.internal.session.ConnectionHandler createConnections FINE: com.reuters.rfa.session.Convx.p2ps Session initialization: acquiring connection "Convx::p2psCon" Feb 13, 2017 9:41:13 AM com.reuters.rfa.internal.connection.ConnectionImpl processConnectionStatusOpenReqMsg FINE: com.reuters.rfa.connection.rssl.Convx.p2psCon Sending CONNECTION_STATUS_MSG, connection name = Convx::p2psCon, status = { state: DOWN, code: NONE, text: "uninitialized"} Feb 13, 2017 9:41:17 AM com.reuters.rfa.internal.connection.ConnectionImpl processConnectionStatusBase FINE: com.reuters.rfa.connection.rssl.Convx.p2psCon Sending CONNECTION_STATUS_MSG, connection name = Convx::p2psCon, status = { state: DOWN, code: NONE, text: "Connection refused: no further information"} Feb 13, 2017 9:41:17 AM com.reuters.rfa.internal.session.SessionImpl cleanup FINE: com.reuters.rfa.session.Convx.p2ps Session cleanup: Deactivating event queues and halting dispatch thread Feb 13, 2017 9:41:17 AM com.reuters.rfa.internal.session.ConnectionHandler sendClosedReqMsg FINE: com.reuters.rfa.session.Convx.p2ps Session cleanup: Releasing connection "Convx::p2psCon"

treprfarfa-api
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
Accepted
1.5k 3 5 7

Hi dyazel

There are a couple of things you need to consider:

  • Everything in the RFA API is asynchronous. And I mean (just about) everything. This means that the way you create your application is different from a traditional old school synchronous application. You may also refer to it as event based. Acquiring a session and getting non-null back only means that there was some valid config present for the session name you are using. That's all. It doesn't mean the connection can actually succeed.
  • Ok, so the way to know if a connection has failed or not is to listen for events. RFA will - behind your back - try to establish the connection and let you know how it progresses by giving you events. RFA has an event model which never sends duplicates, so to speak. So an attempt to connect which fails will result in an event. However, if RFA then - still behind your back - attempts once again 10 seconds later and still fails it will not result in a new event to you. This is because no state has changed between the two attempts: the session is still not connected so there's nothing new to report.
  • RFA lib will attempt to connect forever. This makes sense if you think of it. The assumption is that the session is correctly configured and it is temporary situation that the connection cannot be established. In a real-world scenario this is actually what you want: you don't really want your application to stop trying, you want it to auto-recover, regardless if this may take hours because some network is currently down or whatever. However if you really want to give up then you can control that yourself. Luckily you can actually fire your own events, called timer events. So, if you register such an event at startup so that it fires once after say 20 seconds then you have all what you need: During these 20 seconds you'll either receive a LOGIN message event saying that session was successfully established (in which case you should cancel the timer event) or you'll receive the timer event after 20 seconds and this can then be used as a timeout because in that case you'll know that connection hasn't been established during the first 20 seconds and then you can close down or do whatever you want.

I hope this makes sense. You should be able to piece together a solution for your needs with the above information. I realize I'm not giving you direct recipes more like background knowledge. Trust me: it is better to first know WHY and then from there design the HOW.

Btw: Don't sleep. Ever. The way to get events is to dispatch them from the queue. If you don't dispatch you'll not get any events. So this is what your application should be doing where you are now doing your sleep().

Best of luck

Lars

Addicticks

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Thank you! The main missing piece was that I needed to call dispatch myself. That was a stupid mistake on my part because RFA 6.4 had the same design and I should have remembered that. I just checked my old code and yes, I had a EventQueueThread object that handling the dispatching for a queue.

It is too bad that there is not an explicit failure/status/event for a failure to connect to RFA. Using the absence of an event to infer a failure to connect is doable, but you have to then check the log to understand more about why it failed to connect. There are many reasons why it might fail.

Upvotes
1.5k 3 5 7

There is indeed an event for the first failed connection attempt. There just isn't one for the next failed connection attempt. (as per my comments about no duplicate events)

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.