[Dojo cometd] Java Desktop Application OR Java Applet Authentication


We have been using a traditional method of Writing web applications. A request is send to the Server. Server checks out the designated Servlet and the request is served by sending a response to the Client. Following is a theoretical  representation of what i want to say:

Client [Browser] —> HTTP REQUEST —> Server [Tomcat] —> HTTP RESPONSE —>  Client [Browser]

But consider this: if there is a requirement such that the SERVER should initiate a data transfer without the CLIENT asking it. For example a Sock Exchange App which show you every second update of the stocks and the market fluctuations. Bayeux Protocol solves this problem by transporting messages asynchronously (over HTTP) through designated “channels” with low latency between server and client. Check this link to know more http://cometd.org/documentation/bayeux. Theoretically the following:

Server —> Client [Browser or Java App]

Client[Browser or Java App] <—> Client[Browser or Java App]  (via server)

Cometd is a project by Dojo Foundation which implements bayeux protocol in javascript, java and other languages. There are various other Bayeux implementations available http://cometd.org/documentation/cometd. But i personally like cometd and I had been working with cometd for a long time now and find it damn easy and sufficiently documented. The only disadvantage that i find is the IDE support, there is one netbeans plugin but it is commented as buggy!. It is also a bit of a effort to find all the needed jars. There are also huge change in the 2.x version of cometd compared to 1.x version. Here are some changes documented http://cometd.org/documentation/2.x/migration.

Throughout this article and future blog entries i will keep up to the cometd 2.x classes and packages. As i mentioned before every thing is documented very well, so i will like to explain What is not documented or else i didnt had my eye on.

There are some times a requirement where you need to authenticate a cometd server. There is also a well documented CometD 2 Authentication how-to on that here http://cometd.org/documentation/2.x/howtos/authentication and it mentions how to send authentication information using jquery :

var username = 'foo';
var password = 'bar';

// Send the authentication information
cometd.handshake({
    ext: {
        authentication: {
            user: username,
            credentials: password
        }
    }
});

and the above code works perfect. But imagine doing this from a Java Desktop Application or say Java Applet. The above how-to does not mention that and i was almost going nuts finding a way to do that. Here is how you do that. In your Java Application you have to define a new Extension which extends ClientSession.Extension which is as follows:

import java.util.Map;
import org.cometd.bayeux.Channel;
import org.cometd.bayeux.Message;
import org.cometd.bayeux.Message.Mutable;
import org.cometd.bayeux.client.ClientSession;
import org.cometd.bayeux.client.ClientSession.Extension;
public class ExtExtension implements Extension
{
 public static final String EXT_FIELD = "ext";
private volatile boolean _serverSupportsAcks = false;
 private volatile int _ackId = -1;
 private Map<String, Object> authMap=null;
public ExtExtension(Map<String, Object> authObj){
 super();
 authMap=authObj;
 }
public boolean rcv(ClientSession session, Mutable message)
 {
 return true;
 }
public boolean rcvMeta(ClientSession session, Mutable message)
 {
 return true;
 }
public boolean send(ClientSession session, Mutable message)
 {
 return true;
 }
public boolean sendMeta(ClientSession session, Mutable message)
 {
 if(Channel.META_HANDSHAKE.equals(message.getChannel()))
 {
 message.getExt(true).put(EXT_FIELD, authMap);
 _ackId = -1;
 }
 else if(_serverSupportsAcks && Channel.META_CONNECT.equals(message.getChannel()))
 {
 message.getExt(true).put(EXT_FIELD, _ackId);
 }
return true;
 }
}

Thats it! finally in your Java Desktop Application OR Java Applet it is a matter of adding the extension to the client and making a handshake with the authentication details. Following is the code snippet:

HttpClient httpClient = new HttpClient();
try {
            httpClient.start();
        } catch (Exception ex) {

        }

        // Prepare the transport
        Map<String, Object> options = new HashMap<String, Object>();
        ClientTransport transport = LongPollingTransport.create(options, httpClient); 

ClientSession client = new BayeuxClient("http://localhost:8080/cometd", transport);
        Map<String, Object> logininfo = new HashMap<String, Object>();
        logininfo.put("credentials", "mypassword");
        logininfo.put("user", "myuserid");
        client.addExtension(new PuExtension(logininfo));
        client.getChannel(Channel.META_SUBSCRIBE).addListener(new ClientSessionChannel.MessageListener()
        {
            public void onMessage(ClientSessionChannel channel, Message message)
            {
                System.out.println("Handshake Success");
            }
        });

        client.handshake(logininfo);
        client.getChannel("/hello").subscribe(new ClientSessionChannel.MessageListener()
        {
            public void onMessage(ClientSessionChannel channel, Message message)
            {
                System.out.println("new message received : " + message);
            }
        });

Final Word: Thanks to Dojo Foundation’s cometd and available documentation it easy to develop a scalable Push Server until the websockets arrive. But also to say latest release of cometd 2.4.0 has support for websockets http://webtide.intalio.com/2011/09/cometd-2-4-0-websocket-benchmarks/.

Further Reading:

http://cometd.org/

http://webtide.intalio.com/

Advertisements

About Dominic

J for JAVA more about me : http://about.me/dominicdsouza
This entry was posted in Thechy Stuff and tagged , , , . Bookmark the permalink.

One Response to [Dojo cometd] Java Desktop Application OR Java Applet Authentication

  1. yong says:

    I spent a long time on this too, finally this way worked:

    HashMapMessage msg = new HashMapMessage();
    Map ext = msg.getExt(true);
    Map data = new HashMap();
    data.put(“password”, “1234”);
    data.put(“user”, “user_id”);
    ext.put(“authentication”, data);
    client.handshake(msg);

    In server side:
    Map ext = message.getExt();
    auth = ext.get(“authentication”);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s