Null reference problem while executing Java method from Javascript (jabsorb)

54 views
Skip to first unread message

cevi...@gmail.com

unread,
May 21, 2008, 3:56:15 PM5/21/08
to jabsorb-user
Hi,

I have just decided to use jabsorb in my web application and it seems
to be a powerful tool. However, I have problems in being able to pass
an object as a parameter to Java method, in my client sided Javascript
codes.

Here is the simplest codes I am using to achieve the goal.


package test.entities;

import java.io.Serializable;

public class Bar implements Serializable{


/**
*
*/
private static final long serialVersionUID = 1L;
private String baz;

public String getBaz() {
return baz;
}

public void setBaz(String baz) {
this.baz = baz;
}

public String toString()
{
return "baz : " + baz;
}

}



package test.entities;

import java.io.Serializable;

public class Foo implements Serializable{

/**
*
*/
private static final long serialVersionUID = 1L;
private Bar bar;

public Foo()
{

}

public Bar getBar() {
return bar;
}

public void setBar(Bar bar) {
System.out.println("setter : " + bar);
this.bar = bar;
}
}




My web.xml file :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://
java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://
java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>jsontest</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>JSONRPCServlet</servlet-name>
<servlet-class>org.jabsorb.JSONRPCServlet</servlet-class>
<!--
the gzip_threshold indicates the response size at which the
servlet will attempt to gzip the response
if it can.
Set this to -1 if you want to disable gzip compression for some
reason,
or if you have another filter or other mechanism to handle
gzipping for you.
Set this to 0 to attempt to gzip all responses from this
servlet.
otherwise, set it to the minimum response size at which gzip
compression is attempted.
note: if the browser making the request does not accept gzip
compressed content,
or the result of gzipping would cause the response size to be
larger (this could happen
with very small responses) then the content will be returned
without gzipping regardless
of this setting, so it is very reasonable idea to set this to 0
for maximum bandwidth
savings, at the (very minor) expense of having the server
attempt to gzip all responses.
-->
<init-param>
<param-name>gzip_threshold</param-name>
<param-value>200</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>JSONRPCServlet</servlet-name>
<url-pattern>/JSON-RPC</url-pattern>
</servlet-mapping>



</web-app>



test.jsp file :



<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@page import="test.entities.Foo"%>
<%@page import="test.entities.Bar"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://
www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1">
<title>Insert title here</title>

<script language="JavaScript" src="jsonrpc.js"> </script>
</head>
<jsp:useBean id="JSONRPCBridge" scope="session"
class="org.jabsorb.JSONRPCBridge" />
<%
test.entities.Foo f = new test.entities.Foo();



Bar b = new Bar();
b.setBaz("hede");

JSONRPCBridge.registerObject("fooObj", f);
JSONRPCBridge.registerObject("barObj", b);
%>

<body>


<script language="JavaScript">

var cb = function(result, ex) {
if(ex) throw ex;

// The row and username variables are visible
// here later when this callback function is called

};


var jsonrpc = new JSONRpcClient("/jsontest/JSON-RPC")
var bar=jsonrpc.barObj;

jsonrpc.fooObj.setBar(cb,bar);


</script>

</body>
</html>



jabsorb and slf4j libraries are included in my classpath and web-inf/
lib.

I am using Eclipse as IDE and Tomcat 6.0 as web server in Windows OS.

The problem is, when test.jsp is loaded, the output in console is

setter : baz : null

I have been trying to solve this problem for 2 hours and I would
appreciate any help.

Thanks in advance.

Ali Çevik
cevi...@gmail.com

Michael Clark

unread,
May 21, 2008, 8:27:44 PM5/21/08
to jabsor...@googlegroups.com
cevi...@gmail.com wrote:
>
> <script language="JavaScript">
>
> var cb = function(result, ex) {
> if(ex) throw ex;
>
> // The row and username variables are visible
> // here later when this callback function is called
>
> };
>
>
> var jsonrpc = new JSONRpcClient("/jsontest/JSON-RPC")
> var bar=jsonrpc.barObj;
>
> jsonrpc.fooObj.setBar(cb,bar);
>
>
> </script>
>

You are trying to use the client-side proxy object as an argument to a
call. This I am not sure is currently supported.

There is potential that this sort of thing to be implemented - I think
there was some discussion some time back about using the callable
proxies interchangeably as opaque references although I'm not sure if
support for it is complete. William?

What is probably happening is the BeanSerializer is treating the
serialized client proxy as any other object for which the server then
tries to map the fields to the Bar class (but it will only have the
fields of the client-side proxy object that was sent which has no 'baz'
field - thus it not being set).


William Becker

unread,
May 22, 2008, 5:37:19 AM5/22/08
to jabsor...@googlegroups.com
You are trying to use the client-side proxy object as an argument to a
call. This I am not sure is currently supported.

I haven't tried this, but if it was declared as a callable reference, I'm not sure why it wouldn't work. With 1.3RC1 we have got constructors working, so you have two options, one of which I am sure will work!

First option, just register Bar as a callable reference:
JSONRPCBridge.registerCallableReference(test.entities.Bar.class)

This could fix the whole thing up, but I haven't used a callable reference as an object on the bridge before, so I'm not sure it will work.

Another way is to construct it and use it purely in the javascript. To do this you need to declare it as a constructor by registering it both as a CallableReference and registering its class in jsp:
JSONRPCBridge.registerCallableReference(test.entities.Bar.class)
JSONRPCBridge.registerClass("Bar",test.entities.Bar.class);

Then you can create "Bar" in javascript:
var bar = jsonrpc.createObject("Bar",[]);
bar.setBaz("hede");
jsonrpc.fooObj.setBar(cb,bar);

Hope this works,
Will

Ali Çevik

unread,
May 22, 2008, 5:36:11 PM5/22/08
to jabsor...@googlegroups.com
Hi,

First option seem doesn't seem to work, as it gives exception message:

uncaught exception: JSONRpcClientException: arg 1 could not unmarshall

Second one also gives an exception message which is probably due to a version issue (I am using jabsorb 1.2.2)
jsonrpc.createObject is not a function


However, even if I could use the second option, it wouldn't precisely solve my problem. My intention is to get an object from Java side, modifying it from jsonrpc and sending it to Java again. In second option, I need to specify the details of the object in client side. I guess I can relate it with Java part somehow, but it would be messy.

Thus, if someone could come up with a feature like I mentioned, it would be nice !

PS: I have spent hours for this and it is disappointing being not able to do it. In the documentation, as far as I have read, I haven't been able to recognize any parts regarding to this issue, which is in my opinion quite fundamental. In the documentation, it is explicitly written that we are able to execute java methods with string a parameter. As a newbie,  I tend to understand that a java method can be executed by any parameter type. If you could add a part regarding to this, it would save a lot of time.

PS2: Umm, this one is another issue I guess, but I would like to know if we are able to execute a method with more than one string parameters just like that;

jsonrpc.fooObj.foo("test","test2")

Are we able to execute a method with more than one parameters ? In the documentation as far as I read, I doubt there is a sample about multiple parameters.


best regards,
Ali Cevik

Arthur Blake

unread,
May 22, 2008, 9:02:37 PM5/22/08
to jabsor...@googlegroups.com
Hi, Ali.  I'm sorry that you are having trouble with jabsorb.

On Thu, May 22, 2008 at 5:36 PM, Ali Çevik <cevi...@gmail.com> wrote:
Hi,

First option seem doesn't seem to work, as it gives exception message:

uncaught exception: JSONRpcClientException: arg 1 could not unmarshall

Second one also gives an exception message which is probably due to a version issue (I am using jabsorb 1.2.2)
jsonrpc.createObject is not a function


However, even if I could use the second option, it wouldn't precisely solve my problem. My intention is to get an object from Java side, modifying it from jsonrpc and sending it to Java again. In second option, I need to specify the details of the object in client side. I guess I can relate it with Java part somehow, but it would be messy.

This is quite possible.  I do it all the time.  What you need to do is call registerObject on the "entry points" into your API, and then call them to bring down the objects you want to use on the JavaScript side.  An object that you pull down to JavaScript can then be sent back to Java on the server, but the object coming back will be a copy, not the original object (you have to use references to get back to the original object on the Java side -- I personally never use references, and instead just pass around light weight data transformation objects-- it's simpler and easier to understand that way, IMHO)

In other words, registering an object doesn't make the object itself serialize down to the JavaScript side, it only makes the public methods of that object into entry points that you can then call from JavaScript.  Then you can call those methods (kind of like a factory pattern) to get the objects you are interested in down to JavaScript from Java.

When you call those methods, your objects that get sent as parameters are transformed to Java and the object coming back from Java as the return value is  transformed into JavaScript.  An object received from Java can be sent back to Java and it will serialize back into the proper type of Object on the server side.

Jabsorb can handle all the basic types as well as Java bean classes and aggregates of them quite well.  But some complex types may not serialize properly (you can write a custom serializer for this-- in practice I've never had to do this) and In general you want to be careful about what kinds of objects you pass around anyway as passing very large objects will be inefficient.



Thus, if someone could come up with a feature like I mentioned, it would be nice !

PS: I have spent hours for this and it is disappointing being not able to do it. In the documentation, as far as I have read, I haven't been able to recognize any parts regarding to this issue, which is in my opinion quite fundamental. In the documentation, it is explicitly written that we are able to execute java methods with string a parameter. As a newbie,  I tend to understand that a java method can be executed by any parameter type. If you could add a part regarding to this, it would save a lot of time.

This is correct, you can pass any parameter type to a method from JavaScript.  I'm not sure why you are having a problem with this.  It is quite clearly described in the manual in section 3 (http://jabsorb.org/Manual)
 


PS2: Umm, this one is another issue I guess, but I would like to know if we are able to execute a method with more than one string parameters just like that;

jsonrpc.fooObj.foo("test","test2")

Are we able to execute a method with more than one parameters ? In the documentation as far as I read, I doubt there is a sample about multiple parameters.

Yes, of course you can call  a method with multiple arguments-- and even overloaded methods, and your example is exactly how you would call it (assuming that the fooObj.foo method takes two Strings as it's arguments.)  The unit tests page has at least one example of a call with multiple arguments http://jabsorb.org/jabsorb-1.2/unit.jsp

Good luck.

Ali Çevik

unread,
May 23, 2008, 6:21:29 AM5/23/08
to jabsor...@googlegroups.com
Hi Arthur,

Thanks for your reply. It is great if we are able to do such kind of things. But, what I couldn't understand is, why I can't do those ?

Could you perhaps take my example (which is quite fundamental, consisting two classes Foo and Bar) and make it run and post it here so that I and other programmers having the same problem will be able to benefit from it ? If you could do that, it would really be nice.

Thanks,
Ali.
Reply all
Reply to author
Forward
0 new messages