Friday, January 29, 2010

WebSphere + GWT + Comet

IBM supports Reverse AJAX (AKA Comet) in a form of WebSphere Feature Pack for Web 2.0 for WebSphere Application Server 6.0+. It is shipped by default with the latest fix packs for WAS 6.1 and in all 7.0 versions. Actually this Feature Pack has a lot of nice Web 2.0 features, but at the moment we are interested in Web Messaging Service only.

To install and enable FP you need to follow the documentation, it won't take long. As the result you will get the ability to push data to your client's web browser by publishing it to the special JMS topics. As an alternative, you may also use a more specialized API for doing this, but the Publisher object is stored in the Servlet context, therefore it can be somewhat tricky to access it from an arbitrary part of your application, which is not true with JMS.

I assume that you have successfully installed and tested your Web Messaging, and now want to upgrade your QuoteStreamer sample application to GWT. For example, you have a widget and want its methods to be called when some data arrives from the backend.

It is possible to use JSNI to achieve exactly this goal. The idea is simple: when you need to push some object to the client (for example, out of your Message Driven Bean), you first serialize it using GWT RPC mechanism, then put the resulting string to the appropriate JMS Topic. This string is wrapped to JSON envelope, sent to the client via WFP and unwrapped there via Dojo. Your JavaScript listener should be triggered at this moment. But as we use GWT for all our JavaScript programming, we should implement that listener as JSNI snippet:
private native void initCallbackAndSubscribe (String someParam) /*-{
if ($wnd.dojox) {
$wnd.dojox.cometd.subscribe("/test/" + someParam, this,
function (comet) {
module.@com.test.MyCoolWidget::onReverseAjax(Ljava/lang/String;)(comet.data)
});
}
}-*/;

// This is a normal Java code
public void
onReverseAjax(String msg) throws SerializationException {
SerializationStreamReader r = ((SerializationStreamFactory) svc).createStreamReader(msg);
Object data = r.readObject();
// Do something with that data arrived
}
As you see, the data is deserialized later in your normal Java code called by this listener. That's it. If you have initialized everything right (in your index.jsp or some similar place), this scheme should work fine. Now I will show you how to send data using GWT RPC. It should be simple via RPC.encodeResponseForSuccess method, but there is one problem - it requires SerializationPolicy object for the security reasons. This mechanism restricts serialized objects to the limited set described in *.gwt.rpc files, generated during compilation. Another problem is that there can be several such files. I haven't found a good way to get the SerializationPolicy other than by concatenating these files altogether:
public SerializationPolicy getSerializationPolicy() throws Exception {
String result = "";
for (File file : new File(PATH_TO_YOUR_GENERATED_STUFF).listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".rpc");
}
})) {
result += (FileUtils.readFileToString(file));
}
return SerializationPolicyLoader
.loadFromStream(new ByteArrayInputStream(result
.getBytes("UTF-8")), null);
}

public void publishObject(String topic, Object obj, Method method) throws Exception {
String r = RPC.encodeResponseForSuccess(method, obj, getSerializationPolicy());
publishStringViaJms(topic, r.toString());
}
I forgot to mention that RPC.encodeResponseForSuccess requires a Method instance, but it is used only to extract the return value type, so any method returning the object of the obj.getClass() type will do.

In general, there are some good things about such WebSphere + GWT + Comet integration, the major one is that it uses WFP, which is a pretty powerful Comet server, compared to some custom-built solutions. For example (at least on WAS 7.0), it uses connection multiplexing, nio and all that cool stuff you expect from the modern web server. Also, it naturally integrates into your ESB, so you can use it in your Process Server applications with ease. Some limitations are obvious too, for example it won't work in GWT Hosted Mode with Tomcat. Also it seems to me that this should be implemented somehow simpler, but I was unable to find it. So if you have any other ideas, please give me a clue.

P.S.: Actually, there are some alternatives to this approach. For example you can use gwt-comet-streamhub to enable Reverse AJAX for your GWT applications. But it provides its own Comet server called StreamHub which is definitely not a part of the IBM WebSphere product line :)

P.P.S.: The described method should work with other Comet-enabled J2EE servers like Jetty with minor modifications.

P.P.P.S.: There is left one more issue with security. As for now, it is not really clear for me how to implement role-based security for Comet... I can think of using several update servlets at the same time, and it should allow me to use webapp security. But this issue definitely needs further investigation.

Tuesday, January 26, 2010

WADL toolbox

WADL stands for Web Application Description Language and currently is in a state of W3C Member Submission, that means at the early stage of W3C standardization process. The purpose of the "language" is similar to WSDL, with the orientation towards RESTful APIs in the first place. What is essential for me is that this language perfectly suits the task of Pomodoro Server API description. There are surprisingly few tools utilizing this format, I guess this is due to the immaturity of the language. Though I can name some of the most useful ones:
  • Jersey, a reference implementation of JAX-RS. It is able to generate WADL at run time based on the metadata found in your Java classes.
  • soapUI, a great tool for testing web services. As one of its numerous new features in version 2.5 it can utilize WADL web service description and generate sample test cases automagically. It can even do the trick in the opposite direction, i. e. infer both WADL and XSD from the existing test case structure! Unfortunately I've found some aspects of this generation somewhat buggy not really obvious. For example, it does not inherit template parameters for nested resources. And despite the ability to specify application-wide settings for HTTP Basic Auth, it does not get applied somehow, so it should be specified for each test case separately. Anyway, it is a great tool and I'm looking forward to see it in a bit more stable state.
  • WADL to HTML is an advanced XSLT stylesheet to generate documentation from your WADLs. It seems that either my WADL is all wrong (then why it conforms to the WADL Schema?), or my XSLT processors are broken (both Saxon and Xalan running on Windows and Linux), because I was unable to get any output. But they say it works for them, so I tend to think it is actually my own problem. Anyway, I've already wrote my own simple XSLTs and going to put it here in a matter of few days :)
  • wadl2java generates a web service client based on WADL. It uses JAXB to create the necessary representations based on XSD referred in grammars section.
  • REST Describe & Compile is yet another client generator. It can infer WADL from the set of supplied request URLs, and then generate client code in several languages, namely Java and Python. The tool looks promising, but as for me, the UI is not intuitive enough. Also, you have no control over code generation, so good chances are that you will have to modify your clients manually after generation. Here you can find a great deal of documentation for the tool and underlying concepts.
P. S.: You can find WADL for Pomodoro Server here. Also you can see some generated documentation in the Google Code wiki.