barrister
to convert IDL to JSON and produce docco style HTML docs for your interfaceBarrister is a RPC system that uses an external interface definition (IDL) file to describe the interfaces and data structures that a component implements. It is similar to tools like Protocol Buffers, Thrift, Avro, and SOAP.
Barrister emphasizes:
RPC calls are encoded as JSON-RPC 2.0 requests/responses. Consequently, any JSON-RPC 2.0 client should be able to consume a Barrister RPC service, but Barrister clients are preferred as they provide client side type validation and IDL discovery.
//
// The Calculator service is easy to use.
//
// Examples
// --------
//
// x = calc.add(10, 30)
// # x == 40
//
// y = calc.subtract(44, 10)
// # y == 34
interface Calculator {
// Adds two numbers together and returns the result
add(a float, b float) float
// Subtracts b from a and returns the result
subtract(a float, b float) float
}
package example;
public class Server implements Calculator {
public Double add(Double a, Double b) {
return a+b;
}
public Double subtract(Double a, Double b) {
return a-b;
}
}
package example;
import com.bitmechanic.barrister.HttpTransport;
public class Client {
public static void main(String argv[]) throws Exception {
HttpTransport trans = new HttpTransport("http://127.0.0.1:8080/example/");
CalculatorClient calc = new CalculatorClient(trans);
System.out.println(String.format("1+5.1=%.1f", calc.add(1.0, 5.1)));
System.out.println(String.format("8-1.1=%.1f", calc.subtract(8.0, 1.1)));
System.out.println("\nIDL metadata:");
// BarristerMeta is a Idl2Java generated class in the same package
// as the other generated files for this IDL
System.out.println("barrister_version=" + BarristerMeta.BARRISTER_VERSION);
System.out.println("checksum=" + BarristerMeta.CHECKSUM);
}
}
var barrister = require('barrister');
var express = require('express');
var fs = require('fs');
function Calculator() { }
Calculator.prototype.add = function(a, b, callback) {
// first param is for errors
callback(null, a+b);
};
Calculator.prototype.subtract = function(a, b, callback) {
callback(null, a-b);
};
var idl = JSON.parse(fs.readFileSync("../calc.json").toString());
var server = new barrister.Server(idl);
server.addHandler("Calculator", new Calculator());
var app = express.createServer();
app.use(express.bodyParser());
app.post('/calc', function(req, res) {
server.handle({}, req.body, function(respJson) {
res.contentType('application/json');
res.send(respJson);
});
});
app.listen(7667);
var barrister = require('barrister');
function checkErr(err) {
if (err) {
console.log("ERR: " + JSON.stringify(err));
process.exit(1);
}
}
var client = barrister.httpClient("http://localhost:7667/calc");
client.loadContract(function(err) {
checkErr(err);
var calc = client.proxy("Calculator");
calc.add(1, 5.1, function(err, result) {
var i;
checkErr(err);
console.log("1+5.1=" + result);
calc.subtract(8, 1.1, function(err, result) {
checkErr(err);
console.log("8-1.1=" + result);
console.log("\nIDL metadata:");
meta = client.getMeta();
keys = [ "barrister_version", "checksum" ];
for (i = 0; i < keys.length; i++) {
console.log(keys[i] + "=" + meta[keys[i]]);
}
});
});
});
<?php
$path = $_ENV["BARRISTER_PHP"];
include_once("$path/barrister.php");
class Calculator {
function add($a, $b) {
return $a + $b;
}
function subtract($a, $b) {
return $a - $b;
}
}
$server = new BarristerServer("../calc.json");
$server->addHandler("Calculator", new Calculator());
$server->handleHTTP();
?>
<?php
$path = $_ENV["BARRISTER_PHP"];
include_once("$path/barrister.php");
$barrister = new Barrister();
$client = $barrister->httpClient("http://localhost:8080/cgi-bin/server.php");
$calc = $client->proxy("Calculator");
echo sprintf("1+5.1=%.1f\n", $calc->add(1, 5.1));
echo sprintf("8-1.1=%.1f\n", $calc->subtract(8, 1.1));
echo "\nIDL metadata:\n";
$meta = $client->getMeta();
$keys = array("barrister_version", "checksum");
foreach ($keys as $i=>$key) {
echo "$key=$meta[$key]\n";
}
?>
from flask import Flask, request, make_response
import barrister
# Our implementation of the 'Calculator' interface in the IDL
class Calculator(object):
# Parameters match the params in the functions in the IDL
def add(self, a, b):
return a+b
def subtract(self, a, b):
return a-b
contract = barrister.contract_from_file("../calc.json")
server = barrister.Server(contract)
server.add_handler("Calculator", Calculator())
app = Flask(__name__)
@app.route("/calc", methods=["POST"])
def calc():
resp_data = server.call_json(request.data)
resp = make_response(resp_data)
resp.headers['Content-Type'] = 'application/json'
return resp
app.run(host="127.0.0.1", port=7667)
import barrister
trans = barrister.HttpTransport("http://localhost:7667/calc")
# automatically connects to endpoint and loads IDL JSON contract
client = barrister.Client(trans)
print "1+5.1=%.1f" % client.Calculator.add(1, 5.1)
print "8-1.1=%.1f" % client.Calculator.subtract(8, 1.1)
print
print "IDL metadata:"
meta = client.get_meta()
for key in [ "barrister_version", "checksum" ]:
print "%s=%s" % (key, meta[key])
# not printing this one because it changes per run, which breaks our
# very literal 'examples' test harness, but let's verify it exists at least..
assert meta.has_key("date_generated")
require 'sinatra'
require 'barrister'
class Calculator
def add(a, b)
return a+b
end
def subtract(a, b)
return a-b
end
end
contract = Barrister::contract_from_file("../calc.json")
server = Barrister::Server.new(contract)
server.add_handler("Calculator", Calculator.new)
post '/calc' do
request.body.rewind
resp = server.handle_json(request.body.read)
status 200
headers "Content-Type" => "application/json"
resp
end
require 'barrister'
trans = Barrister::HttpTransport.new("http://localhost:7667/calc")
# automatically connects to endpoint and loads IDL JSON contract
client = Barrister::Client.new(trans)
puts "1+5.1=%.1f" % client.Calculator.add(1, 5.1)
puts "8-1.1=%.1f" % client.Calculator.subtract(8, 1.1)
puts
puts "IDL metadata:"
meta = client.get_meta
[ "barrister_version", "checksum" ].each do |key|
puts "#{key}=#{meta[key]}"
end
1+5.1=6.1 8-1.1=6.9 IDL metadata: barrister_version=0.1.3 checksum=51a911b5eb0b61fbb9300221d8c37134
To convert calc.idl
to JSON and HTML forms, run:
barrister -t "Calculator Interface" -d calc.html -j calc.json calc.idl
Or use the hosted translator (this will only output the JSON file, not the docs):
curl --data-urlencode idl@calc.idl http://barrister.bitmechanic.com/run > calc.json
Output files:
calc.html
- A human readable interface doccalc.json
- A computer readable JSON file