13 Replies Latest reply on Jun 20, 2011 7:48 AM by ronsen

    Serialized picture

    ronsen

      Hey all,

       

      is it a problem to put a serialized picture into a message queue to send it?! Or are there any restrictions i didn't recognize?

        • 1. Re: Serialized picture
          ronsen

          If somebody is interested, it works has to be implemented as follows:

           

           

          
          
          
          
          
          
          
          BufferedImage image = ImageIO.read(new File(IMAGEPATH+""+image));
          
          
          
          
          
          
          
          
          
          
          
          
          
          
          
          
          
          
          byteImage = sbi.toByteArray(image);
          
          
          
          
          
          
          
          
          TextMessage message = sess.createTextMessage(Base64.encodeBytes(byteImage));
          
          
          
          
          
          
          
          
          
          
          prod.send(message);
          
          
          
          
          
          
          
          
          System.out.println("Sent message: " + message.getText());
          
          

           

          The pciture is converted into a byteArray and from the byteArray into a Base64 String (otherwise the picture is crap).

           

          On the other side, the picture has to be decoded as follows:

           

          
          TextMessage textMessage = (TextMessage)message;  
          
          
          
          
          
          
          
          
          
          
          
             String text = textMessage.getText();  
          
          
          
          
          
          byte[] imagebytes = text.getBytes();
          
          
          
          
          BufferedImage image = ImageIO.read(new ByteArrayInputStream(Base64.decode(imagebytes)));
          
          
          
          
          
          
          
          
          BufferedImage outImg = new BufferedImage(400, 300,
          
          
          
          
          BufferedImage.TYPE_INT_RGB);
          
          
          Graphics g = outImg.getGraphics();
          
          
          g.drawImage(image, 0, 0, null);
          
          
          g.dispose();
          
          
          String messageId = textMessage.getJMSMessageID();
          
          
          String uniquePicId = messageId.substring(3,messageId.indexOf("-"));
          
          
          String uniquePicName = "test_new_"+uniquePicId;
          
          
          
          
          ImageIO.write(outImg, "jpg", new File(IMAGEPATH+"/"+uniquePicName+".jpg"));
          
          

           

          Thats it,

           

          My Question: Is it possible to handover a second parameter somewhere in the message to identify the picture e.g. for the picturename?

           

           

           

           

           

           

          __________________________________

          WTF, the editor and I wont get friends.....sorry

          • 2. Re: Serialized picture
            carl.heymann

            This is more about the JMS API. Why are you using a TextMessage? It seems that ObjectMessage would be more efficient, since you wouldn't need to use base64 encoding. Then you could serialize any object, using any serialization scheme. The filename and binary content could then be part of this object.

             

            Regardless of the JMS message type, you can set any header properties you like, using e.g. message.setStringProperty(name, value). You could include the filename in there.

            • 3. Re: Serialized picture
              ronsen

              Hey Carl,

               

              just tried to get it running with the objectMessage but for some reasion it didnt work really well. So I was just lucky that it worked this way.

               

              Only for clarifying, you wanted that instead of the TextMesasge an ObjectMessage is created in which i put the byteImage directly? or directly the image? When it arrives on the other side, im going to work with the picture, doing some transformation etc. how do i get the picture back to a file type?

               

              Thanks

              • 4. Re: Serialized picture
                clebert.suconic

                Actually, a BytesMessage would be the right way to go.

                • 5. Re: Serialized picture
                  carl.heymann

                  You can use ObjectMessage with any serializable object as content. A "byte[]" is probably directly serializable (not 100% sure, but it seems to compile). So you could create the object message using your "byteImage" variable directly. When you get the ObjectMessage back, you can get the content out using (byte[])message.getObject(); If you have the file name in a header property, then you have both the name and the content, and you can reconstruct the image on the other side.

                   

                  One thing to take note of, is that a BufferedImage's data is a raster, so the image is not compressed at all. It would be much more efficient to simply read the binary content of the original file (e.g. a jpeg) and send this.

                  • 6. Re: Serialized picture
                    clebert.suconic

                    You can.. but that's silly...

                     

                     

                    An ObjectMessage is converted internally to a ByteBuffer (byte array) anyway. Why go through the hassle of converting Picture->Bytes->objectMessage->Bytes

                     

                     

                    Just go straight to Bytes.

                     

                     

                    On Message systems, everything internally is a Byte.

                     

                     

                    BTW: if JMS was being created today, there would be a single MessageType. BytesArray, and you would have utility to make anything you want into a ByteBuffer.

                     

                     

                    If you have a ByteArray, just use a BytesMessage.

                     

                     

                    ObjectMessage is sllllooooowww.. As Serialization is sloooooowww.. (if you look at my curriculum by googling me you will see that I have some experience with Serialization).

                    • 7. Re: Serialized picture
                      carl.heymann

                      Hi Clebert, I wrote my previous comment before seeing yours (you'll see the timestamps are just 5 minutes apart). I fully agree that BytesMessage is better suited, and that java serialization is slow. From your serialization experience, is it just as bad if the object implements Externalizable, i.e. most of the serialization can be controlled manually? (I'm working on a system where there are a lot of externalizable objects being serialized)

                      • 8. Re: Serialized picture
                        clebert.suconic

                        Every time you use writeObject, the Serialization will look for a MetaData class to locate the writeExternal / readExternal, and you will have some streaming payload for each object.

                         

                         

                        If you only have a single root object that probably isn't as bad. I would recommend that you won't call any writeObject inside your writeExternal / readExternal, as you will also be looking for duplicate references inside your graph.

                         

                         

                        If you had internal objects in your graph you should do something like this:

                         

                         

                        writeExternal(....)

                        {

                             subObject.writeExternal(....)

                        }

                         

                         

                        readExternal()

                        {

                             subObject = new WhateverClassForSubObject();

                             subObject.readExternal();

                        }

                         

                         

                         

                        if you were doing this:

                         

                        readExternal(....)

                        {

                             subObject = input.readObject();

                        }

                         

                         

                         

                        The subObject read here will be looking for duplicate references, metadata and other stuff. i.e. if you use lots of internal Objects you are going almost as bad as plain serialization.

                        • 9. Re: Serialized picture
                          carl.heymann

                          Thanks Clebert, that makes a lot of sense.

                          • 10. Re: Serialized picture
                            clebert.suconic

                            Regardless of the JMS message type, you can set any header properties you like, using e.g. message.setStringProperty(name, value). You could include the filename in there.

                            +1000

                            • 11. Re: Serialized picture
                              ronsen

                              Hey guys,

                               

                              interesting discussion, could join yesterday sadly to try it out directly. But so far im about to implement cleberts advice to use the bytemessage directly with a bytearray.

                               

                              I just mentioned that the pictures are getting to big to send all of them via the messagequeue and its better to store them somewhere in the network to get them directly or on the nodes locally.

                              • 12. Re: Serialized picture
                                ronsen

                                When i use a messageDrivenBean to receive the messages in that way:

                                 

                                @MessageDriven(name = "MDBExample", 

                                        activationConfig = 

                                           { 

                                //                @ActivationConfigProperty(propertyName="messagingType", propertyValue="javax.jms.MessageListener"),

                                                @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), 

                                                @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/testQueue"), 

                                           })

                                 

                                 

                                and afterwards try to do something with the the message in onMessage(), why cant I call another class in which i declare an imagej object?!

                                The thing is, if i do it without the annotation, it works perfect.

                                • 13. Re: Serialized picture
                                  ronsen

                                  was a classpath issue, works now.

                                   

                                  If somebody is interested in my solution and what i discovered:

                                   

                                  If there are workers doing a task that produces some load, it should be taken nto account, that the threadpool and maxsessions are limited, this can be done with the annotations:

                                   

                                   @Pool (value=PoolDefaults.POOL_IMPLEMENTATION_STRICTMAX, maxSize=1) 
                                  @MessageDriven (mappedName = "MDB", activationConfig = { 
                                  
                                       @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), 
                                       @ActivationConfigProperty(propertyName = "destination", propertyValue = "/queue/theQueue"),
                                       @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
                                        @ActivationConfigProperty(propertyName = "MaxMessages", propertyValue="1"),
                                  })
                                  

                                   

                                   

                                  works for sure in clustered environments.