Friday, April 30, 2010

Exposing GWT RPC services to other protocols and languages

During the design of our EMR application, we started laying out the interfaces in IDL. My prior background in CORBA and IDL had taught me that defining interfaces in IDL is good way of approaching the various interfaces without getting bogged down in programming language issues. It makes it easy for developers to go over the IDLs and once settled on the design, the work of implementing them can be distributed easily. Knowing that we would be using GWT, we used a subset of the IDL - no inouts or out parameters ..

Our hope was that once we defined these interfaces, clients - be it Browser (GWT client) or other programs can access these interfaces as well. The goal essentially was to be able to open up these interfaces to say XML-RPC or other protocols as well and be able to use the same security framework we have in place. I am happy to report that we were able to do this with GWT with ease.

All GWT RPC calls go thru to RemoteServiceServlet (or in our case SecureRemoteServiceServlet) servlets. GWT code then parses the request and executes the appropriate method. In order to support an XML based RPC call we modified the service call as follows.
public class SecureRemoteServiceServlet extends RemoteServiceServlet {
...
protected void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
if ( isXMLRequest(req) ) { //if servlet path is xml
doPostXML(req, res);
else {
super.service(req, res);
}
}
...
}
doPostXML parses the XML request, plugs into the existing security framework ..., calls the method and returns the response back as XML. The XML protocol and serialization of arguments and return types to XML was straight forward using reflection. We ended up using annotations on interface arguments so we can use these as element names in the XML.
Example:
public interface Patient extends SecureRemoteService {
@ParamName("PatientInfo")
public PatientInfo get(@ParamName("AccountID") int accountID,
@ParamName("PatientID") int patientID);
...
}
We then went one step further and decided it's better to provide language bindings for this XML-RPC, so that it makes it easy for developers to use these interfaces. We generated a Java Binding for the GWT service interfaces by adding a code generator that took as an argument a GWT Service interface and generated appropriate java code. We are in the process of generating a binding for Java Script and who knows - may be will provide a binding for Objective-C down the line. So now opening up an interface is just using the code generator for the language binding and adding appropriate access controls.

In summary designing interfaces using IDL/GWT services allowed us to easily open up our platform to other applications and languages.

1 comment: