Search code examples
javaandroidcometdbayeux

Add custom fields to CometD subscribe message


I am using CometD Java client on Android.

compile group: 'org.cometd.java', name: 'cometd-java-client', version: '2.9.1'

I need to subscribe to a channel on a CometD server. But there is a problem - the server requires a custom subscribe message (this is the expected subscribe message payload from the server docs):

[
    {
        "user": "xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
        "domain": "xyz",
        "pid": "gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10",
        "sid": "85f103a2",
        "gid": "WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o",
        "pageId": "6ea23e",
        "entityId": "xyz",
        "triggeringGoal": "3E955818355C44E2479B2A26629E69566C8C6376",
        "chatSearchPattern": "ua.domain=xyz",
        "startTime": 1482931626853,
        "metadata": "{}",
        "chatMetadata": "{}",
        "language": "en",

        "id": "3",
        "channel": "\/meta\/subscribe",
        "subscription": "\/chat\/xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
        "clientId": "26l1v2ngpdcwdtno1wu30rk92dur4",
        "ext": {
        }
    }
]

So my question is how do I add custom fields to the subscribe message (user, domain, pid, sid etc)? Currently I am subscribing to channels like this:

cometdClient.getChannel("/chat/" + clientID).subscribe(new ChannelListener("/chat/ messages"), new ChannelListener("/chat/ progress"));

But it is failing as expected.

By the way I am using org.eclipse.jetty.client.HttpClient as the HttpClient.


Solution

  • First of all, you should really upgrade as CometD 2.9.1 is really old now, and JDK 7 is supported on Android.

    The design of the server requiring all those fields in a /meta/subscribe message is really wrong. Most of that information is static (e.g. user and various "cookies" such as pid etc.) and can be determined at the time of the CometD handshake, so there is no need to send it over during a subscription.

    Also, sending it during a /meta/subscribe message makes it subject to attacks (an attacker can forge a message with a different user field, for example). You want to read the security section of the CometD documentation.

    Furthermore, using a channel per user (as it appears that the channel name is a concatenation of /chat/ and the user field) is not a recommended approach, since it will create possibly a lot of channels, while the same functionality can be achieved much more efficiently with a single service channel (and the user as a field of the messages being sent).

    If you really have to add those fields to the /meta/subscribe message, the way to do it is to use a custom extension, along these lines:

    class SubscribeExtension extends ClientSession.Extension.Adapter {
        @Override
        public boolean sendMeta(ClientSession session, Message.Mutable message) {
            if (Channel.META_SUBSCRIBE.equals(message.getChannel())) {
                String subscription = (String)message.get(Message.SUBSCRIPTION_FIELD);
                if (subscription.startsWith("/chat/") {
                    // Add fields.
                }
            }
            return true;
        }
    }
    

    Finally, if you really need to add extra fields to a /meta/subscribe message, you want to do it inside the ext field, with proper namespacing:

    {
        "id": "3",
        "channel": "/meta/subscribe",
        "subscription": "/chat/xyz-WQUAq3shWho1ZcJHaibQYzCh2ILMMX1o-gA6NuehTFYMhvViv6Ow3dvPbyt8Zwg10-bd8bd779f107615b1c5a1470706e4050e5389ddc",
        "clientId": "26l1v2ngpdcwdtno1wu30rk92dur4",
        "ext": {
            "com.acme.myapp": {
                "time": 1234567890,
                "pageId": "6ea23e",
                ...
            }
        }
    }
    

    Note how the extra fields do no pollute the message itself, but are grouped in the ext field under namespace com.acme.app which would represent your company and application.