How to send parameters from CometD client to CometD server

307 views Asked by At

I have a SessionListener on a CometD server. I want to pass data from a client to the server when the listener's sessionAdded() method is called.

The sessionAdded() method receives a ServerSession and ServerMessage object. ServerSession has an Attribute map that always seems to have nothing in it.

I would like to get some unique client data to the server. This data should be accessed by the server when the sessionAdded() method is invoked.

The documentation talks about basic use of a SessionListener, but says nothing about attributes. All the javadocs for client and server say about it is to describe how setAttribute() sets an attribute and how getAttribute() gets it.

Is there a way to do this? Can the ServerSession's attribute map be used to transfer attributes from the client to the server, and if so, how?

Someone please advise...

1

There are 1 answers

0
sbordet On BEST ANSWER

The ServerSession attributes map is a map that lives on the server.

It is an opaque (from the CometD point of view) map that applications can populate with whatever they need.

If you want to send data from a client to the server, you can just put this additional data into the handshake message, and then retrieve it from the message when BayeuxServer.SessionListener.sessionAdded() is called.

The client looks like this:

BayeuxClient client = ...;
Map<String, Object> extraFields = new HashMap<>();
Map<String, Object> ext = new HashMap<>();
extraFields.put(Message.EXT_FIELD, ext);
Map<String, Object> extraData = new HashMap<>();
ext.put("com.acme", extraData);
client.handshake(extraFields);
extraData.put("token", "foobar");

This creates an extra data structure that in JSON looks like this:

{ 
  "ext": { 
    "com.acme": { 
      "token": "foobar"
    } 
  } 
}

It is always a very good practice to put your data under a namespace such as com.acme, so that you don't mess up with CometD fields, nor with other extensions that you may use. Put your fields inside extraData, like for example field token in the example above.

Then, on the server:

public class MySessionListener implements BayeuxServer.SessionListener {
  @Override
  public void sessionAdded(ServerSession session, ServerMessage message) {
    Map<String, Object> ext = message.getExt();
    if (ext != null) {
      Map<String, Object> extra = (Map<String, Object>)ext.get("com.acme");
      if (extra != null) {
        String token = (String)extra.get("token");
        session.setAttribute("token", token);
      }
    }
  }

  @Override
  public void sessionRemoved(ServerSession session, boolean timedout) {
  }
}

This listener puts into the session attributes data that has been sent by the client, in the example above the token field.

Then, elsewhere in the application, you can access the session attributes and use that data.