History | Log In     View a printable version of the current page.  
Issue Details (XML)

Key: BLZ-100
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Assignee: aglosban
Reporter: Brian Telintelo
Votes: 7
Watchers: 8
Operations

If you were logged in you would be able to see more operations.
BlazeDS

AMF Serialization from Java to AS not working corectly for Map Types

Created: 03/25/08 10:38 AM   Updated: 05/20/09 02:54 PM
Component/s: Channels: AMF, Messaging, Proxy
Security Level: Public (All JIRA Users )

File Attachments: 1. Text File MapProxyPatch.patch (2 kb)


Severity: Incorrectly Functioning
Reproducibility: Every Time
Discoverability: High
Found in Version: BlazeDS 3.0.0
Milestone: BlazeDS 3.0.1
Affected OS(s): All OS Platforms - All
Steps to Reproduce:
Steps to reproduce:
1. Create a java service that returns a Map/HashMap.
2. Make the keys used in the map to be something other than a String(like an Integer).
 
 Actual Results:
 On the actionscript side, you will see that the keys come back, but all the values are null.
 
 Expected Results:
 On the actionscript side, all keys and values will be returned.
 
 Workaround (if any):
 Use strings as keys to the map.

The problem I believe is that at approx.(based on rev) line 89 of MapProxy.java, you are looping through all the keys of the map, and adding them to a property list:
propertyNames.add(key.toString());
This means though that later down the line the value for that key won't be found unless the key was a string to begin with. When the data gets to actionscript, the keys need to be strings, but I don't think this is the desired output when you use something other than a string as a key.

Attached is a patch that will convert the hashmap to have all string keys.
 
 
Language Found: English
Bugbase Id: none
Triaged: Yes
Regression: No
QA Owner: aglosban
Resolved by: Mete Atamel
Participants: aglosban, Brian Telintelo, Mark Bober, Mete Atamel, Seth Hodgson and Trevor Baker
Browser: Firefox 2.x
JDK: Sun JDK 5
Application Server: Apache Tomcat 6.x

Sub-Tasks  All   Open   
 Sub-Task Progress: 

 All   Comments      Sort Order:
Trevor Baker - [03/25/08 03:09 PM ]
to Seth for review/consideration

Seth Hodgson - [03/25/08 06:35 PM ]
The issue with this is that you'll get the expected ActionScript Object on the client, but if you send it back to the server you won't end up with a Map<Integer, String> or whatever you started out with. If that's not a concern it may be worth considering.

For now, you can register your own custom MapProxy with the PropertyProxyRegistry during server startup (from a BootstrapService impl for instance).


Brian Telintelo - [03/26/08 08:45 AM ]
We are only going one way with the HashMap, so we have not had the problem the other way. So you are saying that the only Map you can use is Map<String,Object>(without writing a custom proxy)? We can certainly live with this. However, I think the MapProxy should handle non String keys in a map better. Currently if I have an <Integer,Object>, when I get the values in actionscript, the keys are there but the values are missing. It makes you first troubleshoot problems with your values and those objects rather than your keys. I would expect one of the following resolutions instead:

1. In MapProxy, all of the keys for a map passed in would be converted to strings, thus allowing the values to be found correctly later. As you said, this would be inconsistent if someone went from AS to Java(but this may still be better than the current output).
2. flex.messaging.io.PropertyProxy would make parameters for propertyName type Object instead of String. A toString would be done on the propertyName further down the line after the values are retrieved.
3. MapProxy would do an instanceOf on the keys and if is not type String would throw an error(MapProxy would not accept a Map with non String keys).


Seth Hodgson - [03/26/08 03:53 PM - edited ]
We'll update MapProxy to not toString() entries in the the propertiesNames list and use the original Object key to look up the value during serialization, but we'll still toString() when looking for potential concrete/declared bean properties (for support of strongly typed subtypes that implement Map).

That will resolve your issue, but I still have a concern that folks will expect this sort of thing to roundtrip correctly. Unfortunately, the flash.utils.Dictionary type is not natively supported by AMF so Maps on the server must be serialized to anonymous ActionScript Objects on the client. The API for Object is conceptually Map<String, Object>, so there's no way to ship something like a Map<Integer, Object> from the client back to the server apart from implementing custom types in ActionScript and Java that use IExternalizable to make this work.

So, when sending data to Flash, the recommended approach remains to use strongly typed objects on both ends or to use a Map<String, Object> on the server which is symmetric to an anonymous ActionScript Object.

Fixing and checking this in is lower down my current stack right now, but I'll get to it :)

Brian Telintelo - [03/27/08 09:01 AM ]
Thanks, no rush!

Trevor Baker - [04/24/08 03:14 PM ]
deferred for now

Mark Bober - [01/30/09 09:04 AM ]
We have a public Java API that we have exposed via BlazeDS to a Flex-based client. This public Java API uses maps fairly extensively. We also use typed identifiers in our API, as it is a best practice to use typed identifiers rather than Strings. We REALLY need to get this fixed as soon as possible. So, I'll keep an eye on it!

Mete Atamel - [05/20/09 02:54 PM ]
Fixed with change 7146 on BlazeDS trunk.