Question

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?

Was it helpful?

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.

OTHER TIPS

As @Franck Wolff explained, for the technical reason of how values are stored in memory, you get into all kinds of troubles when using large numbers - not just when transferring between Flex and BlazeDS, but with numeric values in general.

Since it seems you're not using these numbers for any calculations, I presume the correct sequence is more important than the value here.

So you should do yourself a favor: Convert the IDs to String, transfer, then use Integer.valueOf( String ) to convert back to numeric values. It's the only way you really know for sure what you're getting on the other side - unless, of course, you're going to write your own serialization classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top