Search code examples
javaapache-flextype-conversionblazeds

BlazeDs converting an int to a float while passing data from flex to java


I have a problem when passing back an int from flex to java. The int in question is an ID and I seemed to have hit a threshold this morning because things started breaking.

I am passing back 922927950 in flex through blaze to java. By the time the java gets it has been converted to 9.2292795E8

My code in flex is

service.getRemoteObject().sendData(objectIds);

where object ids is an ArrayCollection. In this I can debug and see the number is 922927950. I can then debug the java and see that it has been converted to 9.2292795E8

sendData has the following signature

public void sendData(List<Integer> objectIds) {...}

I have tried changing the flex objectids array to contain numbers and not ints but this does not work either. In java as far as I know to store 9.2292795E8 the number has to be a float. Float does fit inside integer in java so I presume that is why I do not get type mismatch errors. The trouble is that the ids are now in scientific notation that breaks my jpa query which uses them.

Does anyone know why the number is converted into scientific notation?

Thanks

UPDATE

after some more investigation it gets even weirder. I tried the following code in my java

public void sendData(List<Integer> objectIds) {
    List<Integer> converted = new ArrayList<Integer>();

    for (Integer objectId : objectIds) {
        converted.add(objectId);
    }
    ...
}

I now get class cast exceptions saying that I cannot convert double to integer on the converted.add(objectId) line

 java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer

This happens when in flex I cast 922927950 to Number which I presume maps to Double. Is my problem here that I am using generics on the java side and BlazeDs does not consider these so just matches on the signature without generics?


Solution

  • First, look at the Amf3Types documentation:

    The maximum value for an int that will avoid promotion to an ActionScript Number when sent via AMF 3 is 2^28 - 1, or 0x0FFFFFFF

    This is 268,435,455 in decimal representation and 922,927,950 is far over this limit. Note that it is a serialization issue: the int data type is able to hold a 2^31 - 1 value, just like a regular 32-bits int type.

    Now, you should try this with your code:

    public void sendData(List<?> objectIds) {
        List<Integer> converted = new ArrayList<Integer>();
    
        for (Object objectId : objectIds) {
            converted.add(((Number)objectId).intValue());
        }
        ...
    }
    

    If you need better control over type conversions and advanced numeric types, you should consider using GraniteDS instead of BlazeDS. See documentation here and here.

    Regards, Franck.