Note: this documentation used to refer to the module 'yaws_jsonrpc'. This module has been depracated in favor of 'yaws_rpc', which handles both JSON RPC, haXe and SOAP remoting. All references to 'yaws_jsonrpc' on this page were therefore changed to 'yaws_rpc'. For more specific information about SOAP, refer to the SOAP page.
The Yaws Json binding is a way to have Javascript code in the browser evaluate a remote procedure call in the Yaws server.JSON itself as described at http://www.json.org/ is basically a simple marshaling format which can be used from a variety of different programming languages, in particular it completely straightforward to implement in Javascript.
The yaws JSON implementation consist of Javascript client and a server side library which must be explicitly invoked by Erlang code in a .yaws page.
It is not particularly easy to show and explain an AJAX setup through JSON RPC, but here is an attempt:
First we have an HTML page which:
Includes the client side of the JSON library. The library is included in the yaws distribution and it is found under "www/jsolait/jsolait.js" .
Second the HTML code defines the name of a method, i.e. the name of a server side function which shall be called by the client side Javascript code
Finally the HTML code defines a FORM which is used to invoke the RPC. This is just a really simple example, really any Javascript code can invoke any RPC in more interesting scenarios than submitting a form
The HTML code looks like
<html>
<head>
<title>Testing html-json library</title>
</head>
<script src="jsolait/jsolait.js"></script>
<script>
var serviceURL = "json_sample.yaws";
var methods = [ "test1" ];
var jsonrpc = imprt("jsonrpc");
var service = new jsonrpc.ServiceProxy(serviceURL, methods);
function test() {
try {
foo = document.getElementById('foo').value;
bar = document.getElementById('bar').value;
document.getElementById('result').innerHTML =
"<PRE>" + service.test1(foo, bar) + "</PRE>";
} catch(e) {
alert(e);
}
return false;
}
</script>
<body>
<form action="" method="post" onSubmit="return test()">
<div id="result">
</div>
<p>
First Argument: <input id="foo" />
</p>
<p>
Second Argument: <input id="bar"/>
</p>
<p>
<input type="submit" value="Do JSON-RPC call"/>
</p>
</form>
</body>
</html>
This HTML code resides in file json_sample.html and it is the HTML code that is the AJAX GUI !!!
Following that we need to take a look at the page json_sample.yaws which is the "serviceURL" according to the Javascript code. This code defines the function to be called. Remember that the Javascript code defined one method, called "test1", this information will be passed to the serviceURL. The code looks like:
<erl module=sample_mod>
-compile(export_all).
out(A) ->
Peer = if
tuple(A#arg.clisock),
element(1, A#arg.clisock) == sslsocket ->
ssl:peername(A#arg.clisock);
true ->
inet:peername(A#arg.clisock)
end,
{ok,{IP,_}} = Peer,
A2=A#arg{state = [{ip, IP}]},
yaws_rpc:handler_session(A2, {?MODULE, counter}).
counter([{ip, IP}] = _State, {call, test1, Value} = _Request, Session) ->
io:format("Request = ~p~n", [_Request]),
IPStr = io_lib:format("Client ip is ~p~n" , [ IP ]),
OldSession = io_lib:format("Request is: ~p~nOld session value "
"is ~p~n", [ _Request, Session ]),
case Session of
undefined -> % create new session
NewSession = 0;
10 -> % reset session after reaching 10
NewSession = undefined;
N ->
NewSession = N + 1
end,
NewVal = io_lib:format("New session value is ~p ~n", [ NewSession ]),
Str = lists:flatten([IPStr,OldSession,NewVal]),
{true, 0, NewSession, {response, Str }}.
</erl>
The two important lines on the server side are
yaws_rpc:handler_session(A2, {sample_mod, counter}).counter([{ip, IP}] = _State, {call, test1, Value} = _Request, Session)The first line tells Yaws to forward all JSON-RPC methods to the "counter" function in the "sample_mod" module. The second line says, basically, - this is the counter function that will be called when the client invokes a method called 'test1'. We would duplicate this line with a different name than 'test1' for each RPC function we wish to implement.
On the client side we have
var methods = [ "test1" ];
var jsonrpc = imprt("jsonrpc");
var service = new jsonrpc.ServiceProxy(serviceURL, methods);
Which registers the Yaws page with the JSON-RPC handler and gives it a list of methods that the Yaws page can satisfy. In this case, it is only the method called 'test1'.
When we wish to return structured data - we simply let the user defined RPC function return JSON structures such as
{struct, [{field1, "foo"}, {field2, "bar"}]} for a structure and
{array, ["foo", "bar"]}for an array. We can nest arrays and structs in each other
Finally, we must stress that this example is extremely simple. In order to build a proper AJAX application in Yaws, a lot of client side work is required, all Yaws provides is the basic mechanism whereby the client side Javascript code, can RPC the web server for data which can be subsequently used to populate the DOM. Also required to build a good AJAX application is good knowledge on how the DOM in the browser works
Update:The yaws_rpc:handler will now also call: M:F(cookie_expire) which is expected to return a proper Cookie expire string. This makes it possible to setup the Cookie lifetime. If this calback function is non-existant, the default behaviour is to not set a cookie expiration time, i.e it will live for this session only.