class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping schemes

View: New views
9 Messages — Rating Filter:   Alert me  

class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping schemes

by Mike Wilson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ok, first I'll address your comments:
 
> Use-cases for lighter class mapping?
The request I'm mainly thinking about was from a long time ago on the list. I haven't saved a link to it, but the main theme of that request (AFAICR) was that:
1) They didn't need the extra benefits provided by the JavaScript classes. They just wanted to be able to detect types on objects.
2) The types needing class mapping were not known before run-time (hm, possibly because of some internal abstraction/plug-in framework?) so they were not able to mark the desired classes for mapping in dwr.xml before being deployed and started.
3) Thus they needed class mapping that was "always on" and their only solution would be to enable class mapping for all converted classes, but that would potentially mean mapping a lot of classes with the associated overhead of our generated JavaScript class code.
Continuing to Randy's case I think it can be summarized as:
4) Make it possible to use class-mapping for client-side objects that are not created by our generated constructors (because not having control over object creation etc).
 
> Not good to expose Java class names
Variant 1 does not expose Java class names.
 
> Extending signatures to solve this?
I understand Joe's suggestion as telling the signatures system to use a certain concrete class for all calls to a certain method accepting non-concrete arguments.
I'm not sure it's worth the effort to add this behaviour to the signatures handling as it doesn't solve handling of multiple subclasses or client-side type decisions. And the static setup possible with signatures may alternatively and easily be done by wrapping the abstract-argument method with a concrete ditto on the server.
 
> Tweak getObjectClassName to fix Randy's case?
Well, if this becomes an official and documented solution then we are in fact implementing half (the client-side stuff) of my "Plug-in API for class mapping" suggestion below ;-).
 
And here's some new material for discussion:
 
How can we let the client code know the type of outbound objects?
In DWR 2.0 and current 3.0 there are two very different systems in effect: (1) outbound exceptions have a property naming their Java class name and, (2) mapped classes are associated with a JavaScript class (named from the mapping name in dwr.xml) by being instantiated with a generated constructor.
My suggestion is to make it possible to attach type info much like is already done for exceptions, but for all other object types. This is by itself not a big thing, and we can choose to only attach the mapping name (and not the Java name) if that feels better security-wise.
 
How can the client code let the server know the desired type of inbound objects?
Currently this is done by looking up the JavaScript class that the object belongs to.
Though, I'm sensing that we are agreeing that manually setting $dwrclassname could be allowed to override our default type-detection?
 
Updated suggestion
If the above is ok, and implementing a plug-in API for class mapping is not interesting at all but having a lighter class-mapping scheme is a little interesting, then we could do the following short-cut to make this really simple:
  • skip having any settings for class-mapping mode
  • move generated mapped classes to a separate file (/dwr/classes.js) [discussed in other thread]
  • the only other server-side change is to send class-mapped outbound objects like this in DWRP:
      s101=dwr.engine._createObject("Person");
    instead of like today:
      s101=new Person();
  • createObject() would look up if there is a constructor function named "Person" and
      if exists: return an object created using the constructor
      if not exists: return an Object with type as member: { "$dwrclassname": "Person" }
  • client-side type-detection should look for $dwrclassname overrides on objects sent to server
This solution would make it possible to choose between light and full class-mapping just by deciding whether to include the generated classes from /dwr/classes.js or not.
If the generated classes are not present then we would automatically fall back to light class-mapping using the $dwrclassname members instead.
I think this is a coherent and symmetrical solution and I quite like it.
 
Best regards
Mike
Add a simplified class-mapping scheme that doesn't use JavaScript classes
 
The current class mapping scheme was designed to be compatible with JavaScript classes to be able to benefit from native constructors, instanceof support and class inheritance. Though, in some cases it is sufficient to only inspect, or set, the actual class identity and not use any of the other features. Some properties of the current class mapping scheme may then stand in the way for an efficient implementation, f ex not being able to say that an existing type-less object should be parsed as a certain class on the server (Randy's case) without actually recreating the object and calling the appropriate constructor.
 
I have two variations on a suggestion that solves this, and they both depend on using the "$dwrclassname" or "$dwrserverclassname" properties introduced above, but on the actual instances.
 
Variant 1: activate "light" mapping style instead of the normal mapping style
 
This would imply a global setting in web.xml to tell DWR what class mapping scheme to use:
 
    <init-param>
        <param-name>lightClassMapping</param-name>
        <param-value>true</param-value>
    </init-param>
 
The class mapping behaviour would change in the following way:
  • No constructor functions nor any other JavaScript class-related code generated by the DWR servlet for mapped classes.
  • An outbound object of a mapped class will get its class identity annotated as a property instead of a constructor call, ie:
        s101={name:"Donald","$dwrclassname":"db.Person"}
    instead of:
        s101=new db.Person();s101.name="Donald";
  • Inbound objects will be inspected for a "$dwrclassname" property and if there is a matching mapped class, the corresponding Java class will be instantiated. Thus, if the browser code wants to specify the class of an untyped object, it just has to add the "$dwrclassname" property on the object.
Note a few things in the above suggestion:
  1. The "$dwrclassname" property is placed on the objects instead of on the class, as there is no class.
  2. The "$dwrclassname" property still specifies the mapped JavaScript class name, not the Java class name (ie db.Person and not mypkg.dto.Person from the previous examples).
  3. Only classes that have been set-up for conversion and also set-up for mapping through the "javascript" attribute are allowed to be created using the inbound "$dwrclassname" feature, to stop evil hackers that want to create dangerous objects on the server.
Variant 2: activate "light" mapping style in addition to the normal mapping style
 
This means keeping the normal mapping style on all mapped classes (with a "javascript" attribute), and using the light mapping style as a default on the remaining bean classes that are not mapped (without "javascript" attributes). This would work the same way as variant 1, but with a few differences:
  • No web.xml enabling configuration needed as this behaviour is always present.
  • Outbound data will be annotated with "$dwrserverclassname" and the Java class name, as there is no mapped JavaScript class name.
  • Inbound data will also have to use "$dwrserverclassname" instead, and specify the Java class name.
  • Security-wise we will only allow Java classes set-up for conversion to be created by inbound data, which is a little bit broader than variant 1. 
Joe said:
I think I'm struggling here from not really seeing the use-case.
I'm not keen on allowing the internet to know about, much less specify the java side classes, and we already have a solution?

I wonder if we couldn't expand on the signatures idea for times when the current system fails.

Real method:
public void foo(SomeInterface x) {...}

dwr.xml:
<signatures>
public void foo(SomeImplementation x) {...};
<signatures>

What do you think?
 
 
Randy said:
And of course I’m going to argue for this one, as it’s my use case. To remind everyone of my use case, as it has been awhile, I have an api that is built on top of dojo and is fairly extensive. I’d like to be able to just set the $dwrclassname on those objects instead of having to create a new object based on my javascript attribute set in dwr.xml and copy over the attributes every time I send an object.  Do I need to give a more detailed example here?
 
 
Joe said:
So couldn't we just tweak getObjectClassName to inspect $dwrclassname and return that, if set?  
Plug-in API for class-mapping
 
To modularize most of what has been suggested above, and to open up for other customizations of the class-mapping system, the following functions could be moved to a separate overridable class:
  • Code generation for bean/object classes (f ex used by the standard class-mapping scheme).
  • Type annotation of outbound data (f ex new db.Person() or $dwrclassname="db.Person")
  • Checking of inbound data (verifying classes are allowed to be created remotely)
There may also be need for a callback interface in engine.js, so custom code can detect the type of inbound data.
 
Here's an example of what it could look like if implementing the "light" class-mapping from above (according to variant 1) as a custom class-mapper:
 
web.xml:
    <init-param>
        <param-name>org.directwebremoting.extend.ClassMapper</param-name>
        <param-value>org.directwebremoting.impl.LightClassMapper</param-value>
    </init-param>
 
java/server:
    public class LightClassMapper {
        public generateDeclarationsForClass(...) { /*NOP*/ }
        public convertOutboundObject(...) { ... }
        public checkInboundObject(...) { ... }
    }
 
javascript/browser:
    <script src="dwr/engine.js"></script>
    <script src="lightclassmapper.js"></script>
        contains:
            dwr.engine.setClassMapper(function(data) {
                if (data["$dwrclassname"])
                    return data["$dwrclassname"];
                else
                    return null; // Use standard type detection
            });
 
The plug-in API would also open up for other kinds of user-defined customizations, f ex if someone wants to generate getters and setters on mapped bean classes.

Re: class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping schemes

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


OK.
Clearly this isn't a pain point that I feel, but if 2 regulars feel it, then others must too.
http://bugs.directwebremoting.org/bugs/browse/DWR-269

Joe.


On Fri, Jul 11, 2008 at 12:52 AM, Mike Wilson <mike@...> wrote:
Ok, first I'll address your comments:
 
> Use-cases for lighter class mapping?
The request I'm mainly thinking about was from a long time ago on the list. I haven't saved a link to it, but the main theme of that request (AFAICR) was that:
1) They didn't need the extra benefits provided by the JavaScript classes. They just wanted to be able to detect types on objects.
2) The types needing class mapping were not known before run-time (hm, possibly because of some internal abstraction/plug-in framework?) so they were not able to mark the desired classes for mapping in dwr.xml before being deployed and started.
3) Thus they needed class mapping that was "always on" and their only solution would be to enable class mapping for all converted classes, but that would potentially mean mapping a lot of classes with the associated overhead of our generated JavaScript class code.
Continuing to Randy's case I think it can be summarized as:
4) Make it possible to use class-mapping for client-side objects that are not created by our generated constructors (because not having control over object creation etc).
 
> Not good to expose Java class names
Variant 1 does not expose Java class names.
 
> Extending signatures to solve this?
I understand Joe's suggestion as telling the signatures system to use a certain concrete class for all calls to a certain method accepting non-concrete arguments.
I'm not sure it's worth the effort to add this behaviour to the signatures handling as it doesn't solve handling of multiple subclasses or client-side type decisions. And the static setup possible with signatures may alternatively and easily be done by wrapping the abstract-argument method with a concrete ditto on the server.
 
> Tweak getObjectClassName to fix Randy's case?
Well, if this becomes an official and documented solution then we are in fact implementing half (the client-side stuff) of my "Plug-in API for class mapping" suggestion below ;-).
 
And here's some new material for discussion:
 
How can we let the client code know the type of outbound objects?
In DWR 2.0 and current 3.0 there are two very different systems in effect: (1) outbound exceptions have a property naming their Java class name and, (2) mapped classes are associated with a JavaScript class (named from the mapping name in dwr.xml) by being instantiated with a generated constructor.
My suggestion is to make it possible to attach type info much like is already done for exceptions, but for all other object types. This is by itself not a big thing, and we can choose to only attach the mapping name (and not the Java name) if that feels better security-wise.
 
How can the client code let the server know the desired type of inbound objects?
Currently this is done by looking up the JavaScript class that the object belongs to.
Though, I'm sensing that we are agreeing that manually setting $dwrclassname could be allowed to override our default type-detection?
 
Updated suggestion
If the above is ok, and implementing a plug-in API for class mapping is not interesting at all but having a lighter class-mapping scheme is a little interesting, then we could do the following short-cut to make this really simple:
  • skip having any settings for class-mapping mode
  • move generated mapped classes to a separate file (/dwr/classes.js) [discussed in other thread]
  • the only other server-side change is to send class-mapped outbound objects like this in DWRP:
      s101=dwr.engine._createObject("Person");
    instead of like today:
      s101=new Person();
  • createObject() would look up if there is a constructor function named "Person" and
      if exists: return an object created using the constructor
      if not exists: return an Object with type as member: { "$dwrclassname": "Person" }
  • client-side type-detection should look for $dwrclassname overrides on objects sent to server
This solution would make it possible to choose between light and full class-mapping just by deciding whether to include the generated classes from /dwr/classes.js or not.
If the generated classes are not present then we would automatically fall back to light class-mapping using the $dwrclassname members instead.
I think this is a coherent and symmetrical solution and I quite like it.
 
Best regards
Mike
Add a simplified class-mapping scheme that doesn't use JavaScript classes
 
The current class mapping scheme was designed to be compatible with JavaScript classes to be able to benefit from native constructors, instanceof support and class inheritance. Though, in some cases it is sufficient to only inspect, or set, the actual class identity and not use any of the other features. Some properties of the current class mapping scheme may then stand in the way for an efficient implementation, f ex not being able to say that an existing type-less object should be parsed as a certain class on the server (Randy's case) without actually recreating the object and calling the appropriate constructor.
 
I have two variations on a suggestion that solves this, and they both depend on using the "$dwrclassname" or "$dwrserverclassname" properties introduced above, but on the actual instances.
 
Variant 1: activate "light" mapping style instead of the normal mapping style
 
This would imply a global setting in web.xml to tell DWR what class mapping scheme to use:
 
    <init-param>
        <param-name>lightClassMapping</param-name>
        <param-value>true</param-value>
    </init-param>
 
The class mapping behaviour would change in the following way:
  • No constructor functions nor any other JavaScript class-related code generated by the DWR servlet for mapped classes.
  • An outbound object of a mapped class will get its class identity annotated as a property instead of a constructor call, ie:
        s101={name:"Donald","$dwrclassname":"db.Person"}
    instead of:
        s101=new db.Person();s101.name="Donald";
  • Inbound objects will be inspected for a "$dwrclassname" property and if there is a matching mapped class, the corresponding Java class will be instantiated. Thus, if the browser code wants to specify the class of an untyped object, it just has to add the "$dwrclassname" property on the object.
Note a few things in the above suggestion:
  1. The "$dwrclassname" property is placed on the objects instead of on the class, as there is no class.
  2. The "$dwrclassname" property still specifies the mapped JavaScript class name, not the Java class name (ie db.Person and not mypkg.dto.Person from the previous examples).
  3. Only classes that have been set-up for conversion and also set-up for mapping through the "javascript" attribute are allowed to be created using the inbound "$dwrclassname" feature, to stop evil hackers that want to create dangerous objects on the server.
Variant 2: activate "light" mapping style in addition to the normal mapping style
 
This means keeping the normal mapping style on all mapped classes (with a "javascript" attribute), and using the light mapping style as a default on the remaining bean classes that are not mapped (without "javascript" attributes). This would work the same way as variant 1, but with a few differences:
  • No web.xml enabling configuration needed as this behaviour is always present.
  • Outbound data will be annotated with "$dwrserverclassname" and the Java class name, as there is no mapped JavaScript class name.
  • Inbound data will also have to use "$dwrserverclassname" instead, and specify the Java class name.
  • Security-wise we will only allow Java classes set-up for conversion to be created by inbound data, which is a little bit broader than variant 1. 
Joe said:
I think I'm struggling here from not really seeing the use-case.
I'm not keen on allowing the internet to know about, much less specify the java side classes, and we already have a solution?

I wonder if we couldn't expand on the signatures idea for times when the current system fails.

Real method:
public void foo(SomeInterface x) {...}

dwr.xml:
<signatures>
public void foo(SomeImplementation x) {...};
<signatures>

What do you think?
 
 
Randy said:
And of course I'm going to argue for this one, as it's my use case. To remind everyone of my use case, as it has been awhile, I have an api that is built on top of dojo and is fairly extensive. I'd like to be able to just set the $dwrclassname on those objects instead of having to create a new object based on my javascript attribute set in dwr.xml and copy over the attributes every time I send an object.  Do I need to give a more detailed example here?
 
 
Joe said:
So couldn't we just tweak getObjectClassName to inspect $dwrclassname and return that, if set?  
Plug-in API for class-mapping
 
To modularize most of what has been suggested above, and to open up for other customizations of the class-mapping system, the following functions could be moved to a separate overridable class:
  • Code generation for bean/object classes (f ex used by the standard class-mapping scheme).
  • Type annotation of outbound data (f ex new db.Person() or $dwrclassname="db.Person")
  • Checking of inbound data (verifying classes are allowed to be created remotely)
There may also be need for a callback interface in engine.js, so custom code can detect the type of inbound data.
 
Here's an example of what it could look like if implementing the "light" class-mapping from above (according to variant 1) as a custom class-mapper:
 
web.xml:
    <init-param>
        <param-name>org.directwebremoting.extend.ClassMapper</param-name>
        <param-value>org.directwebremoting.impl.LightClassMapper</param-value>
    </init-param>
 
java/server:
    public class LightClassMapper {
        public generateDeclarationsForClass(...) { /*NOP*/ }
        public convertOutboundObject(...) { ... }
        public checkInboundObject(...) { ... }
    }
 
javascript/browser:
    <script src="dwr/engine.js"></script>
    <script src="lightclassmapper.js"></script>
        contains:
            dwr.engine.setClassMapper(function(data) {
                if (data["$dwrclassname"])
                    return data["$dwrclassname"];
                else
                    return null; // Use standard type detection
            });
 
The plug-in API would also open up for other kinds of user-defined customizations, f ex if someone wants to generate getters and setters on mapped bean classes.


RE: class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping schemes

by mikewse :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Nice. I'll implement E5 but skip most parts of E6.
About doing client-side type overrides: should people doing overrides be instructed to override dwr.engine internal methods, or should I add some public API to provide the necessary hooks?
 
Something along the lines of:
    dwr.engine.setMappedClassObjectCreator( function(classname,membervalues){...} )
for allowing custom creation of typed objects coming in from the server.
    dwr.engine.setMappedClassTypeDetector( function(obj){...} )
for allowing custom type-detection of objects being serialized to server.
 
(I used insanely long names here to describe the purpose of the methods.)
 
Best regards
Mike


From: joseph.walker@... [mailto:joseph.walker@...] On Behalf Of Joe Walker
Sent: den 11 juli 2008 18:14
To: users@...
Subject: Re: [dwr-user] class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping schemes


OK.
Clearly this isn't a pain point that I feel, but if 2 regulars feel it, then others must too.
http://bugs.directwebremoting.org/bugs/browse/DWR-269

Joe.


On Fri, Jul 11, 2008 at 12:52 AM, Mike Wilson <mike@...> wrote:
Ok, first I'll address your comments:
 
> Use-cases for lighter class mapping?
The request I'm mainly thinking about was from a long time ago on the list. I haven't saved a link to it, but the main theme of that request (AFAICR) was that:
1) They didn't need the extra benefits provided by the JavaScript classes. They just wanted to be able to detect types on objects.
2) The types needing class mapping were not known before run-time (hm, possibly because of some internal abstraction/plug-in framework?) so they were not able to mark the desired classes for mapping in dwr.xml before being deployed and started.
3) Thus they needed class mapping that was "always on" and their only solution would be to enable class mapping for all converted classes, but that would potentially mean mapping a lot of classes with the associated overhead of our generated JavaScript class code.
Continuing to Randy's case I think it can be summarized as:
4) Make it possible to use class-mapping for client-side objects that are not created by our generated constructors (because not having control over object creation etc).
 
> Not good to expose Java class names
Variant 1 does not expose Java class names.
 
> Extending signatures to solve this?
I understand Joe's suggestion as telling the signatures system to use a certain concrete class for all calls to a certain method accepting non-concrete arguments.
I'm not sure it's worth the effort to add this behaviour to the signatures handling as it doesn't solve handling of multiple subclasses or client-side type decisions. And the static setup possible with signatures may alternatively and easily be done by wrapping the abstract-argument method with a concrete ditto on the server.
 
> Tweak getObjectClassName to fix Randy's case?
Well, if this becomes an official and documented solution then we are in fact implementing half (the client-side stuff) of my "Plug-in API for class mapping" suggestion below ;-).
 
And here's some new material for discussion:
 
How can we let the client code know the type of outbound objects?
In DWR 2.0 and current 3.0 there are two very different systems in effect: (1) outbound exceptions have a property naming their Java class name and, (2) mapped classes are associated with a JavaScript class (named from the mapping name in dwr.xml) by being instantiated with a generated constructor.
My suggestion is to make it possible to attach type info much like is already done for exceptions, but for all other object types. This is by itself not a big thing, and we can choose to only attach the mapping name (and not the Java name) if that feels better security-wise.
 
How can the client code let the server know the desired type of inbound objects?
Currently this is done by looking up the JavaScript class that the object belongs to.
Though, I'm sensing that we are agreeing that manually setting $dwrclassname could be allowed to override our default type-detection?
 
Updated suggestion
If the above is ok, and implementing a plug-in API for class mapping is not interesting at all but having a lighter class-mapping scheme is a little interesting, then we could do the following short-cut to make this really simple:
  • skip having any settings for class-mapping mode
  • move generated mapped classes to a separate file (/dwr/classes.js) [discussed in other thread]
  • the only other server-side change is to send class-mapped outbound objects like this in DWRP:
      s101=dwr.engine._createObject("Person");
    instead of like today:
      s101=new Person();
  • createObject() would look up if there is a constructor function named "Person" and
      if exists: return an object created using the constructor
      if not exists: return an Object with type as member: { "$dwrclassname": "Person" }
  • client-side type-detection should look for $dwrclassname overrides on objects sent to server
This solution would make it possible to choose between light and full class-mapping just by deciding whether to include the generated classes from /dwr/classes.js or not.
If the generated classes are not present then we would automatically fall back to light class-mapping using the $dwrclassname members instead.
I think this is a coherent and symmetrical solution and I quite like it.
 
Best regards
Mike
Add a simplified class-mapping scheme that doesn't use JavaScript classes
 
The current class mapping scheme was designed to be compatible with JavaScript classes to be able to benefit from native constructors, instanceof support and class inheritance. Though, in some cases it is sufficient to only inspect, or set, the actual class identity and not use any of the other features. Some properties of the current class mapping scheme may then stand in the way for an efficient implementation, f ex not being able to say that an existing type-less object should be parsed as a certain class on the server (Randy's case) without actually recreating the object and calling the appropriate constructor.
 
I have two variations on a suggestion that solves this, and they both depend on using the "$dwrclassname" or "$dwrserverclassname" properties introduced above, but on the actual instances.
 
Variant 1: activate "light" mapping style instead of the normal mapping style
 
This would imply a global setting in web.xml to tell DWR what class mapping scheme to use:
 
    <init-param>
        <param-name>lightClassMapping</param-name>
        <param-value>true</param-value>
    </init-param>
 
The class mapping behaviour would change in the following way:
  • No constructor functions nor any other JavaScript class-related code generated by the DWR servlet for mapped classes.
  • An outbound object of a mapped class will get its class identity annotated as a property instead of a constructor call, ie:
        s101={name:"Donald","$dwrclassname":"db.Person"}
    instead of:
        s101=new db.Person();s101.name="Donald";
  • Inbound objects will be inspected for a "$dwrclassname" property and if there is a matching mapped class, the corresponding Java class will be instantiated. Thus, if the browser code wants to specify the class of an untyped object, it just has to add the "$dwrclassname" property on the object.
Note a few things in the above suggestion:
  1. The "$dwrclassname" property is placed on the objects instead of on the class, as there is no class.
  2. The "$dwrclassname" property still specifies the mapped JavaScript class name, not the Java class name (ie db.Person and not mypkg.dto.Person from the previous examples).
  3. Only classes that have been set-up for conversion and also set-up for mapping through the "javascript" attribute are allowed to be created using the inbound "$dwrclassname" feature, to stop evil hackers that want to create dangerous objects on the server.
Variant 2: activate "light" mapping style in addition to the normal mapping style
 
This means keeping the normal mapping style on all mapped classes (with a "javascript" attribute), and using the light mapping style as a default on the remaining bean classes that are not mapped (without "javascript" attributes). This would work the same way as variant 1, but with a few differences:
  • No web.xml enabling configuration needed as this behaviour is always present.
  • Outbound data will be annotated with "$dwrserverclassname" and the Java class name, as there is no mapped JavaScript class name.
  • Inbound data will also have to use "$dwrserverclassname" instead, and specify the Java class name.
  • Security-wise we will only allow Java classes set-up for conversion to be created by inbound data, which is a little bit broader than variant 1. 
Joe said:
I think I'm struggling here from not really seeing the use-case.
I'm not keen on allowing the internet to know about, much less specify the java side classes, and we already have a solution?

I wonder if we couldn't expand on the signatures idea for times when the current system fails.

Real method:
public void foo(SomeInterface x) {...}

dwr.xml:
<signatures>
public void foo(SomeImplementation x) {...};
<signatures>

What do you think?
 
 
Randy said:
And of course I'm going to argue for this one, as it's my use case. To remind everyone of my use case, as it has been awhile, I have an api that is built on top of dojo and is fairly extensive. I'd like to be able to just set the $dwrclassname on those objects instead of having to create a new object based on my javascript attribute set in dwr.xml and copy over the attributes every time I send an object.  Do I need to give a more detailed example here?
 
 
Joe said:
So couldn't we just tweak getObjectClassName to inspect $dwrclassname and return that, if set?  
Plug-in API for class-mapping
 
To modularize most of what has been suggested above, and to open up for other customizations of the class-mapping system, the following functions could be moved to a separate overridable class:
  • Code generation for bean/object classes (f ex used by the standard class-mapping scheme).
  • Type annotation of outbound data (f ex new db.Person() or $dwrclassname="db.Person")
  • Checking of inbound data (verifying classes are allowed to be created remotely)
There may also be need for a callback interface in engine.js, so custom code can detect the type of inbound data.
 
Here's an example of what it could look like if implementing the "light" class-mapping from above (according to variant 1) as a custom class-mapper:
 
web.xml:
    <init-param>
        <param-name>org.directwebremoting.extend.ClassMapper</param-name>
        <param-value>org.directwebremoting.impl.LightClassMapper</param-value>
    </init-param>
 
java/server:
    public class LightClassMapper {
        public generateDeclarationsForClass(...) { /*NOP*/ }
        public convertOutboundObject(...) { ... }
        public checkInboundObject(...) { ... }
    }
 
javascript/browser:
    <script src="dwr/engine.js"></script>
    <script src="lightclassmapper.js"></script>
        contains:
            dwr.engine.setClassMapper(function(data) {
                if (data["$dwrclassname"])
                    return data["$dwrclassname"];
                else
                    return null; // Use standard type detection
            });
 
The plug-in API would also open up for other kinds of user-defined customizations, f ex if someone wants to generate getters and setters on mapped bean classes.


Re: class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping scheme

by Joe Walker-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

We're talking about the situation where neither using 'new Foo()' nor
using $dwrClassName='Foo' are good enough?

I think that the number of people that the number of people for whom
nether 'new Foo' or $dwrClassName are good enough is very small, and
they can be directed where to go by the mailing list.

I think that the number of people that read through APIs looking for
functionallity is high, and we shouldn't put forward really advanced
concepts, which would only serve to obscure the things that we'd like
them to discover.

I do like self describing method names, but I'm leaning towards no
methods at all at the moment.

Joe.

On Sun, Jul 13, 2008 at 8:25 PM, Mike Wilson <mikewse@...> wrote:

> Nice. I'll implement E5 but skip most parts of E6.
> About doing client-side type overrides: should people doing overrides be
> instructed to override dwr.engine internal methods, or should I add some
> public API to provide the necessary hooks?
>
> Something along the lines of:
>     dwr.engine.setMappedClassObjectCreator(
> function(classname,membervalues){...} )
> for allowing custom creation of typed objects coming in from the server.
>     dwr.engine.setMappedClassTypeDetector( function(obj){...} )
> for allowing custom type-detection of objects being serialized to server.
>
> (I used insanely long names here to describe the purpose of the methods.)
>
> Best regards
> Mike
>
> ________________________________
> From: joseph.walker@... [mailto:joseph.walker@...] On Behalf Of
> Joe Walker
> Sent: den 11 juli 2008 18:14
> To: users@...
> Subject: Re: [dwr-user] class mapping E5 & E6: Offer a "lighter"
> bi-directional class-mapping scheme & Allow alternative class-mapping
> schemes
>
>
> OK.
> Clearly this isn't a pain point that I feel, but if 2 regulars feel it, then
> others must too.
> http://bugs.directwebremoting.org/bugs/browse/DWR-269
>
> Joe.
>
>
> On Fri, Jul 11, 2008 at 12:52 AM, Mike Wilson <mike@...> wrote:
>>
>> Ok, first I'll address your comments:
>>
>> > Use-cases for lighter class mapping?
>> The request I'm mainly thinking about was from a long time ago on the
>> list. I haven't saved a link to it, but the main theme of that request
>> (AFAICR) was that:
>> 1) They didn't need the extra benefits provided by the JavaScript classes.
>> They just wanted to be able to detect types on objects.
>> 2) The types needing class mapping were not known before run-time (hm,
>> possibly because of some internal abstraction/plug-in framework?) so they
>> were not able to mark the desired classes for mapping in dwr.xml before
>> being deployed and started.
>> 3) Thus they needed class mapping that was "always on" and their only
>> solution would be to enable class mapping for all converted classes, but
>> that would potentially mean mapping a lot of classes with the associated
>> overhead of our generated JavaScript class code.
>> Continuing to Randy's case I think it can be summarized as:
>> 4) Make it possible to use class-mapping for client-side objects that are
>> not created by our generated constructors (because not having control over
>> object creation etc).
>>
>> > Not good to expose Java class names
>> Variant 1 does not expose Java class names.
>>
>> > Extending signatures to solve this?
>> I understand Joe's suggestion as telling the signatures system to use a
>> certain concrete class for all calls to a certain method
>> accepting non-concrete arguments.
>> I'm not sure it's worth the effort to add this behaviour to the signatures
>> handling as it doesn't solve handling of multiple subclasses or client-side
>> type decisions. And the static setup possible with signatures
>> may alternatively and easily be done by wrapping the abstract-argument
>> method with a concrete ditto on the server.
>>
>> > Tweak getObjectClassName to fix Randy's case?
>> Well, if this becomes an official and documented solution then we are in
>> fact implementing half (the client-side stuff) of my "Plug-in API for class
>> mapping" suggestion below ;-).
>>
>> And here's some new material for discussion:
>>
>> How can we let the client code know the type of outbound objects?
>> In DWR 2.0 and current 3.0 there are two very different systems in effect:
>> (1) outbound exceptions have a property naming their Java class name and,
>> (2) mapped classes are associated with a JavaScript class (named from the
>> mapping name in dwr.xml) by being instantiated with a generated constructor.
>> My suggestion is to make it possible to attach type info much like is
>> already done for exceptions, but for all other object types. This is by
>> itself not a big thing, and we can choose to only attach the mapping name
>> (and not the Java name) if that feels better security-wise.
>>
>> How can the client code let the server know the desired type of inbound
>> objects?
>> Currently this is done by looking up the JavaScript class that the object
>> belongs to.
>> Though, I'm sensing that we are agreeing that manually setting
>> $dwrclassname could be allowed to override our default type-detection?
>>
>> Updated suggestion
>> If the above is ok, and implementing a plug-in API for class mapping is
>> not interesting at all but having a lighter class-mapping scheme is a little
>> interesting, then we could do the following short-cut to make this really
>> simple:
>>
>> skip having any settings for class-mapping mode
>> move generated mapped classes to a separate file (/dwr/classes.js)
>> [discussed in other thread]
>> the only other server-side change is to send class-mapped outbound objects
>> like this in DWRP:
>>   s101=dwr.engine._createObject("Person");
>> instead of like today:
>>   s101=new Person();
>> createObject() would look up if there is a constructor function named
>> "Person" and
>>   if exists: return an object created using the constructor
>>   if not exists: return an Object with type as member: { "$dwrclassname":
>> "Person" }
>> client-side type-detection should look for $dwrclassname overrides on
>> objects sent to server
>>
>> This solution would make it possible to choose between light and full
>> class-mapping just by deciding whether to include the generated classes from
>> /dwr/classes.js or not.
>> If the generated classes are not present then we would automatically fall
>> back to light class-mapping using the $dwrclassname members instead.
>> I think this is a coherent and symmetrical solution and I quite like it.
>>
>> Best regards
>> Mike
>>
>> Add a simplified class-mapping scheme that doesn't use JavaScript classes
>>
>> The current class mapping scheme was designed to be compatible with
>> JavaScript classes to be able to benefit from native constructors,
>> instanceof support and class inheritance. Though, in some cases it is
>> sufficient to only inspect, or set, the actual class identity and not use
>> any of the other features. Some properties of the current class mapping
>> scheme may then stand in the way for an efficient implementation, f ex not
>> being able to say that an existing type-less object should be parsed as a
>> certain class on the server (Randy's case) without actually recreating the
>> object and calling the appropriate constructor.
>>
>> I have two variations on a suggestion that solves this, and they both
>> depend on using the "$dwrclassname" or "$dwrserverclassname" properties
>> introduced above, but on the actual instances.
>>
>> Variant 1: activate "light" mapping style instead of the normal mapping
>> style
>>
>> This would imply a global setting in web.xml to tell DWR what class
>> mapping scheme to use:
>>
>>     <init-param>
>>         <param-name>lightClassMapping</param-name>
>>         <param-value>true</param-value>
>>     </init-param>
>>
>> The class mapping behaviour would change in the following way:
>>
>> No constructor functions nor any other JavaScript class-related code
>> generated by the DWR servlet for mapped classes.
>> An outbound object of a mapped class will get its class identity annotated
>> as a property instead of a constructor call, ie:
>>     s101={name:"Donald","$dwrclassname":"db.Person"}
>> instead of:
>>     s101=new db.Person();s101.name="Donald";
>> Inbound objects will be inspected for a "$dwrclassname" property and if
>> there is a matching mapped class, the corresponding Java class will be
>> instantiated. Thus, if the browser code wants to specify the class of an
>> untyped object, it just has to add the "$dwrclassname" property on the
>> object.
>>
>> Note a few things in the above suggestion:
>>
>> The "$dwrclassname" property is placed on the objects instead of on the
>> class, as there is no class.
>> The "$dwrclassname" property still specifies the mapped JavaScript class
>> name, not the Java class name (ie db.Person and not mypkg.dto.Person from
>> the previous examples).
>> Only classes that have been set-up for conversion and also set-up for
>> mapping through the "javascript" attribute are allowed to be created using
>> the inbound "$dwrclassname" feature, to stop evil hackers that want to
>> create dangerous objects on the server.
>>
>> Variant 2: activate "light" mapping style in addition to the normal
>> mapping style
>>
>> This means keeping the normal mapping style on all mapped classes (with a
>> "javascript" attribute), and using the light mapping style as a default
>> on the remaining bean classes that are not mapped (without "javascript"
>> attributes). This would work the same way as variant 1, but with a few
>> differences:
>>
>> No web.xml enabling configuration needed as this behaviour is always
>> present.
>> Outbound data will be annotated with "$dwrserverclassname" and the Java
>> class name, as there is no mapped JavaScript class name.
>> Inbound data will also have to use "$dwrserverclassname" instead, and
>> specify the Java class name.
>> Security-wise we will only allow Java classes set-up for conversion to be
>> created by inbound data, which is a little bit broader than variant 1.
>>
>> Joe said:
>> I think I'm struggling here from not really seeing the use-case.
>> I'm not keen on allowing the internet to know about, much less specify the
>> java side classes, and we already have a solution?
>>
>> I wonder if we couldn't expand on the signatures idea for times when the
>> current system fails.
>>
>> Real method:
>> public void foo(SomeInterface x) {...}
>>
>> dwr.xml:
>> <signatures>
>> public void foo(SomeImplementation x) {...};
>> <signatures>
>>
>> What do you think?
>>
>>
>> Randy said:
>> And of course I'm going to argue for this one, as it's my use case. To
>> remind everyone of my use case, as it has been awhile, I have an api that is
>> built on top of dojo and is fairly extensive. I'd like to be able to just
>> set the $dwrclassname on those objects instead of having to create a new
>> object based on my javascript attribute set in dwr.xml and copy over the
>> attributes every time I send an object.  Do I need to give a more detailed
>> example here?
>>
>>
>> Joe said:
>> So couldn't we just tweak getObjectClassName to inspect $dwrclassname and
>> return that, if set?
>>
>> Plug-in API for class-mapping
>>
>> To modularize most of what has been suggested above, and to open up for
>> other customizations of the class-mapping system, the following functions
>> could be moved to a separate overridable class:
>>
>> Code generation for bean/object classes (f ex used by the standard
>> class-mapping scheme).
>> Type annotation of outbound data (f ex new db.Person() or
>> $dwrclassname="db.Person")
>> Checking of inbound data (verifying classes are allowed to be created
>> remotely)
>>
>> There may also be need for a callback interface in engine.js, so custom
>> code can detect the type of inbound data.
>>
>> Here's an example of what it could look like if implementing the "light"
>> class-mapping from above (according to variant 1) as a custom class-mapper:
>>
>> web.xml:
>>     <init-param>
>>         <param-name>org.directwebremoting.extend.ClassMapper</param-name>
>>
>> <param-value>org.directwebremoting.impl.LightClassMapper</param-value>
>>     </init-param>
>>
>> java/server:
>>     public class LightClassMapper {
>>         public generateDeclarationsForClass(...) { /*NOP*/ }
>>         public convertOutboundObject(...) { ... }
>>         public checkInboundObject(...) { ... }
>>     }
>>
>> javascript/browser:
>>     <script src="dwr/engine.js"></script>
>>     <script src="lightclassmapper.js"></script>
>>         contains:
>>             dwr.engine.setClassMapper(function(data) {
>>                 if (data["$dwrclassname"])
>>                     return data["$dwrclassname"];
>>                 else
>>                     return null; // Use standard type detection
>>             });
>>
>> The plug-in API would also open up for other kinds of user-defined
>> customizations, f ex if someone wants to generate getters and setters on
>> mapped bean classes.
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@...
For additional commands, e-mail: users-help@...


RE: class mapping E5 & E6: Offer a "lighter" bi-directional class-mapping scheme & Allow alternative class-mapping scheme