Qt && C++ implementation of the hessian protocol
QHessian is based on Qt Framework. That means that you need only qt framework to use all features of hessian. No code generation needed to work with qhessian.
Comparsion of c++ implementations:
Project | Code generation | Libraries |
---|---|---|
hessianorb project | Yes | CURL |
hessiancpp project | No | SSLPP |
qhessian | No | Qt |
-
Get a local copy of the qhessian repository with command
git clone clone https://github.com/caiiiycuk/qhessian.git
-
Add include macro into your source file line
#include "{$path}/QHessian.h"
To call a remote method you need to:
- Create
QHessianMethodCall
object - Set the method paramters with operator
<<
- Invoke method
Example of calling method with signature int substract(int a, int b)
:
{
using namespace QHessian::in;
QHessian::QHessianMethodCall call("substract");
call << Integer(5) << Integer(4);
call.invoke(networkManager, url, reciver, SLOT(replySubtractCall()), SLOT(error(int, const QString&)));
}
Where:
networkManager
- is instance of QNetworkAccessManagerurl
- url to hessian servicereciver
- is QObject that receives reply or errorreplyMyMethodCall
- will be invoked with server responseerror(int, const QString&)
- will be invoked to process error
To parse server response you need to:
- Get an instance of
QHessian::QHessianReturnParser
- Parse results with operator
>>
Example of result parsing:
void replySubtractCall() {
qint32 result;
using namespace QHessian::out;
QHessian::QHessianReturnParser& parser = *(QHessian::QHessianReturnParser*) QObject::sender();
parser >> Integer(result); // 1
parser.deleteLater();
}
You should use peek
when you don't know what type or property goes next in response stream.
For example: service can return untyped object. This object may be a Apple or Banana or anything else.
To determine type use peek
method:
if (parser.peek(BeginObject("Apple"))) {
//can parse Apple type
} else if (parser.peek(BeginObject("Banana"))) {
//can parse Banana type
}
QHessian types (or properties) are just wrappers for hessian's object serialization types. Properties are divided into two namespaces:
QHessian::out
- contain properties that wrap responsesQHessian::in
- contain properties that wrap requests
In both namespaces there are properties:
Null
: Null represents a null pointer.Boolean
: Wraps the boolean data type. Has only two possible values: true and false. Use this data type for simple flags that track true/false conditionsInteger
: Wraps the int data type. Int is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).Long
: Wraps the long data type. Long is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive).Double
: Wraps The double (and float) data type. Double is a double-precision 64-bit IEEE 754 floating point.String
: Wraps the UTF8-encoded string.DateTime
: Represents a specific instant in time, with millisecond precision.Binary
: Wraps the binary data. Typically an array of byte.BeginCollection
: This proeprty is a marker for collection start.EndCollection
: This property is a marker for collection end.BeginMap
: This property is a marker for map begin.HasMoreMap
: This property is a marker for available elements in map.EndMap
: This property is a marker for end map.BeginObject
: This property is a marker for begin object.EndObject
: This property is a marker for end object.Ref
: This proerpty is a marker for shared and circular object references.
Each propety optionally has 'name', 'value' and 'type' attributes.
- Q.1 How to call void method()
- Q.2 How to read Null
- Q.3 How to read Boolean
- Q.4 How to read Integer
- Q.5 How to read Long
- Q.6 How to read Double
- Q.7 How to read Date
- Q.8 How to read String
- Q.9 How to read Binary
- Q.10 How to read untyped collection
- Q.11 How to read typed collection
- Q.12 How to read untyped map
- Q.13 How to read typed map
- Q.14 How to read Object
- Q.15 How to read references
- Q.16 How to read multi-typed object
- Q.17 How to write Null
- Q.18 How to write Boolean
- Q.19 How to write Integer
- Q.20 How to write Long
- Q.21 How to write Double
- Q.22 How to write Date
- Q.23 How to write String
- Q.24 How to write Binary
- Q.25 How to write untyped collection
- Q.26 How to write typed collection (String
[``]
) - Q.27 How to write untyped map
- Q.28 How to write typed map (hashtable)
- Q.29 How to write Object
- Q.30 How to write references
- Q.31 How to call int method(int, int)
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Object class:
package com.caucho.hessian.test;
public class TestObject implements java.io.Serializable {
private Integer _value;
public TestObject(Integer value)
{
_value = value;
}
public Object getValue()
{
return _value;
}
}
Java server example | QHessian client example |
|
|
From hessian docs:
An integer referring to a previous list, map, or object instance. As each list, map or object is read from the input stream, it is assigned the integer position in the stream, i.e. the first list or map is '0', the next is '1', etc. A later ref can then use the previous object. Writers MAY generate refs. Parsers MUST be able to recognize them.
ref can refer to incompletely-read items. For example, a circular linked-list will refer to the first link before the entire list has been read.
A possible implementation would add each map, list, and object to an array as it is read. The ref will return the corresponding value from the array. To support circular structures, the implementation would store the map, list or object immediately, before filling in the contents.
Each map or list is stored into an array as it is parsed. ref selects one of the stored objects. The first object is numbered '0'.
Object class:
package com.caucho.hessian.test;
import java.io.IOException;
import java.util.*;
/**
* Cons-cell for testing
*/
public class TestCons implements java.io.Serializable {
private Object _first;
private Object _rest;
public TestCons()
{
}
public TestCons(Object first)
{
_first = first;
}
public TestCons(Object first, Object rest)
{
_first = first;
_rest = rest;
}
public Object getFirst()
{
return _first;
}
public void setFirst(Object first)
{
_first = first;
}
public Object getRest()
{
return _rest;
}
public void setRest(Object rest)
{
_rest = rest;
}
}
Java server example | QHessian client example |
|
|
Java classes:
package name.caiiiycuk.test;
/* Fruit (root of hierarchy)*/
public class Fruit implements Serializable {
private static final long serialVersionUID = 6697223799952319341L;
private final float weight;
public Fruit(float weight) {
this.weight = weight;
}
public float getWeight() {
return weight;
}
}
/* Fruit -> Apple */
enum AppleColor {
RED,
GREEN
}
public class Apple extends Fruit {
private static final long serialVersionUID = 7908387468053290925L;
private final AppleColor color;
public Apple(float weight, AppleColor color) {
super(weight);
this.color = color;
}
public AppleColor getColor() {
return color;
}
}
/* Fruit -> Banana */
enum BananaSize {
HUGE, LITTLE
}
public class Banana extends Fruit {
private static final long serialVersionUID = 1180374660481214068L;
private final BananaSize bananaSize;
public Banana(float weight, BananaSize bananaSize) {
super(weight);
this.bananaSize = bananaSize;
}
public BananaSize getBananaSize() {
return bananaSize;
}
}
/* Fruit -> Apple -> PlasticApple */
public class PlasticApple extends Apple {
private static final long serialVersionUID = -8613694398769613071L;
public PlasticApple(float weight, AppleColor color) {
super(weight, color);
}
}
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Object class:
package com.caucho.hessian.test;
/**
* Empty object for short-encoding testing
*/
public class TestObject implements java.io.Serializable {
private Integer _value;
public TestObject()
{
}
public TestObject(Object value)
{
_value = value;
}
public Integer getValue()
{
return _value;
}
}
Java server example | QHessian client example |
|
|
From hessian docs:
An integer referring to a previous list, map, or object instance. As each list, map or object is read from the input stream, it is assigned the integer position in the stream, i.e. the first list or map is '0', the next is '1', etc. A later ref can then use the previous object. Writers MAY generate refs. Parsers MUST be able to recognize them.
ref can refer to incompletely-read items. For example, a circular linked-list will refer to the first link before the entire list has been read.
A possible implementation would add each map, list, and object to an array as it is read. The ref will return the corresponding value from the array. To support circular structures, the implementation would store the map, list or object immediately, before filling in the contents.
Each map or list is stored into an array as it is parsed. ref selects one of the stored objects. The first object is numbered '0'.
Object class:
package com.caucho.hessian.test;
/**
* Empty object for short-encoding testing
*/
public class TestObject implements java.io.Serializable {
private Integer _value;
public TestObject()
{
}
public TestObject(Object value)
{
_value = value;
}
public Integer getValue()
{
return _value;
}
}
Java server example | QHessian client example |
|
|
Java server example | QHessian client example |
|
|
Each QHessian implementation must pass these tests:
Primitive types (Group 1):
- read/write raw binary data
- read/write boolean
- read/write 64-bit millisecond date
- read/write 64-bit double
- read/write 32-bit int
- read/write 64-bit long
- read/write null
- read/write UTF8-encoded string
Recursive types (Group 2):
- read/write lists and arrays
- read/write maps and dictionaries
- read/write objects
- read/write refs for shared and circular object references.
Hessian 2.0 addtitional tests (Group 3):
- read/write object/list reference maps
- read/write class definition reference maps
- read/write type (class name) reference maps
We use standart test implementation form com.caucho.hessian.test:
- Test.java, service link (after server starts) localhost:8080/test1
- TestHessian2.java, service link (after server starts) localhost:8080/test2
Test.java includes this tests:
Test name | Description | Parameters | Return value |
---|---|---|---|
nullCall | Does nothing | void | void |
hello | Hello, World | void | string - Hellow, World |
subtract | Subtraction | int a, int b | a-b |
echo | Echos the object to the server | Object | Object |
fault | Throws an application fault | void | void throws IOException |
TestHessian2.java includes this tests:
Test name | Description | Parameters | Return value |
---|---|---|---|
methodNull | trivial null method call | void | void |
replyNull | Result of null | void | void |
replyTrue | Boolean true | void | Object |
replyFalse | Boolean false | void | Object |
replyInt_0 | Result of integer 0 | void | int |
replyInt_1 | Result of integer 1 | void | int |
replyInt_47 | Result of integer 47 | void | int |
replyInt_m16 | Result of integer -16 | void | int |
replyInt_0x30 | Result of integer 0x30 | void | int |
replyInt_0x7ff | Result of integer x7ff | void | int |
replyInt_m17 | Result of integer -17 | void | int |
replyInt_m0x800 | Result of integer -0x800 | void | int |
replyInt_0x800 | Result of integer 0x800 | void | int |
replyInt_0x3ffff | Result of integer 0x3ffff | void | int |
replyInt_m0x801 | Result of integer -0x801 | void | int |
replyInt_m0x40000 | Result of integer m0x40000 | void | int |
replyInt_0x40000 | Result of integer 0x40000 | void | int |
replyInt_0x7fffffff | Result of integer 0x7fffffff | void | int |
replyInt_m0x40001 | Result of integer m0x40001 | void | int |
replyInt_m0x80000000 | Result of integer -0x80000000 | void | int |
replyLong_0 | Result of long 0 | void | long |
replyLong_1 | Result of long 1 | void | long |
replyLong_15 | Result of long 15 | void | long |
replyLong_m8 | Result of long -8 | void | long |
replyLong_0x10 | Result of long 0x10 | void | long |
replyLong_0x7ff | Result of long x7ff | void | long |
replyLong_m9 | Result of long -9 | void | long |
replyLong_m0x800 | Result of long -0x800 | void | long |
replyLong_0x800 | Result of long 0x800 | void | long |
replyLong_0x3ffff | Result of long 0x3ffff | void | long |
replyLong_m0x801 | Result of long -0x801 | void | long |
replyLong_m0x40000 | Result of long m0x40000 | void | long |
replyLong_0x40000 | Result of long 0x40000 | void | long |
replyLong_0x7fffffff | Result of long 0x7fffffff | void | long |
replyLong_m0x40001 | Result of long m0x40001 | void | long |
replyLong_m0x80000000 | Result of long -0x80000000 | void | long |
replyLong_0x80000000 | Result of long 0x80000000 | void | long |
replyLong_m0x80000001 | Result of long -0x80000001 | void | long |
replyDouble_0_0 | Result of double 0.0 | void | double |
replyDouble_1_0 | Result of double 1.0 | void | double |
replyDouble_2_0 | Result of double 2.0 | void | double |
replyDouble_127_0 | Result of double 127.0 | void | double |
replyDouble_m128_0 | Result of double -128.0 | void | double |
replyDouble_128_0 | Result of double 128.0 | void | double |
replyDouble_m129_0 | Result of double -129.0 | void | double |
replyDouble_32767_0 | Result of double 32767.0 | void | double |
replyDouble_m32768_0 | Result of double -32768.0 | void | double |
replyDouble_0_001 | Result of double 0.001 | void | double |
replyDouble_m0_001 | Result of double -0.001 | void | double |
replyDouble_65_536 | Result of double 65.536 | void | double |
replyDouble_3_14159 | Result of double 3.14159 | void | double |
replyDate_0 | date 0 (01-01-1970 00:00 GMT) | void | date |
replyDate_1 | Date by millisecond (05-08-1998 07:51:31.000 GMT) | void | date |
replyDate_2 | Date by minute (05-08-1998 07:51:00.000 GMT) | void | date |
replyString_0 | A zero-length string | void | String |
replyString_null | A null string | void | String |
replyString_1 | A one-length string | void | String |
replyString_31 | A 31-length string | void | String |
replyString_32 | A 32-length string | void | String |
replyString_1023 | 1023-length string | void | String |
replyString_1024 | A 1024-length string | void | String |
replyString_65536 | A 65536-length string | void | String |
replyBinary_0 | A zero-length binary | void | Object |
replyBinary_null | A null string | void | Object |
replyBinary_1 | A one-length string | void | Object |
replyBinary_15 | A 15-length binary | void | Object |
replyBinary_16 | A 16-length binary | void | Object |
replyBinary_1023 | A 1023-length binary | void | Object |
replyBinary_1024 | A 1024-length binary | void | Object |
replyBinary_65536 | A 65536-length binary | void | Object |
replyUntypedFixedList_0 | Zero-length untyped list | void | Object |
replyUntypedFixedList_1 | 1-length untyped list | void | Object |
replyUntypedFixedList_7 | 7-length untyped list | void | Object |
replyUntypedFixedList_8 | 8-length untyped list | void | Object |
replyTypedFixedList_0 | Zero-length typed list (String array) | void | Object |
replyTypedFixedList_1 | 1-length typed list (String array) | void | Object |
replyTypedFixedList_7 | 7-length typed list (String array) | void | Object |
replyTypedFixedList_8 | 8-length typed list (String array) | void | Object |
replyUntypedMap_0 | zero-length untyped map | void | Object |
replyUntypedMap_1 | untyped map with string key | void | Object |
replyUntypedMap_2 | untyped map with int key | void | Object |
replyUntypedMap_3 | untyped map with list key | void | Object |
replyTypedMap_0 | zero-length typed map | void | Object |
replyTypedMap_1 | untyped map with string key | void | Object |
replyTypedMap_2 | typed map with int key | void | Object |
replyTypedMap_3 | typed map with list key | void | Object |
replyObject_0 | Returns a single object | void | Object |
replyObject_16 | Returns 16 object types | void | Object |
replyObject_1 | Simple object with one field | void | Object |
replyObject_2 | Simple two objects with one field | void | Object |
replyObject_2a | Simple repeated object | void | Object |
replyObject_2b | Two object with equals | void | Object |
replyObject_3 | Circular object | void | Object |
argNull | Null | void | Object |
argTrue | Boolean true | void | Object |
argFalse | Boolean false | void | Object |
argInt_0 | Integer 0 | void | Object |
argInt_1 | Integer 1 | void | Object |
argInt_47 | integer 47 | void | Object |
argInt_m16 | Result of integer -16 | void | Object |
argInt_0x30 | Integer 0x30 | void | Object |
argInt_0x7ff | Result of integer x7ff | void | Object |
argInt_m17 | integer -17 | void | Object |
argInt_m0x800 | Integer -0x800 | void | Object |
argInt_0x800 | Integer 0x800 | void | Object |
argInt_0x3ffff | Integer 0x3ffff | void | Object |
argInt_m0x801 | Integer -0x801 | void | Object |
argInt_m0x40000 | Integer m0x40000 | void | Object |
argInt_0x40000 | integer 0x40000 | void | Object |
argInt_0x7fffffff | Integer 0x7fffffff | void | Object |
argInt_m0x40001 | Integer m0x40001 | void | Object |
argInt_m0x80000000 | Result of integer -0x80000000 | void | Object |
argLong_0 | long 0 | void | Object |
argLong_1 | long 1 | void | Object |
argLong_15 | long 15 | void | Object |
argLong_m8 | long -8 | void | Object |
argLong_0x10 | long 0x10 | void | Object |
argLong_0x7ff | long x7ff | void | Object |
argLong_m9 | long -9 | void | Object |
argLong_m0x800 | long -0x800 | void | Object |
argLong_0x800 | long 0x800 | void | Object |
argLong_0x3ffff | long 0x3ffff | void | Object |
argLong_m0x801 | long -0x801 | void | Object |
argLong_m0x40000 | long m0x40000 | void | Object |
argLong_0x40000 | long 0x40000 | void | Object |
argLong_0x7fffffff | long 0x7fffffff | void | Object |
argLong_m0x40001 | long m0x40001 | void | Object |
argLong_m0x80000000 | long -0x80000000 | void | Object |
argLong_0x80000000 | Result of long 0x80000000 | void | Object |
argLong_m0x80000001 | Result of long -0x80000001 | void | Object |
argDouble_0_0 | double 0.0 | void | Object |
argDouble_1_0 | double 1.0 | void | Object |
argDouble_2_0 | double 2.0 | void | Object |
argDouble_127_0 | double 127.0 | void | Object |
argDouble_m128_0 | double -128.0 | void | Object |
argDouble_128_0 | double 128.0 | void | Object |
argDouble_m129_0 | double -129.0 | void | Object |
argDouble_32767_0 | double 32767.0 | void | Object |
argDouble_m32768_0 | Double -32768.0 | void | Object |
argDouble_0_001 | double 0.001 | void | Object |
argDouble_m0_001 | double -0.001 | void | Object |
argDouble_65_536 | double 65.536 | void | Object |
argDouble_3_14159 | Result of double 3.14159 | void | Object |
argDate_0 | date 0 (01-01-1970 00:00 GMT) | void | Object |
argDate_1 | Date by millisecond (05-08-1998 07:51 GMT) | void | Object |
argDate_2 | Date by minute (05-08-1998 07:51 GMT) | void | Object |
argString_0 | A zero-length string | void | Object |
argString_1 | A one-length string | void | Object |
argString_31 | A 31-length string | void | Object |
argString_32 | A 32-length string | void | Object |
argString_1023 | A 1023-length string | void | Object |
argString_1024 | A 1024-length string | void | Object |
argString_65536 | A 65536-length string | void | Object |
argBinary_0 | A zero-length binary | void | Object |
argBinary_1 | A one-length string | void | Object |
argBinary_15 | A 15-length binary | void | Object |
argBinary_16 | A 16-length binary | void | Object |
argBinary_1023 | A 1023-length binary | void | Object |
argBinary_1024 | A 1024-length binary | void | Object |
argBinary_65536 | A 65536-length binary | void | Object |
argUntypedFixedList_0 | Zero-length untyped list | void | Object |
argUntypedFixedList_1 | 1-length untyped list | void | Object |
argUntypedFixedList_7 | 7-length untyped list | void | Object |
argUntypedFixedList_8 | 8-length untyped list | void | Object |
argTypedFixedList_0 | Zero-length typed list (String array) | void | Object |
argTypedFixedList_1 | 1-length typed list (String array) | void | Object |
argTypedFixedList_7 | 7-length typed list (String array) | void | Object |
argTypedFixedList_8 | 8-length typed list (String array) | void | Object |
argUntypedMap_0 | zero-length untyped map | void | Object |
argUntypedMap_1 | untyped map with string key | void | Object |
argUntypedMap_2 | untyped map with int key | void | Object |
argUntypedMap_3 | untyped map with list key | void | Object |
argTypedMap_0 | zero-length typed map | void | Object |
argTypedMap_1 | untyped map with string key | void | Object |
argTypedMap_2 | typed map with int key | void | Object |
argTypedMap_3 | typed map with list key | void | Object |
argObject_0 | Returns a single object | void | Object |
argObject_16 | Returns 16 object types | void | Object |
argObject_1 | Simple object with one field | void | Object |
argObject_2 | Simple two objects with one field | void | Object |
argObject_2a | Simple repeated object | void | Object |
argObject_2b | Two object with equals | void | Object |
argObject_3 | Circular object | void | Object |