PDA

View Full Version : Using ExtJS in Java with jabsorb or json-rpc-java



Arthur.Blake
28 Mar 2008, 9:01 AM
UPDATE 2008-04-22: Created new post in the plugins forum here: http://extjs.com/forum/showthread.php?t=33353
PLEASE POST YOUR COMMENTS/QUESTIONS THERE!

UPDATE 2008-04-21: Full demo and source code is now online here: http://jabsorb.org/jabsorb-trunk/projectmetrics.html

I've recently starting learning ExtJS. I must say, I'm very impressed. It's quite elegant, powerful and beautiful. The only issue I have is that it's a bit big... I spent a little time trying to make a smaller custom ExtJS build-- but it's still big! (mainly because I wanted to use a lot of the features!) That point aside, it's a great framework that I'll be spending a lot of time with in the upcoming days...

My first goal was to get the grid working with my favorite server side framework, jabsorb (http://jabsorb.org). After some extensive searching, I could not find anyone else using ExtJS with jabsorb (http://jabsorb.org) or json-rpc-java (http://oss.metaparadigm.com/jsonrpc/), so I coded it up!

jabsorb and json-rpc-java abstract away the whole server side interaction from you so you don't need to worry about URLs, XHR or even data serialization/transformation...

So, what I did was make a new kind of proxy, I based my code off of the HttpProxy, but it really just wraps a json-rpc call/callback.

This worked beautifully with the jabsorb framework and an ExtJS JsonReader. If anyone is interested, I will try and post a more complete example and demo with some server side code, later.

Here's the code:



/**
* @class Ext.data.JsonRpcProxy
* @extends Ext.data.DataProxy
*
* An implementation of Ext.data.DataProxy that invokes a json-rpc method call
* via the json-rpc-java and/or jabsorb library to retrieve the data needed by
* the Reader when it's load method is called.
*
* @constructor
* @param {Function} rpc The jabsorb or json-rpc-java function to call to
* retrieve the data object which the Reader uses to
* construct a block of Ext.data.Records. When invoked,
* it will be passed one json object containing the call
* parameters used to retrieve and optionally sort the data
* and a second callback function to load the resultant
* data from the result of the rpc call.
*/
Ext.data.JsonRpcProxy = function(rpc) {
Ext.data.JsonRpcProxy.superclass.constructor.call(this);
this.rpc = rpc;
};

Ext.extend(Ext.data.JsonRpcProxy, Ext.data.DataProxy, {
/**
* Load data from the requested source read the data object into
* a block of Ext.data.Records using the passed Ext.data.DataReader
* implementation and process that block using the passed callback.
*
* @param {Object} params This parameter is not used by the JsonRpcProxy class.
* @param {Ext.data.DataReader) reader The Reader object which converts the data
* object into a block of Ext.data.Records.
* @param {Function} callback The function into which to pass the block of Ext.data.records.
* The function must be passed <ul>
* <li>The Record block object</li>
* <li>The "arg" argument from the load function</li>
* <li>A boolean success indicator</li>
* </ul>
* @param {Object} scope The scope in which to call the callback
* @param {Object} arg An optional argument which is passed to the callback as its second parameter.
*/
load : function(params, reader, callback, scope, arg){
if(this.fireEvent("beforeload", this, params) !== false)
{
var o = {
params : params || {},
request: {
callback : callback,
scope : scope,
arg : arg
},
reader: reader,
callback : this.loadResponse,
scope: this
};

this.rpc(function(r,e){o.callback.call(o.scope,o,r&&!e, r||e);}, o.params);
}
else
{
callback.call(scope||this, null, arg, false);
}
},

// private
loadResponse : function(o, success, response){
if(!success){
this.fireEvent("loadexception", this, o, response);
o.request.callback.call(o.request.scope, null, o.request.arg, false);
return;
}
var result;
try {
result = o.reader.readRecords(response);
}catch(e){
this.fireEvent("loadexception", this, o, response, e);
o.request.callback.call(o.request.scope, null, o.request.arg, false);
return;
}
this.fireEvent("load", this, o, o.request.arg);
o.request.callback.call(o.request.scope, result, o.request.arg, true);
},

// private
update : function(dataSet){
},

// private
updateResponse : function(dataSet){
}
});


This will also work perfectly for the older json-rpc-java server side framework which jabsorb is based on, and indeed should work with any back end json-rpc 1.0 compliant server, (using the jsonrpc.js front end call methodology from jabsorb (http://jabsorb.org) or json-rpc-java (http://oss.metaparadigm.com/jsonrpc/).)

I just wrote this as if it were part of ExtJS and indeed it would be great if it were in a future release if the code is up to the ExtJS team's standards. If there are problems or issues with it, please point that out to me (I'm still quite new to ExtJS) -- I'd like this to be a good clean reusable implementation...

mystix
28 Mar 2008, 9:25 AM
Welcome to the Ext community :)
very neat work indeed.

as a jabsorb user, could you throw a little light on jabsorb vs dwr?
(i've been meaning to start on dwr and the DWRProxy (improved) plugin by @loeppky, but now that you've dangled a competing framework in front of me... ;))

p.s. you might also want to start a thread (with a link back here) in the 2.0 User Extensions and Plugins (http://extjs.com/forum/forumdisplay.php?s=&daysprune=&f=21) forum for your plugin.

Arthur.Blake
28 Mar 2008, 9:31 AM
Thanks for the welcome!

I answered that very question a couple of months ago here:

http://tech.groups.yahoo.com/group/json/message/933

mystix
28 Mar 2008, 9:37 AM
thanks for the info :)

(and after taking a peek at the committers' list, pardon me for mistaking you for a mere jabsorb user :">)

Arthur.Blake
28 Mar 2008, 9:48 AM
No offense taken whatsoever. After all, I am a very active user (and I just happen to be a committer as well ;))

jbeasley
30 Mar 2008, 8:35 PM
Thank you for your post on the JsonRpcProxy using ExtJS. I'm just learning ExtJS as well, and am also impressed by the framework and it's features.

I was looking to create a service without the XML overhead, and would be interested in seeing what's all involved in a working example of jabsorb w/ExtJS when ones available.

Czy
10 Apr 2008, 8:41 AM
Hi, Arthur.


This worked beautifully with the jabsorb framework and an ExtJS JsonReader. If anyone is interested, I will try and post a more complete example and demo with some server side code, later.


I have very, very interested in this example and demo. Jabsorb and Ext can be very nice conjuntion.
Thank you very much, Arthur.

Arthur.Blake
10 Apr 2008, 9:22 AM
I will try and get a more complete example together very soon.

Czy
17 Apr 2008, 7:39 AM
Hi, Arthur

Have you try some complete example already?

I need to know how use the jabsorb framework with an ExtJS JsonReader. It's very important for me.

Thanks you very much, Arthur.

flatburger
18 Apr 2008, 7:57 PM
can we have a full bundle example that we can test it here

we develop a backend system using jabsorb also, json -rpc

take a look at

httP//source.meruvian.com

they idea of our project, we develop proto to consume json server and read by swing, javame and extjs.

glad if we can exchange this experience.

Arthur.Blake
20 Apr 2008, 3:38 PM
I've coded up a much more complete example.
It demonstrates using ExtJS with jabsorb and an Apache Derby embedded database.

Demo is up here:

http://jabsorb.org/jabsorb-trunk/projectmetrics.html

You can build and run the full demo by checking out the jabsorb SVN trunk:

You will need JDK 1.5 or greater, and ant 1.65 or greater.


svn checkout http://svn.jabsorb.org/svn/jabsorb/trunk jabsorb
cd jabsorb
ant test.dist run


(this will run it directly with an embedded web server inside of ant)

then connect to
http://localhost:8084/projectmetrics.html (http://localhost:8084)

Let me know if you have any questions.

Czy
21 Apr 2008, 12:24 AM
Thanks a lot, Arthur.

I will inspect it and analyze inmediately.

Czy.

Czy
21 Apr 2008, 6:32 AM
I have coded a Java class named "Formularios"



public class Formularios implements Serializable {
public String[][] getTodasFamilias(){
String[][] familias = ..... ; // Content asignament to String[][]
return familias ;
}


In JSP page, I register this class:


<jsp:useBean id="DatosParaFormulario" scope="page" class="czy.flora.jabsorb.Formularios" />
<% JSONRPCBridge.registerObject( "datosForm", DatosParaFormulario ); %>


Until now, I make a call to getTodasFamilias method, from this way:


var jsonrpc = new JSONRpcClient("JSON-RPC");
var datosFamilias = jsonrpc.datosForm.getTodasFamilias();

and this work fine. But now, I write a proxy, as you example:


var proxy = new Ext.data.JsonRpcProxy( jsonrpc.datosForm.getTodasFamilias );
proxy.on( "loadexception", function(p,o,e){ excepcion(p,o,e); });


And as result, it throw an exception: code 591. method not found (session may have timed out)

What is I do wrong?

Thanks you for you help, Arthur.

Arthur.Blake
21 Apr 2008, 6:49 AM
Try changing the getTodasFamilias method to take one argument, a JSONObject (even if you don't use the argument.)



public class Formularios implements Serializable {
public String[][] getTodasFamilias(JSONObject query){
String[][] familias = ..... ; // Content asignament to String[][]
return familias ;
}
Because the proxy normally sends you a paging/query information Object (even if you aren't using it) you may need to do this...

Czy
21 Apr 2008, 7:14 AM
Eureka !! :)) Now, it works fine.

Thanks you very much, Arthur. Now I have two wonderfull tools for write web applications: Ext + Jabsorb.

Czy
21 Apr 2008, 9:13 AM
Try changing the getTodasFamilias method to take one argument, a JSONObject (even if you don't use the argument.)



public class Formularios implements Serializable {
public String[][] getTodasFamilias(JSONObject query){
String[][] familias = ..... ; // Content asignament to String[][]
return familias ;
}
Because the proxy normally sends you a paging/query information Object (even if you aren't using it) you may need to do this...

... and how I do (from javascript side) if I want to pass any argument to the Java class? This arguments go into JSONObject or separately?

And (in Java side) how can read those argument?

Thanks again, Arthur.

Arthur.Blake
21 Apr 2008, 9:31 AM
The way JsonRpcProxy works currently is to just pass a single JSONObject (or any other bean class you define.)

If you examine:

http://svn.jabsorb.org/websvn/jabsorb/trunk/webapps/jsonrpc/ext/ext-jabsorb.js?op=file&rev=0&sc=0

You can see pretty clearly how this works (it is passed as the params argument in the load method.)

One really simple way to override this would be to write your own function in front of the json-rpc call and manipulate the data before you call it, like this:

for example:



proxy = new Ext.data.JsonRpcProxy(function(callback, query){jsonrpc.Method.doStuff(callback, query, otherArg1, otherArg2,...);});
With a little JavaScript magic, you could do anything you want.

Czy
22 Apr 2008, 1:15 AM
I'm sorry, Arthur, but I do not understand to you. It must be by my badly English.

Let's work in a practical example. Until now, I coded proxy from this way :


var proxy = new Ext.data.JsonRpcProxy( jsonrpc.datosForm.getGeneros );

In Java side, I coded this method thus:


public String[][] getGenerosDeLaFamilia( JSONObject query ) {....}

and it work fine, but now, I want to modify the getGeneros method, with one argument.
It must be thus:


public String[][] getGenerosDeLaFamilia( JSONObject query, String arg ) {....}

That I must replace in javascript side? The code you have write:


proxy = new Ext.data.JsonRpcProxy(function(callback, query){jsonrpc.Method.doStuff(callback, query, otherArg1, otherArg2,...);});

where have I to place ?

Sorry by the inconvenience, and thanks one more time.

Arthur.Blake
22 Apr 2008, 2:51 AM
No hay problema...

In terms of your specific example, change:



var proxy = new Ext.data.JsonRpcProxy( jsonrpc.datosForm.getGeneros );
to



var arg = ... ;

var proxy = new Ext.data.JsonRpcProxy(
function (cb, query) {
jsonrpc.datosForm.getGeneros (cb, query, arg);
}
);
All we are doing is creating an anonymous function that does the actual JSON-RPC call and the proxy calls that anonymous function instead of the actual JSON-RPC call.

Therefore you can pass any arguments you want to the getGeneros method--

You could even omit the query argument entirely in this case and redefine your Java side method to not have the query argument since you don't use it...

Like this:



var arg = ... ;

var proxy = new Ext.data.JsonRpcProxy(
function (cb, query) {
jsonrpc.datosForm.getGeneros (cb, arg);
}
);

Czy
22 Apr 2008, 6:16 AM
Good. Now, I understand all.

Thanks a lot, Arthur.

gonzalez
26 Mar 2009, 12:18 PM
Dear Arthur!

I got a perl back-end using this library :http://search.cpan.org/~makamaka/JSON-RPC-0.96/lib/JSON/RPC.pm
How can I call this with your stuff?

Many thanks,
Gonzalez

Arthur.Blake
26 Mar 2009, 4:09 PM
I'm not sure... The code I wrote is designed to work with jsonrpc.js from the jabsorb library, so if you include jsonrpc.js and your perl back end is truly JSON-Rpc compliant, you could probably get it to work with a little bit of fiddling...