JSON-RPC Service
The JSON-RPC Service supports JavaScript to Java AJAX communications using JSON-RPC-Java (Jabsorb replaced project oss.metaparadigm.com/jsonrpc/. As of March 2015 Google Code projects are only read-only and this project is archived too, though GIT exports are allowed probably until Jan 2016, e.g. https://github.com/gmkll/jabsorb).
Configuration
# ------------------------------------------------------------------- # # S E R V I C E S # # ------------------------------------------------------------------- ... services.JsonRpcService.classname=org.apache.turbine.services.jsonrpc.TurbineJsonRpcService ...
Usage
There are a number of things you need to do in order to add AJAX functionality to your webapp. First you implement the functions:
public class MyJsonFunctions { public String getHello(String clientParameter) { return "Hello " + clientParameter; } public String getGoodbye(String clientParameter) { return "Goodbye " + clientParameter; } }
Next you implement your Screen class to make your functions available:
public class MyJsonScreen extends JSONScreen { public void doOutput(RunData data) throws Exception { MyJsonFunctions myFunctions = new MyJsonFunctions(); // Session specific TurbineJsonRpc.registerObject(data.getSession(), "myFunctions", myFunctions); // Global //TurbineJsonRpc.registerObjectGlobal("testGlobal", testObject); super.doOutput(data); } }
Client Side: Synchronous AJAX Calls
Now we shift focus to your template classes. Firstly, there are a few useful utility functions that you need to make sure are available to the pages that will include AJAX functionality:
// Body onload utility (supports multiple onload functions) function SafeAddOnload(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { oldonload(); func(); }; } } // Prepare for possible JSON-RPC requests. // jsonurl must be set before calling this function. // First example synchronous call function jsonOnLoadSync() { try { jsonrpc = new JSONRpcClient(jsonurl); } catch(e) { if(e.message) { alert(e.message); } else { alert(e); } } } // Process a JSON-RPC request. function jsonEval(evalStr) { try { return eval(evalStr); } catch(e) { if(e.javaStack) { alert("Exception: \n\n" + e.javaStack); } else { alert("Exception: \n\n" + e); } } return null; }
In these pages you also need to include the JavaScript necessary to process the
JSON calls - this file is available as part of the JSON-RPC Java distribution
(it is included in the webapps\jsonrpc
directory):
$page.addScript($content.getURI('scripts/jsonrpc.js'))
Then you need to set up the specific handler for the page (synchronous example):
<script type="text/javascript"> <!-- ## Set up the JSON-RPC handler. var jsonurl = '$link.setScreen("MyJsonScreen")'; SafeAddOnload(jsonOnLoad); ## myArg below would be provided when you call this function from your ## web page (usually you would retrieve something via the DOM or your ## favorite JavaScript DOM wrapper library). function retrieveHello(myArg) { ## This is a synchronous call. var helloResult = jsonEval("jsonrpc.myFunctions.getHello(" + myArg + ")"); if(null == helloResult) { alert('Something went wrong!'); return; } ## Here you would again use the DOM to include the result somewhere on your ## page. } --> </script>
Client Side: Asynchronous AJAX Call
Alternatively, asynchronous calls require handling of the deferred objects, which could be done by using some kind of Promise) library. As an example a JQuery Promise Object model (supported since version 1.5) is shown. Usage of asynchronous calls conforms more to XMLHttpRequest specification.
// Prepare for possible JSON-RPC requests. // jsonurl must be set before calling this function. // Second example asynchronous call var deferred; function jsonOnLoad() { try { // This feature is available since jabsorb 1.1 release, cft. webapps/jaxrpc/CHANGES.txt. // JQuery Promises are available since jQuery 1.5/1.8 (with major changes). // This is just an example, any other Promise handling will do it. if (deferred != undefined) { return deferred; } else { deferred = jQuery.Deferred(function(defer) { // Add a default function as first parameter to enable asynchronous call. jsonrpc = new JSONRpcClient(function(result, e) { defer.resolve(result,e); }, jsonurl); }).promise(); return deferred; } } catch(e) { if(e.message) { alert(e.message); } else { alert(e); } } }
In these pages you also need to include the JavaScript necessary to process the
JSON calls - this file is available as part of the JSON-RPC-Java distribution
(it is included in the webapps\jsonrpc
directory):
$page.addScript($content.getURI('scripts/jsonrpc.js'))
Then you need to set up the specific handler for the page (in this case a asynchronous handler):
<script type="text/javascript"> <!-- ## Set up the JSON-RPC handler. var jsonurl = '$link.setScreen("MyJsonScreen")'; ## myArg below would be provided when you call this function from your ## web page (usually you would retrieve something via the DOM or your ## favorite JavaScript DOM wrapper library). function retrieveHello(myArg) { ## This is a an ansynchronous call as you provide as first parameter a callback function to getHello ## (Jabsorb JSON-RPC library expects it this way). var promiseA = jsonOnLoad(); var promiseB = jQuery.Deferred(); promiseA.done( function() { jQuery.Deferred(function(deferred) { jsonrpc.myFunctions.getHello( function(res,e) { deferred.resolve(); // not used promiseB.resolve(res); }, " + myArg + ")" ); }).promise(); } ); return jQuery.when(promiseA, promiseB); } # call function var helloResult; var promise = retrieveHello(myArg); promise.done( function(resultA,resultB) { helloResult = resultB; ## Here or in another dependent Promise you would again use the DOM to include the result somewhere on your ## page. } ); --> </script>
The above code is executable by users that are not logged into your application. Your Screen class can extend JSONSecureScreen to require that users be logged in before allowing execution.