0

I am trying to understand the Bayeux protocol. I haven't found a web-resource explaining how the bayeux client will technically work, in detail.

From this resource,

The Bayeux protocol requires that the first message a new client sends be a handshake message (a message sent on /meta/handshake channel).

The client processes the handshake reply, and if it is successful, starts – under the covers – a heartbeat mechanism with the server, by exchanging connect messages (a message sent on a /meta/connect channel).

The details of this heartbeat mechanism depend on the client transport used, but can be seen as the client sending a connect message and expecting a reply after some time.

Connect messages continue to flow between client and server until either side decides to disconnect by sending a disconnect message (a message sent on the /meta/disconnect channel).

I have written in Java methods to first do a handshake, then subscribe to a particular channel. I made use of the Apache HttpClient library to do the HTTP POST requests.

Now comes the part of connect.

My understanding is that, I need to keep a request open to the bayeux server and whenever I receive a response, make another request.

I have the written the below code. Is my understanding correct and does this bayeux client exhibit the correct connect functionality? (please ignore the missing disconnect, unsubscribe methods)

Also, I have tested the code against a bayeux server and it works correctly.

/* clientId - Unique clientId returned by bayeux server during handshake
    responseHandler - see interface below */

private static void connect(String clientId, ResponseHandler responseHandler) 
        throws ClientProtocolException, UnsupportedEncodingException, IOException {
    String message = "[{\"channel\":\"/meta/connect\"," 
                    + "\"clientId\":\"" + clientId + "\"}]"; 
    CloseableHttpClient httpClient = HttpClients.createDefault();
    

    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            while (!doDisconnect) {
                try {
                    CloseableHttpResponse response = HttpPostHelper.postToURL(ConfigurationMock.urlRealTime,
                            message, httpClient, ConfigurationMock.getAuthorizationHeader());

                    responseHandler.handleResponse(response);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }
        
            try {
                httpClient.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    });
    t.start();
        
}

/*Simple interface to define what happens with the response when it arrives*/

private interface ResponseHandler {
    void handleResponse(CloseableHttpResponse httpResponse);
}

public static void main(String[] args) throws Exception{
    String globalClientId = doHandShake();  //assume this method exists
    subscribe(globalClientId,"/measurements/10500"); //assume this method exists
    connect(globalClientId, new ResponseHandler() {
        @Override
        public void handleResponse(CloseableHttpResponse httpResponse) {
            try {
                System.out.println(HttpPostHelper.toStringResponse(httpResponse));
            } catch (ParseException | IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    });
}
Community
  • 1
  • 1
rents
  • 768
  • 1
  • 7
  • 22

1 Answers1

1

Your code is not correct.

Messages on the /meta/connect channel do not have the subscription field.

Subscriptions must be sent on the /meta/subscribe channel.

You want to study the Bayeux Specification for further details, in particular the meta messages section and the event messages section.

A suggestion is to launch the CometD Demo and look at the messages exchanged by the client, and mimic those in your implementation.

sbordet
  • 16,856
  • 1
  • 50
  • 45
  • Yes you are correct that connect doesn't have the subscription field. In my example, it is getting ignored at server side (and the code works correctly). Do you mean to say apart from that, my implementation correct? I have written a subscribe function which subscribes to a channel in an earlier call. – rents Feb 12 '16 at 14:15
  • Your code is not correct. It does not take into account the `advice` field to decide whether and when to issue the `/meta/connect` message. If an exception happens, you are in a spin loop burning the CPU. If a non `IOException` happens you close the HTTP client and exit. Your implementation is blocking, which is fine for a simple example, but typically you don't want to do this because it does not scale. You don't want applications to call your `connect` method, this should be done internally by the implementation. – sbordet Feb 12 '16 at 19:25
  • As I said in my answer, you want to study the Bayeux protocol and the [CometD implementation](https://github.com/cometd/cometd/blob/master/cometd-java/cometd-java-client/src/main/java/org/cometd/client/BayeuxClient.java), and see how it's being done there. – sbordet Feb 12 '16 at 19:26