Nov 30 2008

A ride with hessian

Published by Kefah Issa at 11:54 pm under General, Grails, c++, groovy, java

Today, I came across what I call a deep-sea pearl. I came to know Hessian, the binary web service protocol.

Some time ago I blogged about the same idea Predictable Binary Representation (PBR)
, naively thinking that no one has done this before.

With the help of few friends, and some googling there turned out to be a zillion solutions that attempt to address that very problem; the etch has been really scratched by many, and the need for a compact, and predictable binary protocol is a must, no matter how fast the internet is or will become.

Parsing JSON, despite the fact that its among the most elegant human-readable text-protocols, would consume CPU cycles, and would be susceptible to errors more likely than not.

With a Binary protocol, you could …

  • Know the total size of a message (aka packet) before hand
  • Have its checksum that you can verify
  • For every single data entry, you would exactly know what size in bytes to expect next and what the type of data is, as opposed to checking for special marking characters to tell when an end of that item is reached.
  • No need to escape any special characters, should they occur plainly within the data. The problems JSON and XML have because of this deficiency are huge. Why all that hassle?! A question that puzzled me for years.
  • Far more compact in size, even without compression. There are no xml tags repeating for every node. In hessian, a dictionary of entry-names is only defined once at the header, then corresponding id’s are used across the message.

From the technical perspective, when we talk about web services, we are talking about software-to-software communication. As such Human-readable protocols are mere overhead to say the least. We should focus more on optimizing software-to-software protocol than making it look good to the human eyes.

Forget about XML, JSON or anything similar; and consider the beauty, performance, and optimization of binary protocols.

Despite the competition from Thrift (by facebook), Protocol Buffers (by google), and ASN.1 (older standard), along many others, Hessian (by Caucho) stands out from the crowd …

Let me tell you why I quickly fell in love with Hessian,

  • Dead-simple to use, both server-side and client-side.
  • Can be equally used on Java, C/C++, .Net, Ruby, PHP, Flash and so forth.
  • Saves tons of bandwidth, cpu cycles and increases reliability
  • Runs via the firewall-friendly http-protocol

It was intriguing when reading the features and specifications. Being the hands-on person I am, I only believe what I can do …

So, lets roll up our sleeves and get in a quick practical session with Hessian ….

Hessian and Java

Preparations

Create few folders to host our samples

mkdir -p hessian/lib
cd hessian

I downloaded the latest hessian library jar file to my local lib folder.

wget 'http://hessian.caucho.com/download/hessian-3.2.0.jar'
mv hessian-3.2.0.jar lib

Using jetty 6.1.x or 7.x would do equally well,

wget 'http://dist.codehaus.org/jetty/jetty-6.1.12/jetty-6.1.12.zip'

Unpack

 unzip jetty-6.1.12.zip

we only need three jars, as we are going to use the compact embeddable jetty jars.

mv jetty-6.1.12/lib/jetty-* jetty-6.1.12/lib/servlet-api-2.5-6.1.12.jar lib/
rm -rf jetty-6.1.12

Make sure to define CLASSPATH environment variable that would properly point to all the jars in our lib folder. for that I use the following setenv.sh script that can be sourced every time needed.

setenv.sh

#!/bin/bash
CLASSPATH="."
for myjar in $(find $PWD/lib -iname '*.jar'); do CLASSPATH=$CLASSPATH:$myjar; done;
export CLASSPATH

Then you can source it like this

source setenv.sh

Define (create) our API interface using POJO

BasicAPI.java

public interface BasicAPI {
	public String hello ();
}

Create the service API implementation and expose via an embeddable servlet container

BasicService.java

import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.Server;
import com.caucho.hessian.server.HessianServlet;
 
public class BasicService extends HessianServlet implements BasicAPI {
	private String _greeting = "Hello, world";
 
	public void setGreeting(String greeting) {
		_greeting = greeting;
	}
 
	public String hello() {
		return _greeting;
	}
 
	public static void main (String [] args) throws Exception {
		Server server = new Server(8080);  
		Context context = new Context(server, "/", Context.SESSIONS);
		context.addServlet(BasicService.class, "/basic");
		server.start();
	}
}

Compile the Java Server API and Interface and start our service

javac BasicService.java 
java BasicService

Create the Client app

Client.java

import com.caucho.hessian.client.*;
public class Client {
	public static void main (String [] args) throws Exception {
		String url = "http://localhost:8080/basic";
		HessianProxyFactory factory = new HessianProxyFactory();
		BasicAPI basic = (BasicAPI) factory.create(BasicAPI.class, url);
		System.out.println("basic.hello() said : " + basic.hello());
	}
}

Compile and run the client

javac Client.java
java Client

C’est tout! (Thats all). Your java-based client-server hessian binary protocol web service system is up and running. Wow!

Hessian in Ruby

After download and unpacking hessian library for ruby it only takes three lines of code to connect to our java web service

require "lib/hessian.rb"
client = Hessian::HessianClient.new('http://localhost:8080/basic')
print client.hello

It seems that you can also easily create hessian-based services via ruby, but i didn’t dig into it.

Hessian in PHP
Download, unpack and make accessible via apache the php library of hessian. There is a minor glitch in Hessian PHP in which the DateTime class conflicts with Php 5.2 pre-defined DateTime class. Simply re-touch the library code and rename that class.

php_hessian_client.php

<?
include_once 'HessianClient.php';
$proxy = &new HessianClient('http://localhost:8080/basic');
echo $proxy->hello(); 
?>

You can also write a simple hessian web service api provider …
php_hessian_service.php

<?
class Math{    
  function add($n1,$n2) {        
    return $n1+$n2;    
  }    
  function sub($n1,$n2) {        
    return $n1-$n2;    
  }    
  function mul($n1,$n2) {        
    return $n1*$n2;    
  }    
  function div($n1,$n2) {        
    return $n1/$n2;    
  }
}
include_once 'HessianService.php';
$wrapper = &new HessianService();
$wrapper->registerObject(new Math);
$wrapper->service();
?>

More!
Wait, there is more!

  • Lanuages Support Hessian is supported on Grails via the remoting plugin, I didn’t try the rest of the languages supported by hessian yet, but it looks that they would be fine.
  • Authentication and Http Proxy
    You can also make use of Http Authentication to add a security layer on top of your api’s, and proxy-by-pass in case there is a proxy in the way.
  • Additional Services built on top of Hessian
    There are also two interesting technologies by Caucho built on top of hessian, viz BAM and comet .
  • Performance benchmarks
    This is an interesting benchmark, demonstrating how hessian perform against classical text and binary protocols.

Gotcha’s
I can see a couple of minor gotcha’s in Hessian library that can be addressed …

A. The language-support projects seem not to be updated for a long time, some more than a year. Those projects only support hessian protocol version 1.0.x and don’t support the latest hessian 2 protocol.

B. The thing I really missed is a JavaScript library that connects me to a hessian service directly. That alone will immediately offer a great value to AJAX applications. I don’t see that far from possible, given the fact that there is already an ActionScript implementation for Flash. I hope someone will dedicate the effort to make that a reality.

Conclusion
The Internet is coming back to its senses :) , using Binary-based communication protocols might sound 30-year old concept, but it brings a lot on the table that current text-based human-readable protocols don’t.
I am all forward for making use of such protocols in SaaS / SOA setups. Simply Binary Protocols such as hessian, could provide an alternative communication option for today’s SOAP/XML-RPC/JSON ones.

3 responses so far

3 Responses to “A ride with hessian”

  1. blink4blogon 04 Dec 2008 at 11:26 am

    hi there,

    thanks for the nice article but there is a little problem with the shell script:

    bash: setenv.sh: line 4: syntax error near unexpected token `/home/user1/workspace/hessian/lib/jetty-util-6.1.12.jar’
    bash: setenv.sh: line 4: `/home/user1/workspace/hessian/lib/jetty-util-6.1.12.jar’

    anything wrong i did?

    P/S: This is the content of the setenv.sh after sourced:

    #!/bin/bash
    CLASSPATH=”.”
    for myjar in /home/david/workspace/hessian/lib/hessian-3.2.0.jar
    /home/david/workspace/hessian/lib/jetty-util-6.1.12.jar
    /home/david/workspace/hessian/lib/servlet-api-2.5-6.1.12.jar
    /home/david/workspace/hessian/lib/jetty-6.1.12.jar; do CLASSPATH=.:; done;
    export CLASSPATH

  2. Kefah Issaon 04 Dec 2008 at 12:33 pm

    Hello blink4blog,

    Please create the setenv.sh file, using your favourite editor, place the script lines into it.
    then source it. I updated that section of the blog too.

    Thanks,
    - Kefah.

  3. blink4blogon 05 Dec 2008 at 6:34 am

    thanks Kefah, now it works.

Trackback URI |