View Full Version : Zend_Json_Server
albeva
29 May 2009, 8:05 PM
How to use this with Zend_Json_Server. Has anyone tried that? It seems that specs are different.
albeva
31 May 2009, 10:31 PM
Ok I decided to write a provider for the Ext.Direct to support JSON-RPC 2 specification ( http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal ) mind that this is still a work in progress, but I would like to hear your thoughts.
This provider requires a method definition according to "Service Mapping Description" proposal ( http://groups.google.com/group/json-schema/web/service-mapping-description-proposal )
There are 2 ways to provide the SMD - passing a JSON notation to constructor in the config or let the provider fetch the info from the server using GET request.
The provider: JsonRpc2.js
/**
* Ext.Direct provider for JS-RPC ver 2
* http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal
*
* @author Albert Varaksin
*/
// define the namespace
Ext.ns('Ext.albeva');
/**
* Declare the class
*/
Ext.albeva.JsonRpc2Provider = Ext.extend(Ext.direct.RemotingProvider, {
/**
* Service Mapping Description
*
* @param {Object} _smd
*/
smd : null,
/**
* Create JSON-RPC 2 provider
* @param {Object} config
*/
constructor : function (config)
{
if (config.namespace == undefined)
{
throw "JsonRpc2 requires a namespace";
return;
}
Ext.albeva.JsonRpc2Provider.superclass.constructor.call(this, config);
},
/**
* Connect
*/
connect : function ()
{
if(this.url)
{
this.initAPI();
}
else if(!this.url)
{
throw 'Error initializing RemotingProvider, no url configured.';
}
},
/**
* Request success
*/
onSMDSuccess : function (response, opts)
{
// get response
this.initSMD(Ext.decode(response.responseText));
},
/**
* Initalize SMD
* @param {Object} smd
*/
initSMD : function (smd)
{
// check for correct response
if (smd == undefined || smd == undefined)
{
throw "Invalid response. Expected Service Map Description";
return;
}
// check for version
if (smd.SMDVersion != '2.0')
{
throw "JsonRpc2 works only with version 2.0 of Service Map Description specification";
}
// iterate through the methods
for (var name in smd.methods)
{
var info = smd.methods[name];
var m = {
len : info.parameters.length
}
this.namespace[name] = this.createMethod(name, m);
}
// finalize and notify
this.smd = smd;
this.connected = true;
this.fireEvent('connect', this);
},
/**
* SMD failed.
*
* @param {Object} response
* @param {Object} opts
*/
onSMDFailure : function (response, opts)
{
// do something
},
/**
* Initalize API. The information is pulled using
* Service Mapping Description
* http://groups.google.com/group/json-schema/web/service-mapping-description-proposal
*/
initAPI : function () {
if (this.smd != undefined)
{
this.initSMD(this.smd);
}
else {
Ext.Ajax.request({
url: this.url,
success: this.onSMDSuccess,
failure: this.onSMDFailure,
scope: this
});
}
},
/**
* Fool...
*
* @param {Object} xhr
*/
parseResponse: function(xhr){
if(!Ext.isEmpty(xhr.responseText)){
var o = (typeof xhr.responseText == 'object') ? xhr.responseText : Ext.decode(xhr.responseText);
o.type = 'rpc';
o.tid = o.id;
return o;
}
return null;
},
/**
* Get RPC call data according to
* JSON-RPC 2 spec
*/
getCallData : function (t)
{
return {
jsonrpc : this.smd.methods[t.action].envelope,
method : t.action,
params : t.data,
id : t.tid
};
}
})
Ext.Direct.PROVIDERS['jsonrpc2'] = Ext.albeva.JsonRpc2Provider;
Sample JS app.js
/**
* Simple js-rpc test
*/
Ext.onReady( function () {
Ext.Direct.addProvider({
type : 'jsonrpc2', // the provider type.
url : 'server.php',
id : 'my-provider',
namespace : 'Calculator', // required! methods will be placed in taht
// namespace.
enableBuffer: false,
smd : mySmdApi, // this can be omitted in whitch case
// provider will make GET request to the url
// to try and get SMD
listeners : {
'connect' : Loaded
}
});
});
/**
* Fully loaded...
*/
function Loaded ()
{
new Ext.Button({
renderTo : document.body,
text : 'Send',
listeners : {
'click' : function () {
Calculator.add(10,10, function (a, b) {
alert(a);
});
}
}
});
}
Sample PHP using Zend_Json_Server (Zend version 1.8): server.php
<?php
/**
* Simple example of Zend_Json_Server
*/
/**
* Calculator - sample class to expose via JSON-RPC
*/
class Calculator
{
/**
* Return sum of two variables
*
* @param int $x
* @param int $y
* @return int
*/
public function add($x, $y)
{
return $x + $y;
}
/**
* Return difference of two variables
*
* @param int $x
* @param int $y
* @return int
*/
public function subtract($x, $y)
{
return $x - $y;
}
/**
* Return product of two variables
*
* @param int $x
* @param int $y
* @return int
*/
public function multiply($x, $y)
{
return $x * $y;
}
/**
* Return the division of two variables
*
* @param int $x
* @param int $y
* @return float
*/
public function divide($x, $y)
{
return $x / $y;
}
}
// Autoload Zend classes
// -----------------------------------------------------------------------------
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
// The JSON-RPC server
// -----------------------------------------------------------------------------
$server = new Zend_Json_Server();
$server->setClass('Calculator');
// GET request
if ('GET' == $_SERVER['REQUEST_METHOD']) {
// Indicate the URL endpoint, and the JSON-RPC version used:
$server->setTarget('/testing/jsonserver/server.php')
->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
// Grab the SMD
$smd = $server->getServiceMap();
// if passing JSON notation directly to the
// config of the provider then collect SMD into a variable
echo "var mySmdApi = ($smd)";
// otherwise:
// header('Content-Type: application/json');
// echo $smd;
return;
}
// handle the request
$server->handle();
Your thoughts, suggestions etc are welcome. I haven't fully tested this yet and there are some problems - for example form submit is not yet supported. Also JSON_RPC does nto return the action as Ext.Direct requires. But these can be solved.
Although you suggest to echo $mySmdApi variable at server-side it seems that JsonRpc2Provider doesn't use smd variable in method requests. I added a line of code to initSMD method:
// finalize and notify
this.smd = smd;
this.url = smd.target; // now provider use smd.target url (as noted in SMD specification) in method calls
// instead of url specified in Ext.Direct.addProvider
this.connected = true;
this.fireEvent('connect', this);
And now we can use different urls for getting SMD and calling methods.
albeva
2 Jun 2009, 9:06 AM
probably better this way. thanks
ryzmen
7 Jun 2009, 8:38 AM
Great job, albeva.
I think there's an error somewhere in Ext.Direct (or maybe in JsonRpc2?). When I call remote method without parameters, JSON request looks like this:
{"jsonrpc":"JSON-RPC-2.0","method":"getStoragesData","params":null,"id":3}
params should be JSONArray, not null. Zend_Json_Server_Request also throws an exception.
PS. Hi everybody :) It's my 1st post here and 3rd intensive day with ExtJS ;) I wanna to use them in my new project.
Hi, I've noticed this error too. Once I've solved this problem, but now can't remember how :)
I think there may be a problem in Ext.encode (Ext.util.JSON.encode) method: if no data is present it returns "null" as a result:
this.encode = isNative ? JSON.stringify : function(o){
if(typeof o == "undefined" || o === null){
return "null";
...
Now I'm trying to use JsonRpc2 function as directFn in DirectStore object, but I'm getting infinite loop in Ext.util.JSON.encode method - 'params' field of jsonData, that is being encoded before calling server function, contains cycle references :(
ryzmen
11 Jun 2009, 10:28 AM
myram, you get infinite loop when there're more then 1 or 2 params to the remote func? I found a solution: DirectProxy.paramOrder.
myram
17 Jun 2009, 1:42 AM
Thanx, but I've nevertheless decided to use api.load function to call remote proc instead of directFn - too difficult ( for me :) ) to find solution for successful using remote proc as directFn in DirectStore.
And I offer to use this changed code in case of calling remote function without parameters (you've mentioned above) in JsonRpc2 provider:
getCallData : function (t)
{
return {
jsonrpc : this.smd.methods[t.action].envelope,
method : t.action,
params : t.data === null ? new Array() : t.data,
id : t.tid
};
}
For me it works.
albeva
17 Jun 2009, 5:11 AM
Thanks guys. I've been working a bit on this and will soon post updated version.
Dumbledore
25 Jun 2009, 2:50 AM
can some made a complete package with a samle code (Ext-Zend)?
pmarko
27 Jun 2009, 12:21 PM
I wouuld like to see sample package as well. Thanks.
jon.whitcraft
6 Nov 2009, 7:19 AM
Any update on the JsonRpc2 provider?
Air_Mike
6 Nov 2009, 9:50 AM
+1 interested in this
JorisA
8 Nov 2009, 6:50 AM
I also would really like to see Ext/ZF integretion. any updates? :">
jon.whitcraft
9 Nov 2009, 6:22 AM
I'm trying to get this to work with parameters but it's not working..can anyone help?
albeva
17 Nov 2009, 2:39 PM
I'm trying to get this to work with parameters but it's not working..can anyone help?Sample?
I will review this over the weekend and post an updated package with a sample soon.
mynsa04
10 Jun 2010, 7:08 AM
it's still alive?
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.