On Jun 15, 2009, at 18:54 , Andreas Junghans wrote:

> Hi Jean-Baptiste,
>
> Am 15.06.2009 um 17:21 schrieb Jean-Baptiste BRIAUD -- Novlog:
>
>> Why do I have to filter java.lang.Class or java.lang.reflect.Method ?
>
> "class" is filtered out in the default implementation to avoid
> unnecessary traffic and/or reference cycles.
So, why do I have to filter it in my own filter was the real  
question :-) ?

> The root of the problem
> is that every Java object has a method "getClass" (which matches the
> JavaBean pattern). So without filtering, the RPC implementation would
> try to serialize the Class objects of all instances that are
> transmitted. And since java.lang.Class has lots of getXYZ() methods
> (some of them forming reference cycles IIRC), the JSON representation
> quickly explodes ...
I fully agree and because I had to filter it manually, I asked the  
question but now I guess I probably filter the wrong way !
Here is how I did it, could you, please, revue my code :

     protected RemoteCallUtils getRemoteCallUtils() {
         return new RemoteCallUtils() {

             protected Map filter(Object obj, Map map) {
                 final String className = obj.getClass().getName();
                 // System.out.println("----------- filter : " +  
className);
                 if ("java.lang.reflect.Method".equals(className) ||  
"java.lang.Class".equals(className) )) {
                     map.clear();
                     return map;
                 }
                 removeUnwantedProperties(map); // This method remove  
my "user land" unwanted property
                 return super.filter(obj, map);
             }

Should I do "my stuff" before or after the super.filter() ?


>
> You don't have to filter java.lang.reflect.Method, at least not when
> you're transmitting simple objects. However, if there's a getXYZ()
> method in one of your objects that returns a java.lang.reflect.Method
> (or array thereof), then it should be filtered. Just look at the Java
> API documentation of Method so see why: There's stuff like
> getReturnType() that returns a Class. And regarding Class objects, see
> above ...
Same thing : I fully agree but I had to filter it in my own filter ...

>
> Maybe I should provide some background info about the filtering
> mechanism. In general, when you try to convert Java objects to a
> String representation, there are two choices:
>
> 1.) Explicitly specify which properties get serialized. This requires
> some sort of meta data, e.g. the WSDL in case of web services. Or you
> can put up a requirement that every object needs to implement a
> specific serialization API (e.g. java.io.Serializable), which is also
> some kind of meta data.
>
> 2.) Serialize all properties by default. In this case, you have to
> provide a filter mechanism to avoid unnecessary traffic and reference
> cycles (see above).
>
> Both approaches have their pros and cons.
Same as before : I fully agree

> qooxdoo's Java RPC
> implementation uses the second one to ease development and deployment.
> If you transmit simple objects, it works quite well. However, if you
> take existing, complicated business objects, you may have to adjust
> the filter. You could argue that the default filter list could be more
> extensive, but this would be a never-ending story: Many JDK classes
> are not easily serializable to a String, so you could end up with
> thousands of filter entries that would be checked before each
> transmission.
>
> You could also argue that only objects implementing
> java.io.Serializable should be transmitted, but that would be very
> annoying IMHO. Lots of objects in many libraries and existing
> applications are not implementing Serializable, even when they can be
> converted to JSON without issues.
>
> We could debate the different approaches all night long :-)  If you
> don't agree with the one chosen in qooxdoos Java RPC implementation,
> take a look at the other Java RPC libraries out there. Maybe you can
> find one that suits your needs better (or mabye not - I don't know in
> detail how the different libs handle serialization).
>
> One last remark about the filtering: Even when your transmission works
> (no reference cycles), you should still take a look at the data
> stream. In many cases, you can reduce the size of the JSON string
> greatly by more aggressive filtering.

True. That's why I'm thinking about adding one feature :
Have both 1. and 2. approachs.
Use annotation to tag some POJO at class level, say @C
All the non @C classes will be kept with the current filtering behavior
For those who have the @C, and only that one, filter will keep only  
the taged property (at attribute or getter level), say @A.
Only @A in the classes who is @C will be kept.
Benefits :
* for that cases, the filtering do not have to be dynamic. No need to  
check at runtime and everytime if the property is to keep or reject. A  
cache could be done for that since annotation won't change.
* this would be a comprimise between 1 and 2 : have both, keep the  
current behavior if nothing is done but allow new behavior only if you  
want
* handle well the case of existing business object.

What about the case of a class tagged @C where you would like to keep  
the dynamic filtering ability ? Use @D.
Any property (at getter level or attribute level) that would have @D  
(only for a @C class) will go to the filter and the answer to keep or  
reject could be done based on rules or any code in the user land (aka  
a subclass of the servlet like now)

In summary, 3 anotations, no changes to existing code base, no change  
to existing behavior but a way tp have a static approach (with the  
hope or more speed) when needed.

Example :

@C
public class Person {

        @A
        String name

        String complicatedThingsOnlyForTheServer

        @D
        String ClientPromoCode
}

Because Person is @C, the "new" behavior is applied :
* complicatedThingsOnlyForTheServer will never be JSONified, this  
become structural.
* name will always be JSONified, this become structural.
* ClientPromoCode may or may not be JSONified, depending on filter  
code in the RPC subclass.

We may improve one thing to let the developper be as less as possible  
verbose :
@A specify the property to kept, we could imagine to have the  
opposite : @R to reject a property.
So, @C(defineR) will let you define the @R and the others are kept by  
default
@C(defineA) will let you define the @A and the others are rejected by  
default
@C is equal to @C(defineA)

=> depending on classes, one can only have to write the less !



> If you have existing business
> objects that you'd like to transmit, there are probably tons of things
> that are of no interest to the client.
>
absolutly !


> Regards,
>
>   Andreas J.
>
>
> ------------------------------------------------------------------------------
> Crystal Reports - New Free Runtime and 30 Day Trial
> Check out the new simplified licensing option that enables unlimited
> royalty-free distribution of the report engine for externally facing
> server and web deployment.
> http://p.sf.net/sfu/businessobjects
> _______________________________________________
> qooxdoo-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
>


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
qooxdoo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel

Reply via email to