Using hessiancpp to call Java servlets from C++
Background
Hessian is a binary web service protocol. It’s quite efficient (see Daniel Gredler’s and Miquel’s benchmarks) and it’s dynamically typed.
[proto-footnote] Dynamic typing is of course very convenient for Java-Java communication building from a single source tree. I expect it’ll be much less of a good thing if we make a habit of calling from C++ to Java via Hessian, at which point the overhead of using a different remoting mechanism which uses an IDL might be worth it, to enforce a contract between the two languages.
Hessian is written by a company called Caucho, who also make Resin, a webserver / servlet container.
Grammar
Caucho provide what they call a “Formal Definition” of the Hessian protocol; it would be more helpful if it didn’t omit several carriage returns - there’s an older version of the document which is better formatted. To be honest, I found Caucho’s documentation to be a bit of a maze of twistly little packages, all alike.
Bindings for C++
One of the reasons Nominet originally chose to use Hessian was that client bindings are available for many languages, including C++. The (only) C++ binding is hessiancpp [sourceforge]. It is released under LGPL, but isn’t being actively maintained.
Building hessiancpp
hessiancpp depends on a library called “sslpp”. A bit of searching brings up a package called SSL++; this looks promising but it’s a red herring; hessiancpp is written to use a modified version of it.
The modified version is hidden in the CVS repository for hessiancpp. It’s had a few minor changes and a GPL licence added to the original author’s copyright statement.
With a bit of fiddling to Boost include paths etc., sslpp builds fine & so does hessiancpp.
Running a basic/demo program
There are some tutorials on Caucho’s site. They use Resin, which is simple to set up. Of course if you’re already using another server (e.g. TomCat) then you can’t run both simultaneously on the same port!
- install Resin
- set Resin’s user/password by getting server to create a digest & pasting that into [RESIN_INSTALL_DIR]/conf/resin.conf
- download hessian_3.1.6.jar (or whatever’s the current version)
Make a Java package (which for example I’ll call pkg_foo) with demo servlet class interface (e.g. IFoo). Write a concrete class (e.g. CFoo) which
- imports com.caucho.hessian.server.HessianServlet;
- extends HessianServlet
- implements IFoo
and compile with the hessian_xxx.jar and [RESIN_INSTALL_DIR]/lib/jsdk-15.jar in the classpath.
Copy or make a link in [RESIN_INSTALL_DIR]/webapps/ROOT/WEB-INF/classes to your demo servlet package directory.
Add a file web.xml in [RESIN_INSTALL_DIR]/webapps/ROOT/WEB-INF/ containing something like:
<web-app xmlns=“http://caucho.com/ns/resin”>
<servlet
servlet-name=“foo”
servlet-class=“pkg_foo.CFoo”/>
<servlet-mapping
url-pattern=“/hessian/foo”
servlet-name=“foo”/>
</web>
Make a demo client:
- import com.caucho.hessian.client.HessianProxyFactory;
- import your servlet interface
- making a Hessian call like:
HessianProxyFactory factory = HessianProxyFactory();
String url = (“http://” + “localhost” + “:” + “8080″ + “/hessian/foo”);
try {
IFoo f = (IFoo) factory.create(IFoo.class, url);
int i = f.fmethod(42);
}
catch (etc. …)
{ … }
- compile with hessian_xxx.jar in the classpath
- run with hessian_xxx.jar in the classpath
Calling from C++
So far we’ve just demonstrated that you can call from Java->Java. It’s easier because both client & server can share the Java interface. Calling from C++ using hessiancpp will be more laborious, so it was worth the overhead of having made it work from Java first. We’ve verified the server set-up, and also now have a framework for prototyping the methods & their parameters, and a fallback.
There’s an example “main” in the hessiancpp distribution;
- create a hessian_proxy instance, noting that:
- hostspec is “host:port” (i.e. no “http://”)
- leading slash is expected on url (e.g. “/hessian/pkg_foo”) - call method “call”, passing in the method name, the parameter count & the parameters
This is where you meet a hurdle: hessiancpp doesn’t include much in the way of error-handling/checking, for example
- parameter count isn’t checked against number of parameters
- result for the HTTP call doesn’t check the HTTP status code (e.g. 200=success, 404=page not found etc)
- the decoding of hessian datatype “fault” makes assumptions about which fields will be populated (and their ordering) in the response, so crashes decoding some basic exceptions e.g. “wrong method name”
- doesn’t cope with exceptions thrown in Java-land
It’s often not obvious how to construct more complicated types; what/whether to put in the “type” fields of a Hessian map representing an object, for example. However if you add code to dump the Hessian datastream input & outputs it’s straightforward to refer to the Hessian grammar & make sense of the datastream. It’s a small matter of programming to modify hessian_wrappers & hessian_input to make hessiancpp decode it correctly, and hessian_output to serialise correctly.
Download
Improvements
I’ve made some changes to hessiancpp, which I’ll document and post on this blog.








