Class file requirements on Java client.

22 views
Skip to first unread message

Dominic

unread,
Dec 11, 2007, 1:36:07 PM12/11/07
to json-rpc-client
Hi Sasha,

many thanks for this library. I had a look at the code and had one
slight issue
which is no doubt related to my specific requirements. One of the
things which attracted me to JSON-RPC (as against another remoteing
protocol such as Hessian http://www.caucho.com/resin-3.0/protocols/hessian-messaging.xtp)
is that the client doesn't need to have access to the server class
files, namely the interface classes.

In your implementation, the openProxy method requires access to the
class type of the object which is being retrieved (even if it is
simply an interface). This creates a coupling between the client and
server that I am trying to remove.

I understand that most pure Java clients will require access to the
interface classes at some point, although my particular client doesn't
as it uses the Rhino JavaScript interpreter to transform the
constructed Java proxy object into a JavaScript equivalent.

I was wondering if there might be some way to make the openProxy
method more generic whereby it just returns an object whose signature
is constructed dynamically via introspection. Otherwise, it may be
possible to construct a Scriptable object
(org.mozilla.javascript.Scriptable) directly.

Anyway, I'll keep experimenting.

Regards,
Dominic.

sash...@gmail.com

unread,
Dec 11, 2007, 4:46:55 PM12/11/07
to json-rp...@googlegroups.com, jabsor...@googlegroups.com
Hi Dominic --

I also like JSON-RPC for looser coupling between client and server.
Still, in order to do RPC you need to expose at least some information
about the object you are talking to.

So if you know the server class' methods and their parameters, this is
already an interface description. Now using this information it could be
possible to generate Java interface file, something along the lines of
WSDL->proxy class compilers in SOAP implementaitons. Is this something
that may help?

I for one like the fact I can use Java interface as "protocol
definition". BTW, client and server definitions does not have to be 100%
in sync. In many cases, older clients may be able to talk to newer
servers and vise versa.

Also, could you give more information about your use case?

Thanks,
-- Sasha

Dominic

unread,
Dec 14, 2007, 10:50:59 AM12/14/07
to json-rpc-client
Hi Sasha,

thanks for the reply. My use case might be a little bit unique,
although I feel that removing the necessity to have the interface
class files available on the client may help in other situations as
well.

I'm in the process of developing a kind of universal client which
allows for the display of rich user interfaces (http://www.uidl.net).
This client includes a Rhino JavaScript interpreter and downloads
scripts containing the UI code from a server (as per HTML for a
browser but for complex UIs).

I would like to use JSON-RPC to transparently call server side objects
from thir JavaScript proxies on the client. I can do this if I use the
JavaScript JSON-RPC client from within Rhino, although this isn't
efficient. I'd prefer to be able to use a native Java JSON-RPC client
to retreive the Java proxies and then just get Rhino to expose them as
JavaScript equivalents.

As you suggest, we have the interface information available. In fact,
this is how the standard (JavaScript) client constructs proxies. It
issues a request when it loads of the type:

{"id": 1, "params": [], "method": "system.listMethods"}

... and the server responds with a response like:

{"id":1,"result":
["serviceTranslationManager.translateAllLocal","productManager.isEnabled","serviceManager.getAllServices","serviceTranslationManager.getNonTranslatedCriterium","productManager.getHibernateTemplate","serviceTranslationManager.translate","serviceManager.getSessionFactory","serviceManager.getHibernateTemplate","productManager.afterPropertiesSet","productManager.setHelpDeskManager","serviceManager.setEnabled","productTranslationManager.translateLocal","productManager.getEnabledProducts","productTranslationManager.translate","serviceTranslationManager.afterPropertiesSet","serviceManager.update","serviceTranslationManager.setTranslation","serviceManager.setHibernateTemplate","companyManager.getCompanyName","serviceManager.setSessionFactory","productTranslationManager.translateAll","serviceManager.setHelpDeskManager","serviceTranslationManager.setHibernateTemplate","productTranslationManager.translateAllLocal","serviceManager.getService","serviceTranslationManager.getHibernateTemplate","serviceTranslationManager.setType","productManager.setEnabled","serviceTranslationManager.setProductManager","productManager.update","serviceManager.afterPropertiesSet","serviceTranslationManager.getProductList","productTranslationManager.afterPropertiesSet","serviceTranslationManager.getNonUniqueCriteriumNames","serviceManager.getProduct","companyManager.setHelpDeskManager","productTranslationManager.getSessionFactory","productManager.getProduct","companyManager.loadCompanies","serviceManager.getEnabledServices","productTranslationManager.setType","productManager.getSessionFactory","serviceManager.getAllProducts","productManager.setSessionFactory","companyManager.loadCompany","productManager.getAllProducts","productTranslationManager.getHibernateTemplate","productTranslationManager.getProductList","serviceTranslationManager.translateLocal","serviceTranslationManager.setSessionFactory","productManager.setHibernateTemplate","productTranslationManager.setSessionFactory","productTranslationManager.setHibernateTemplate","productTranslationManager.removeTranslation","serviceManager.isEnabled","serviceTranslationManager.getSessionFactory","serviceTranslationManager.removeTranslation","serviceTranslationManager.translateAll","productTranslationManager.setTranslation","productTranslationManager.setProductManager","productTranslationManager.getNonUniqueCriteriumNames","serviceManager.getEnabledProducts","productTranslationManager.getNonTranslatedCriterium"]}

As far as I can see, the json-rpc-client Java client doesn't use this
"self describing" functionality of the JSON-RPC server. Ideally, it
would be good to use this information to help construct the Java
proxy objects so that we don't need to supply the interface class
files to the client.

The reason that I don't want the client to need the class files for
the interfaces to the server implementation objects is that this means
my "universal client" isn't so universal any more. I do have the
ability to dynamically load class or JAR files from the server (within
my client) although I don't really want developers to need to worry
about generating complex ANT build files which separate out only the
class files which may be required by the client. Ideally it should be
as simple as registering any POJO on the server and then referencing
it on a client.

Regards,
Dominic.

On Dec 11, 10:46 pm, sasha...@gmail.com wrote:
> Hi Dominic --
>
> I also like JSON-RPC for looser coupling between client and server.
> Still, in order to do RPC you need to expose at least some information
> about the object you are talking to.
>
> So if you know the server class' methods and their parameters, this is
> already an interface description. Now using this information it could be
> possible to generate Java interface file, something along the lines of
> WSDL->proxy class compilers in SOAP implementaitons. Is this something
> that may help?
>
> I for one like the fact I can use Java interface as "protocol
> definition". BTW, client and server definitions does not have to be 100%
> in sync. In many cases, older clients may be able to talk to newer
> servers and vise versa.
>
> Also, could you give more information about your use case?
>
> Thanks,
> -- Sasha
>
> Dominic wrote:
> > Hi Sasha,
>
> > many thanks for this library. I had a look at the code and had one
> > slight issue
> > which is no doubt related to my specific requirements. One of the
> > things which attracted me to JSON-RPC (as against another remoteing
> > protocol such as Hessianhttp://www.caucho.com/resin-3.0/protocols/hessian-messaging.xtp)

Arthur Blake

unread,
Dec 14, 2007, 11:01:57 AM12/14/07
to json-rp...@googlegroups.com
Looks like an interesting project!

Have you seen http://j2s.sourceforge.net/ ?

There might be a little bit of cross-over...

sash...@gmail.com

unread,
Dec 14, 2007, 8:43:54 PM12/14/07
to json-rp...@googlegroups.com
Dominic --

Thanks for the explanation. I think what you need here is a "native" client that is optimized to be called from JavaScript via the "native" Rhino API. Something like
Rhino "native" client / JavaScript client = Java "native" method / Java method
Your project looks interesting; if you can give me a working example of  what you are trying to achieve using the (non-efficient) JavaScript implementation of proxy I can take a stab at making more efficient native implementation in Java. Should be pretty straightforward.

Let me know if this could work for you,
-- Sasha

Dominic wrote:
Hi Sasha,

thanks for the reply. My use case might be a little bit unique,
although I feel that removing the necessity to have the interface
class files available on the client may help in other situations as
well.

I'm in the process of developing a kind of universal client which
allows for the display of rich user interfaces (http://www.uidl.net).
This client includes a Rhino JavaScript interpreter and downloads
scripts containing the UI code from a server (as per HTML for a
browser but for complex UIs).

I would like to use JSON-RPC to transparently call server side objects
from thir JavaScript proxies on the client. I can do this if I use the
JavaScript JSON-RPC client from within Rhino, although this isn't
efficient. I'd prefer to be able to use a native Java JSON-RPC client
to retreive the Java proxies and then just get Rhino to expose them as
JavaScript equivalents.

As you suggest, we have the interface information available. In fact,
this is how the standard (JavaScript) client constructs proxies. It
issues a request when it loads of the type:

{"id": 1, "params": [], "method": "system.listMethods"}

... and the server responds with a response like:

{"id":1,"result":
["serviceTranslationManager.translateAllLocal","productManager.isEnabled","serviceManager.getAllServices","serviceTranslationManager.getNonTranslatedCriterium","productManager.getHibernateTemplate","serviceTranslationManager.translate","serviceManager.getSessionFactory","serviceManager.getHibernateTemplate","productManager.afterPropertiesSet","productManager.setHelpDeskManager","serviceManager.setEnabled","productTranslationManager.translateLocal","productManager.getEnabledProducts","productTranslationManager.translate","serviceTranslationManager.afterPropertiesSet","serviceManager.update","serviceTranslationManager.setTranslation","serviceManager.setHibernateTemplate","companyManager.getCompanyName","serviceManager.setSessionFactory","productTranslationManager.translateAll","serviceManager.setHelpDeskManager","serviceTranslationManager.setHibernateTemplate","productTranslationManager.translateAllLocal","serviceManager.getService","serviceTranslationManager.getHibernateTempl
ate","serviceTranslationManager.setType","productManager.setEnabled","serviceTranslationManager.setProductManager","productManager.update","serviceManager.afterPropertiesSet","serviceTranslationManager.getProductList","productTranslationManager.afterPropertiesSet","serviceTranslationManager.getNonUniqueCriteriumNames","serviceManager.getProduct","companyManager.setHelpDeskManager","productTranslationManager.getSessionFactory","productManager.getProduct","companyManager.loadCompanies","serviceManager.getEnabledServices","productTranslationManager.setType","productManager.getSessionFactory","serviceManager.getAllProducts","productManager.setSessionFactory","companyManager.loadCompany","productManager.getAllProducts","productTranslationManager.getHibernateTemplate","productTranslationManager.getProductList","serviceTranslationManager.translateLocal","serviceTranslationManager.setSessionFactory","productManager.setHibernateTemplate","productTranslationManager.setSessionFactory","
productTranslationManager.setHibernateTemplate","productTranslationManager.removeTranslation","serviceManager.isEnabled","serviceTranslationManager.getSessionFactory","serviceTranslationManager.removeTranslation","serviceTranslationManager.translateAll","productTranslationManager.setTranslation","productTranslationManager.setProductManager","productTranslationManager.getNonUniqueCriteriumNames","serviceManager.getEnabledProducts","productTranslationManager.getNonTranslatedCriterium"]}

As far as I can see, the json-rpc-client Java client doesn't use this
"self describing" functionality of the JSON-RPC server. Ideally, it
would be good to use this information to  help construct the Java
proxy objects so that we don't need to supply the interface class
files to the client.

The reason that I don't want the client to need the class files for
the interfaces to the server implementation objects is that this means
my "universal client" isn't so universal any more. I do have the
ability to dynamically load class or JAR files from the server (within
my client) although I don't really want developers to need to worry
about generating complex ANT build files which separate out only the
class files which may be required by the client. Ideally it should be
as simple as registering any POJO on the server and then referencing
it on a client.

Regards,
Dominic.

On Dec 11, 10:46 pm, sasha...@gmail.com wrote:
  

Dominic

unread,
Jan 2, 2008, 8:04:19 PM1/2/08
to json-rpc-client
Hi Sasha,

if you download the UIDL code (http://code.google.com/p/uidl/downloads/
list) and have a look at the
JsonRpcClientExample.uidl example, you will see that I need to load a
JAR file (remoteClasses.jar)
which contains my remote interfaces for the services exposed by the
server plus any objects
which are transmitted between the client and the server.

The JavaScript client (see the JsonRpcJsExample.uidl example) has no
such requirement as the
proxy objects are constructed with descriptors provided on
initialization by the server.

If you don't want to get the whole distribution running locally, I
have the server side code hosted
at http://java.uidl.net/uidl/JSON-RPC.

See the WebStart browser at http://java.uidl.net/uidl/browser/uidl.jnlp.

Regards,
Dominic.

On Dec 15 2007, 12:43 pm, sasha...@gmail.com wrote:
> Dominic --
> Thanks for the explanation. I think what you need here is a "native" client that is optimized to be called from JavaScript via the "native" Rhino API. Something likeRhino "native" client/ JavaScript client = Java "native" method / Java methodYour project looks interesting; if you can give me a working example of what you are trying to achieve using the (non-efficient) JavaScript implementation of proxy I can take a stab at making more efficient native implementation in Java. Should be pretty straightforward.

Sasha Ovsankin

unread,
Jan 7, 2008, 4:10:14 AM1/7/08
to json-rp...@googlegroups.com
Hi Dominic --

Interesting project, indeed. I had a look and I think I understand the problem much better now.

I think what can be done here is a special "Rhino-native" client that, given an JSON-RPC object handle:
  • Using JSON-RPC introspection, creates a series of FunctionObjects for every method;
  • Builds "class ClientProxy extends ScriptableObject  {}" and sets the above FunctionObjects as properties of this object,
  • Returns this object to JavaScript
It seems that this project cannot be reused in Java because in Java you need static typing anyway, but maybe in JRuby or Jython.

Does it make sense? Do you see more straightforward way?

-- Sasha

Dominic

unread,
Jan 9, 2008, 4:46:37 AM1/9/08
to json-rpc-client
Hi Sasha,

many thanks for the reply. Yes, what you are describing is exactly
what I had in mind.
I was lazy and nearly got this working by simply making a modified
version of the
standard JavaScript JSON-RPC client and interpreting it with Rhino
onto the current context.
Unfortunately, this had some issues with object type conversion and is
very slow. Your
proposal to construct the ScriptableObjects directly is much better.

The only other thought that I had is that it is a pity that we can
only do it this way (i.e. building
Rhino objects). I mean, this is perfect for me and my project but not
so good for someone
wishing to implement a pure Java client who doesn't want to worry
about keeping the
client side class files and interfaces up to date. Surely it would be
possible in Java as well
to construct an object dynamically based on the metadata we can
retrieve from the
JSON-RPC server?

Anyway, again, I don't really require this for my project and I'm just
being pedantic. As for the
dynamic construction of Rhino ScriptableObjects, is this something
that you would be willing
to help with?

Regards,
Dominic.

On Jan 7, 8:10 pm, Sasha Ovsankin <sa...@codebistro.com> wrote:
> Hi Dominic --
> Interesting project, indeed. I had a look and I think I understand the problem much better now.
> I think what can be done here is a special "Rhino-native" client that, given an JSON-RPC object handle:Using JSON-RPC introspection, creates a series of FunctionObjects for every method;Builds "class ClientProxy extends ScriptableObject {}" and sets the above FunctionObjects as properties of this object,Returns this object to JavaScriptIt seems that this project cannot be reused in Java because in Java you need static typing anyway, but maybe in JRuby or Jython.
> Does it make sense? Do you see more straightforward way?
> -- Sasha
> Dominic wrote:Hi Sasha, if you download the UIDL code (http://code.google.com/p/uidl/downloads/list) and have a look at the JsonRpcClientExample.uidl example, you will see that I need to load a JAR file (remoteClasses.jar) which contains my remote interfaces for the services exposed by the server plus any objects which are transmitted between the client and the server. The JavaScript client (see the JsonRpcJsExample.uidl example) has no such requirement as the proxy objects are constructed with descriptors provided on initialization by the server. If you don't want to get the whole distribution running locally, I have the server side code hosted athttp://java.uidl.net/uidl/JSON-RPC. See the WebStart browser athttp://java.uidl.net/uidl/browser/uidl.jnlp. Regards, Dominic. On Dec 15 2007, 12:43 pm,sasha...@gmail.comwrote:Dominic -- Thanks for the explanation. I think what you need here is a "native" client that is optimized to be called from JavaScript via the "native" Rhino API. Something likeRhino "native" client/ JavaScript client = Java "native" method / Java methodYour project looks interesting; if you can give me a working example of what you are trying to achieve using the (non-efficient) JavaScript implementation of proxy I can take a stab at making more efficient native implementation in Java. Should be pretty straightforward. Let me know if this could work for you, -- Sasha

Sasha Ovsankin

unread,
Jan 10, 2008, 1:57:07 AM1/10/08
to jabsorb-user, json-rp...@googlegroups.com
Hi Dominic --

Surely it would be possible in Java as well to construct an object dynamically based on the metadata we can retrieve from the JSON-RPC server?
Well technically yes, but practically it won't be Java programming anymore:
RemoteObject myObject= client.openProxy("myObject");
Result1 result1= (Result1)myObject.call("method1", param1, param2);
myObject.call("method2");
I think the future optimized Rhino client can be retrofitted for this kind of work.

If really needed, I would go the more traditional way: generate Java class query from interface description, very much like WSDL2Java in SOAP.
Anyway, again, I don't really require this for my project and I'm just
being pedantic. As for the
dynamic construction of Rhino ScriptableObjects, is this something
that you would be willing
to help with?
I can look into that when I have couple of hours. Where should I start?

Thanks,
-- Sasha

P.S. since the client is being integrated, moving this discussion into the jabsorb list, too.

Dominic

unread,
Jan 13, 2008, 7:40:37 PM1/13/08
to json-rpc-client
Hi Sasha,

> Anyway, again, I don't really require this for my project and I'm just being pedantic. As for the dynamic construction of Rhino ScriptableObjects, is this something that you would be willing to help with?I can look into that when I have couple of hours. Where should I start?

If you download the latest UIDL release (http://code.google.com/p/uidl/
downloads/list) you should be able to get up and running pretty
quickly. Just unzip it and run "webserver.bat". Then navingate to
http://localhost:8080/uidl/ and run either the applet or WebStart
versions of the UIDL browser. Have a look at the JsonRpcClientExample
example or the CarSales demo (after choosing JSON-RPC as the remoting
protocol).

In both cases, you will see that the JSON client is instantiated as
follows:

// Remote interfaces for exmaple application
browser.loadRemoteLibrary("../jar/remoteClasses.jar");

// Libraries for json-rpc-client
browser.loadRemoteLibrary("../jar/jabsorb.jar");
browser.loadRemoteLibrary("../jar/slf4j-api.jar");
browser.loadRemoteLibrary("../jar/slf4j-jdk14.jar");

var hostRoot = "http://" + hostName + ":" + hostPort + "/uidl/";

JsonRpc = Packages.org.jabsorb.client;
var session = JsonRpc.TransportRegistry.i().createSession(hostRoot +
"JSON-RPC");
client = new JsonRpc.Client(session);

Then you can simply instantiate a proxy opbect as follows:

var userManager = client.openProxy("userManager",
Uidl.example.UserManager);

The idea would be to use introspection data from the server during the
client creation and cache the proxxy objects. I this way, after the
execution of:

client = new JsonRpc.Client(session);

... we would already know which services were exposed by the server
(along with method calls and parameters). This would allow us to
simplify the creation of a proxy to:

var userManager = client.openProxy("userManager");

i.e. we wouldn't need to supply any Java interface. In this way, we
completely decouple the server side development from the client which
would cereate a more dynamic and flexible binding. It would also mean
that the server could be implemented in languages other than Java.

Regards,
Dominic.


Reply all
Reply to author
Forward
0 new messages