Skip to content

talbright/hessian

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ruby Hessian Client

This is a Ruby implementation of the Hessian Binary Web Service Protocol. This is the Github version of the Ruby Hessian client originating from RubyForge, with patches and updates.

What is Hessian?

Here's the description from the Hessian site at http://www.caucho.com/hessian.

The Hessian binary web service protocol makes web services usable without requiring a large framework, and without learning yet another alphabet soup of protocols. Because it is a binary protocol, it is well-suited to sending binary data without any need to extend the protocol with attachments.

Please consult the Hessian home page or the Hessian 1.0.2 specification for more information.

Usage

The Hessian Ruby Client acts as a proxy for remote calls to Hessian services.

Hessian services are identified by URI's and the Ruby Hessian Client supports the http and https schemes. A call to a Hessian service is made like a regular method invocation in Ruby, and the Ruby Hessian Client will transparently serialize and deserialize to and from Ruby types.

Hessian's object serialization has 13 types, and the following mappings are used in the Ruby Hessian Client.

The 9 primitive types:

  • binary:: Hessian::Binary
  • boolean:: TrueClass or FalseClass
  • date:: Time
  • double:: Float
  • int:: Integer
  • long:: Integer
  • remote:: Not implemented!
  • string:: String
  • xml:: String
  • symbol:: String

The 2 combining types:

  • list:: Array
  • map:: Hash

Finally, the 2 special constructs:

  • null:: NilClass
  • ref:: The type referenced

The combining Hessian types can be given an explicit type understood by the service. This can be used to specify that a list only contain strings for example, or more importantly - this is how to serialize custom types. A custom type in this context is all types not conforming to the 13 types above, such as your own objects etc.

Custom types are serialized using the map with an explicit type specified and the underlying Ruby type must be a Hash. To specifiy an explicit type wrap the object in a Hessian::TypeWrapper or create the method +hessian_type+ on that object. See the examples below.

The Ruby Hessian Client will automatically convert instances of the Struct class to a Hash but for all other custom types you must create the conversion.

When a service reply (i.e. the return type of the method called) is a custom type, the Ruby Hessian Client will always return a Hash since the type returned might be unknown in Ruby. You may then convert that Hash to suite your needs.

Errors in a call to a Hessian service will result in a fault that is wrapped as a Hessian::HessianException.

Examples

To create a Hessian::HessianClient instance:

client = Hessian::HessianClient.new('http://localhost:8080/echo')

To specify a user and a password for basic authentication:

client.user, client.password = 'foo', 'bar'

To create a Hessian::HessianClient using a proxy:

proxy = { :host => 'proxy.foo.bar', :port => '80' }
client = Hessian::HessianClient.new('http://localhost:8080/echo, proxy)

The valid symbol keys for the proxy hash are: [:host] Proxy host [:port] Proxy port [:user] Proxy user [:password] Proxy password

Let's say that the service bound to echo is the following:

class Echo
  def echo(msg)
    "Echo reply: #{msg}"
  end
end

Then invoking the service call echo:

client.echo('hessian') => "Echo reply: hessian"

Explicit types

To specify an explicitly typed list as a Java string array for example (where foo is a method on the Java service used):

list = %w(one two three)
client.foo(Hessian::TypeWrapper.new('[string', list))

or

list = %w(one two three)
def list.hessian_type
  '[string'
end
client.foo(list)

Let's pretend that we want to call a Java service that has the following interface:

public interface PersonService implements Serializable {
   public Person addPerson(Person person);
}

and where the Person is defined as (could be a JavaBean as well):

public interface Person implements Serializable {
   public int age;
   public String name;
}

Person is a custom type so we need to send a Hash with an explicit type specified:

person = { 'age' => 32, 'name' => 'Christer Sandberg' }
reply = client.addPerson(Hessian::TypeWrapper.new('Person', person))

The Ruby Hessian Client will automatically convert a Struct to a Hash so the following will also work:

person = Struct.new(:age, :name)[32, 'Christer Sandberg']
class << person
  def hessian_type
    'Person'
  end
end
reply = client.addPerson(person)

The result from these invocations would be a Hash:

reply => { 'age' => 32, 'name' => 'Christer Sandberg' }

About

Hessian protocol implementation in Ruby

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages