google-code-export / gwtphp-derpc

Automatically exported from code.google.com/p/gwtphp-derpc
1 stars 0 forks source link

@return ArrayList<POJO> gives 'Call to a member function getValue() on a non-object' for Integer attribute #5

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. define a services which returns an Arraylist<POJO>

What do you see instead?
PHP Fatal error:  Call to a member function getValue() on a non-object in 
.../war/<prj>/phprpc/serializers.php on line 94

What version of the product are you using?
r6

Workaround?
Replace private Integer id; in POJO with private String id;

Please provide any additional information below:

/**
* @param ArrayList<YourDataObject> $objects
* @return ArrayList<YourDataObject>
*/
public function sendData( $objects ) 
{
    // Correctly received
    ini_set('error_log','/tmp/error.log');
    error_log( var_export( $objects, true ) );

    // Error when a list is returned
    list = new ArrayList();             
    $obj1 = new YourDataObject();
    $obj1->id = 1;
    $obj1->name = "johan";
    $obj1->location = "almere";
    $list->add( $obj1 );
    error_log( var_export( $list, true ) );

    return $list;
}

------

public class YourDataObject implements IsSerializable 
{
    private Integer id;
    private String name;
    private String location;
}

Original issue reported on code.google.com by lightwor...@gmail.com on 3 Jun 2011 at 12:39

GoogleCodeExporter commented 9 years ago
I think the problem is at the line :
$obj1->id = 1;
You have declared an Integer variable in your java code.
So in php, it will be an Integer too. But the php does not perform int/Integer 
transformation.
You must create an Integer object by your own in PHP code :
$obj1->id = new Integer(1);

Another solution is to declare the id variable with an int type. But maybe you 
have your reasons not to do that.

I will think to add the int/Integer transformation for future version.

Original comment by mathieu....@gmail.com on 3 Jun 2011 at 1:43

GoogleCodeExporter commented 9 years ago
Ah, that makes sense! Thanks. I was just testing, so I don't need int or 
Integer yet :-)

How about String? In the above example I do $obj1->name = "johan", which seems 
to be converted to String?

note: did you see my posts at the forum group?

Original comment by lightwor...@gmail.com on 3 Jun 2011 at 7:58

GoogleCodeExporter commented 9 years ago
For String, it is different. Java has two types for all primitives (int, byte, 
short, double, float, boolean...), the primitive one and the object one 
(Integer, Byte, Short, Double, Float, Boolean). The String is not a primitive 
type, so in php I always transform it into a php string. 

For Primitives, i transformed them into the corresponding php type (bool, int, 
double) and for their object form, i have created PHP Object (Integer, Byte, 
Short, Double, Float, Boolean) to keep the logic.
Primtive/object conversion is not automatic in php like in Java 1.5. If you 
declare object form, in php you must create an object. If you declare primitive 
form, you can use php value.

For your example :
(JAVA)
public class YourDataObject implements IsSerializable 
{
    private int id;
    private String name;
    private String location;
}

(PHP)
[...]
$obj1 = new YourDataObject();
$obj1->id = 1;
[...]

PS: I saw your posts, i m thinking about the answers ;)

Original comment by mathieu....@gmail.com on 4 Jun 2011 at 10:59

GoogleCodeExporter commented 9 years ago
Ah, thanks for explaining. I did see you implemented in PHP the object form of 
the Java primitives and a lot of Collection related objects as well. Great job! 
That must have been quite some work.

I don't have a proper overview of the pros and cons of doing automatic 
conversion. But, if it does not break to much, I vote for it :-) Since PHP is 
typeless and does automatic (internal) type conversions, I would like to see 
that for the GWT-RPC part as well. This way, at least on the PHP/backend side 
for the RPC layer, I don't have to worry about types.

note: is it correct for me to assume that PHP/you do a automatic type 
conversion for the non object form primitive types? For example: $obj->a = 
"10"; And in the RPC interface 'a' is defined as int. The "string" "10" is 
automatically converted to int 10.

Maybe, if you choose to do implement automatic conversion, make it configurable?

For now I will use the non object form of the primitive types, because this 
works the easiest on the PHP side. For example:

(JAVA)
class MyObject {
   private Integer id;
   private int ref_id;
   private String name;
}

$db = new PDO( $dbdef );
$sth = $db->query( $q );
$sth->setFetchMode( PDO::FETCH_CLASS, 'MyObject' );
foreach( $sth as $objMyObject )
...

This code will do a SQL query and maps the columns of each row to named 
properties in the class. This method works just fine for int and String, but 
not for Integer. Well the attribute id does get assigned with correct values 
but upon serialization it goes wrong of course.

Original comment by lightwor...@gmail.com on 16 Jun 2011 at 10:44

GoogleCodeExporter commented 9 years ago
If you want to use non object form of the primitive types, you must not use 
Integer, Byte, Double, Long, Boolean... But only int, byte, double, long, 
boolean...

I just saw that Integer in java part will be automatically converted to int 
type in php part. But the inverse is not converted. In fact, when php part 
sends a data to java part, there are two main cases :
  - the primitive type are sent with special signature
  - the object type are sent with class name.
It is the second case that make more difficult to use auto conversion between 
php int and java Integer. You see, when your java part waits a Integer object, 
it waits the class java.lang.Integer and not the int. 

The auto conversion (php->java) is certainly possible to implement. I will try 
to see how to do. But I will not implements that in a short time.

Original comment by mathieu....@gmail.com on 21 Jun 2011 at 8:35