Details

    • Affects:
      Interactive Demo/Tutorial, Compatibility/Configuration
    • Workaround:
      Workaround Exists
    • Workaround Description:
      Hide

      Convert byte array in Flex to base64 and then use toBinary on the backend to retrieve actual binary data. This causes increase in transport size of data, but effectively eliminates the error. This will not be possible in all environments, so it is only a temporary workaround.

      Show
      Convert byte array in Flex to base64 and then use toBinary on the backend to retrieve actual binary data. This causes increase in transport size of data, but effectively eliminates the error. This will not be possible in all environments, so it is only a temporary workaround.
    • Estimated Difficulty:
      Medium

      Description

      This is an older issue I was having when I was still testing on Resin,
      but it applies on JBoss as well.

      I have a Flex RemoteObject that sends binary data (JPEG) through
      BlazeDS to ColdFusion to be written to a file. This works perfectly on
      ColdFusion 8. In CF8 I can do:

      <cfargument type="binary" name="myData">
      <cffile action="write" file="/data/images/test.jpg" output="#myData#">

      I can also call the coldboxproxy.cfc as a RemoteObject and pass the
      argument into ColdBox and it becomes part of the request collection
      (#rc.myData#) which I can write with:

      <cffile action="write" file="/data/images/test.jpg"
      output="#rc.myData#">

      So, ColdFusion 8 has no problem with this.

      Here is what Railo 3.1 does:

      If I attempt to accept the argument as binary as in my first example,
      I get this error:

      faultCode:Server.Processing
      faultString:'flex.messaging.MessageException:
      railo.runtime.exp.UDFCasterException : invalid call of the function
      process, second Argument (MYDATA) is of invalid type, can't cast
      Object type [Array] to a value of type [binary]' faultDetail:'null'

      Railo seems to treat my binary argument (a ByteArray from Flex) as an
      array where ColdFusion would see it as a byte array and allow me to
      write it directly to a file as binary. Is this intended behavior? I
      can't tell if this is the way the data is handled by Railo or the way
      the data is being prepared by BlazeDS. Any thoughts on this? I did
      some tests to find out as best I could.

      In Railo, if I use <cffile action="readBinary" variable="picture"> and
      dump the variable #picture# I see:

      Native Array
      140132...........-69-78 [truncated]

      This is nearly the same as the CF8 dump for the incoming argument. It
      is the binary information for the JPEG. I no longer see the ArrayImpl
      type for the data object. If I run picture.getClass() I get: class[B

      I can pass this #picture# variable into another CFC in Railo that
      accepts a binary argument and use <cffile action="write"
      output="#arguments.picture#"> within that CFC and it writes the file
      correctly! So, Railo CAN use binary arguments, but the ones coming in
      from Flex are being treated as arrays. (Or so I am leading myself to
      believe at this point)

      I am using BlazeDS (not LiveCycle Data Services) on my ColdFusion 8
      installation and this works fine, so BlazeDS hands over the data to
      CF8 correctly when received from Flex and CF8 sees (or can work with
      it as, not sure how exactly this is working) it as binary while Railo
      receives only an array. When I use the method above of reading binary
      data directly with Railo and then passing it into another CFC in
      Railo, it works just fine and I can use <cffile> and a binary incoming
      argument without issue.

      So, I'm guessing there might be a problem with the way BlazeDS hands
      things to Railo. As a side thought, does anyone have experience
      running a standalone BlazeDS instance and trying to have it connect
      with Railo? I was doing server push apps with both AJAX and Flex with
      instantaneous updates over CF8 using BlazeDS, but with Railo I'm
      limited to AMF calls to send and receive data, my push / live apps
      will not function correctly. Has anyone else gotten consumer /
      subscriber working with BlazeDS on Railo? And any word on if there
      will be gateway support in Railo in the near future?

      Anyway, If I specify the argument type as array I don't get a type
      error but instead I have to find a new way to write the file. I have
      tried to write the arguments.myData variable directly to a file, but
      this does nothing but create a 500+ kb file that is not an image. (It
      is the binary data for the array structure). I have tried to write
      arguments.myData.toString().getBytes() but this writes the bytes that
      make up the string representation of my JPEG data (including the
      [ and , characters from the toString() dump which I am featuring a
      tiny portion of below:

      If I run arguments.myData.toString() to see the contents of the array,
      I end up with a giant dump of something like this (but much longer).
      These are the numerical values of my bytes.

      [-1, -40, -1, -32, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0,
      0, -1, -37, 0, -124, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
      -64, 0, 17, 8, 0, -16, 1, 64, 3, 1, 17, 0, 2, 17, 1, 3, 17, 1, -1,
      -60, 1, -94, 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
      2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4,
      4, 0, 0, 1, 125, 1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81, 97,
      7, 34, 113, 20, 50, -127, -111, -95, 8, 35, 66, -79, -63, 21, 82, -47,
      -16, 36, 51, 98, 114, -126, 9, 10, 22, 23, 24, 25, 26, 37, 38, 39, 40,
      41, 42, 52, 53, 54, 55, 56,....... I REMOVED THOUSANDS OF additional
      array items here for space ........ 57, 58, 67, 68, 69, 70, 71, 72,
      73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104,
      105, 106, 115, 116, 117, 118, 119, 120, 121, 122, -125, -124, -123,
      -122, -121, -120, -119, -118, -110, -109, -108, -107, -106, -105,
      -104, -103, -102, -94, -93, -92, -91, -90, -89, -88, -87, -86, -78,
      -77, -76, -75, -74, -73, -72, -71, -70, -62, -61, -60, -59, -58, -57,
      -56, -55, -54, -46, -45, -44, -43, -42, -41, -40, -39, -38, -31, -30,
      -29, -28, -27, -26, -25, -24, -23, -22, -15, -14, -13, -12, -11, -10,
      -9, -8, -7, -6, 1, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 17, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5,
      4, 4, 0, 1, 2, 119, 0, 1, 2, 3, 17, 4, 5, 33]

      The array data is correct, those are the byte values for my array, but
      I cannot dump them to a file without some more serious effort... which
      I did put in, details later in the post.

      I have tried passing the data into ColdBox, but when I do so I receive
      a java heap error if I try to process the data as an argument in
      ColdBox or if I try to dump the contents of the array with <cfdump> in
      a ColdBox event. After this happens I have to restart Railo or else
      all of my pages have a message at the bottom after they process (which
      they still do, the error doesn't halt processing). This is the message
      that appears at the bottom of my pages after the first heap error:

      Railo 3.1.0.012 Error (Java.lang.outofmemoryerror)
      Message Java heap space
      Stacktrace The Error Occurred in
      /soft/railo-3.1.0.012-resin-3.1.2-without-jre/webapps/ROOT/coldbox/
      system/includes/panels/TracersPanel.cfm: line 29

      27: <cfif not isSimpleValue(TracerArray[i].extrainfo)>
      28: <strong>ExtraInformation:<br></strong>
      29: <cfdump var="#TracerArray[i].extrainfo#">
      30: <cfelseif TracerArray[i].extrainfo neq "">
      31: <strong>ExtraInformation:<br></strong>

      This is Railo running out of memory when trying to trace the array.
      All of my ColdBox pages display this error after I encounter it until
      I restart Railo.

      ColdFusion 8 when doing this dump shows me something like:

      [binary]
      -1-40-1-320167459-67 [truncated]

      So, it sees my argument as binary and handles it. Railo sees and array
      and tries to give me all of the elements in the trace / dump, thus the
      heap error.

      I have considered looping through the entire array and writing each
      byte out to a stream, but this would be terribly inefficient and not
      worth the trouble.

      I wrote a custom conversion class in Java and tested it on ColdFusion
      8. It creates a JPEG image with the right width and height and type,
      but the data is scrambled and not complete (green/grey, no real image
      data). This is due to an error in Java concerning handling hex data
      and rewriting bytes. I thought it may have been an encoding (unicode)
      thing or signed / unsigned bytes issue. Still looking into this. I
      used a <cffile action="read" file="test.jpg"> on a test JPEG to
      populate the object to stream the bytes into the buffer.

      My class is included at the end of the post. I never tested this on
      Railo because I couldn't get Railo to recognize my .class file. In CF8
      I just put it in web-inf/classes but I didn't know where the custom
      class directory was in Railo (on a per-site basis, not for the entire
      server instance).

      Ultimately I gave up on the class because I couldn't find the
      arrayImpl class in the Railo JARs and I needed this to properly read /
      map the array. (without a lot more work or the alternate, sluggish
      loop implementation) I ran arguments.myData.getClass() and ended up
      with:

      java.lang.Object
      railo.runtime.type.ArrayImpl

      So, that's the type of the array holding my binary data when received
      from Flex via BlazeDS

      I opened the type directory in the railo JAR and could not find this
      ArrayImpl class. Any ideas on the location? And where is the custom
      class directory for java objects that you want to use in Railo? (like
      WEB-INF/classes in CF8)

      For now I have settled on a workaround. I convert the ByteArray to a
      base64 string in Flex and then use #ToBinary(arguments.myData)# to do
      my file write. This increases the size of the data in transport, but
      ultimately alleviates my issue and writes my image perfectly.

      If anyone else is running into anything similiar, do let me know. I
      have other uses for this type of interaction and I won't have base64
      as an option in some of them.

      My attempted class is below. This class does compile, load, read the
      array and process the data into a JPEG, but there are some kinks. It
      won't be too helpful, but in case you were interested. It's cheap and
      dirty and very poorly-formed, I was just trying to get the job
      done!

      Please let me know about your BlazeDS configurations, if you have
      consumer/subscriber push / publish working or anything close

      import java.io.ByteArrayInputStream;
      import java.io.File;
      import java.io.FileNotFoundException;
      import java.io.FileOutputStream;
      import java.io.IOException;

      public class MyWriter {

      public String myText;

      public MyWriter(String theText)

      { //THIS IS JUST PLACEHOLDER TEXT UNTIL I FEED IN THE FILE DATA myText = theText; }

      public String WriteMyImage(java.lang.Object newtext) throws
      IOException {

      // CANNOT LOCATE THIS CLASS ArrayImpl arr = new ArrayImpl();
      String text;

      text = newtext;

      File file = new File("c:
      testing.jpg");
      FileOutputStream fouts = new FileOutputStream(file);

      // byte [] buf = byte[1024];

      if (myText.length() > 0)

      { text = myText; }

      byte buf[] = text.toString().getBytes();

      ByteArrayInputStream in = new ByteArrayInputStream(buf);

      int read = 0;
      while((read = in.read(buf)) > 0)

      { fouts.write(buf, 0, read); fouts.flush(); }

      fouts.close();
      return myText;

        Gliffy Diagrams

          Attachments

            Activity

              People

              • Assignee:
                micstriit Michael Offner
                Reporter:
                jbosshog98 James Glenn
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: