7 Replies Latest reply on Nov 8, 2006 2:40 PM by seth_hodgson

    Java to Actionscript conversion problem

      Hi all,

      I have got a strange problem with java to actionscript conversion that i have not been able to figure out.

      Ive got an actionscript VO mapped to a java VO, and when i call my remote object from actionscript that returns a collection of VO, surprisingly some of my objects in the collection are Object type an others are VO type. The rarest thing is that the omount of Object types vary when refreshing the application.

      If I debug my Java DAO, it is returning a Collection full of VO instances, but when debugging actionscript, some of them are Object instance.

      Any clues?

      Lee Oneal.
        • 1. Re: Java to Actionscript conversion problem
          Peter Farland Level 3
          Are you using RemoteObject or DataService?

          Do you have only one type of VO?

          Out of curiosity, does the VO implement any of the java standard interfaces such as java.io.Externalizable, java.util.Collection, java.util.List or java.util.Map?
          • 2. Re: Java to Actionscript conversion problem
            I am using Remote Object, my Java VO implements java.io.Serializable. I am also using hibernate 3.

            Here is my code.

            Actionscript VO
            ===========
            package com.imagemaker.olimpo.contacto.vo {

            import com.adobe.cairngorm.vo.ValueObject;
            import mx.collections.ArrayCollection;

            [Bindable]
            [RemoteClass(alias="com.imagemaker.olimpo.beans.Empresa")]

            public class EmpresaVO implements ValueObject {
            public var id:int;
            public var nombre:String;
            public var direccion:String;
            public var rut:String;
            public var contactos:ArrayCollection;
            }
            }

            Java VO
            =======
            package com.imagemaker.olimpo.beans;

            /**
            * AbstractEmpresa generated by MyEclipse - Hibernate Tools
            */

            public abstract class AbstractEmpresa implements java.io.Serializable {

            private Integer id;
            private String nombre;
            private String direccion;
            private String rut;

            // Constructors

            /** default constructor */
            public AbstractEmpresa() {
            }

            /** minimal constructor */
            public AbstractEmpresa(String nombre) {
            this.nombre = nombre;
            }

            /** full constructor */
            public AbstractEmpresa(String nombre, String direccion, String rut) {
            this.nombre = nombre;
            this.direccion = direccion;
            this.rut = rut;
            }


            // Property accessors

            public Integer getId() {
            return this.id;
            }

            public void setId(Integer id) {
            this.id = id;
            }

            public String getNombre() {
            return this.nombre;
            }

            public void setNombre(String nombre) {
            this.nombre = nombre;
            }

            public String getDireccion() {
            return this.direccion;
            }

            public void setDireccion(String direccion) {
            this.direccion = direccion;
            }

            public String getRut() {
            return this.rut;
            }

            public void setRut(String rut) {
            this.rut = rut;
            }
            }


            package com.imagemaker.olimpo.beans;
            // Generated by MyEclipse - Hibernate Tools

            import java.util.Set;


            /**
            * Empresa generated by MyEclipse - Hibernate Tools
            */
            public class Empresa extends AbstractEmpresa implements java.io.Serializable {

            // Constructors

            /**
            *
            */
            private static final long serialVersionUID = -5039282446108510122L;

            /** default constructor */
            public Empresa() {
            }

            /** minimal constructor */
            public Empresa(String nombre) {
            super(nombre);
            }

            /** full constructor */
            public Empresa(String nombre, String direccion, String rut) {
            super(nombre, direccion, rut);
            }

            }


            My service returns a List of Empresa and in Actionscript not all of my objects in the collection are transformed into EmpresaVO

            Please HELP!!!

            Thanks,

            Lee Oneal
            • 3. Java to Actionscript conversion problem
              Peter Farland Level 3
              Hi Lee,

              I don't immediately see anything wrong here. I can only start guessing at various theoretical situations.

              1. Can you experiment with delaying your RemoteObject call until after the creationComplete event has fired from the top level <mx:Application>?

              2. I see your AS VO has a contactos:ArrayCollection property... but this doesn't seem to correlate to anything in your Java VO... did you forget some code in your last message as I see you import java.util.Set in Empresa but never use it?

              3. When you say your RemoteObject returns a "collection of VO"... what is the Java type explicitly of this collection? Is there some getEmpresas() method? If so, can I see that method signature?

              4. Do you send the exact same instance of any of the Empresa objects back in the collection more than once? AMF allows for serialization by reference... perhaps the items that are being returned as anonymous Object instead of VO instances are related to this and may help us track down the cause?

              5. This should not matter, but we need to think outside of the box to track this issue down... can you try changing things about your VO to isolate the cause... try removing certain interfaces like Serializable and try again.

              Pete
              • 4. Re: Java to Actionscript conversion problem
                Hi Pete,

                thanks for te help.

                1. Can you experiment with delaying your RemoteObject call until after the creationComplete event has fired from the top level <mx:Application>?
                <strong>Ans: done</strong>

                2. I see your AS VO has a contactos:ArrayCollection property... but this doesn't seem to correlate to anything in your Java VO... did you forget some code in your last message as I see you import java.util.Set in Empresa but never use it?
                <strong>Ans: done</strong>

                3. When you say your RemoteObject returns a "collection of VO"... what is the Java type explicitly of this collection? Is there some getEmpresas() method? If so, can I see that method signature?
                <strong>
                SERVICE
                =======
                </strong>

                public List getEmpresas() {
                EmpresaDAOImpl impl = (EmpresaDAOImpl) FactoryDao.getInstance().getDao(EmpresaDAO.class);

                return impl.getAll(Empresa.class);
                }

                <strong>
                HIBERNATE PORTION
                ==================
                </strong>
                public List getAll(Class clase) {
                try {
                Session session = HibernateUtil.currentSession();
                Query query = session.createQuery("from " + clase.getSimpleName());
                List lista = query.list();
                return lista;
                } catch (HibernateException e) {
                HibernateUtil.closeSession();
                throw e;
                }
                }


                4. Do you send the exact same instance of any of the Empresa objects back in the collection more than once? AMF allows for serialization by reference... perhaps the items that are being returned as anonymous Object instead of VO instances are related to this and may help us track down the cause?
                <strong>Ans: NO, [com.imagemaker.olimpo.beans.Empresa@15e7597, com.imagemaker.olimpo.beans.Empresa@16cdbb8, com.imagemaker.olimpo.beans.Empresa@1cd2b82]</strong>

                5. This should not matter, but we need to think outside of the box to track this issue down... can you try changing things about your VO to isolate the cause... try removing certain interfaces like Serializable and try again.
                <strong>Ans:done</strong>

                I´ve done all your recomendatios and the problem continues. I´ve maid some debuggin in flex builder an I found something strange:

                <ul>
                <li>this = com.imagemaker.olimpo.contacto.command.GetEmpresasCommand (@4e25ee1)</li>
                <li>data = mx.rpc.events.ResultEvent (@929b079)</li>
                <li>
                event = mx.rpc.events.ResultEvent (@929b079)
                <ul>
                <li>bubbles = false</li>
                <li>cancelable = true</li>
                <li>currentTarget = null</li>
                <li>eventPhase = 2 [0x2]</li>
                <li>message = mx.messaging.messages.AcknowledgeMessage (@8e3c121)</li>
                <li>messageId = "742853CB-9E08-B9B2-3637-07521BD5E837"</li>
                <li>
                result = mx.collections.ArrayCollection (@9334701)
                <ul>
                <li>
                [0] = Object (@931b2c1)
                <ul>
                <li>callbacks = Array (@9334071)
                <ul>
                <li>
                [0] = Object (@931b221)
                <ul>
                <li>identifier = 1 [0x1]</li>
                <li>implementation = com.imagemaker.olimpo.contacto.vo.EmpresaVO (@92d5449)
                <ul>
                <li>direccion = "Hernando de Aguirre 268 of. 502"</li>
                <li>id = 1 [0x1]</li>
                <li>nombre = "Imagemaker IT"</li>
                <li>rut = null</li>
                </ul>
                </li>
                <li>session = Object (@92e6b41)</li>
                </ul>
                </li>
                <li>length = 1 [0x1]</li>
                </ul>
                <li>direccion = "Hernando de Aguirre 268 of. 502"</li>
                <li>id = 1 [0x1]</li>
                <li>nombre = "Imagemaker IT"</li>
                <li>rut = null</li>
                </ul>
                </li>
                <li>[1] = Object (@92e6201)</li>
                <li>[2] = com.imagemaker.olimpo.contacto.vo.EmpresaVO (@92d58a9)</li>
                <li>filterFunction = null</li>
                <li>length = 3 [0x3]</li>
                <li>list = mx.collections.ArrayList (@8f6c201)</li>
                <li>sort = null</li>
                <li>source = Array (@9334761)</li>
                </ul>
                </li>
                <li>target = null</li>
                <li>token = mx.rpc.AsyncToken (@92e21a1)</li>
                <li>type = "result"</li>
                </ul>
                </li>
                </ul>
                You can notice that not all of my instances are transformed to EmpresaVO, but inside callbacks they are.

                Why is that?

                May be this could help to figure this out.

                thanks,

                Lee
                • 5. Re: Java to Actionscript conversion problem
                  Any notice about this issue?

                  Lee O´neal
                  • 6. Re: Java to Actionscript conversion problem
                    seth_hodgson Level 1
                    Hi Lee,

                    What does the contactos property of an EmpressaVO contain? Other EmpressaVOs?

                    Seth
                    • 7. Re: Java to Actionscript conversion problem
                      seth_hodgson Level 1
                      So it turns out the problem was due to Lee's use of Hibernate from within his remote object implementation. Hibernate optionally uses CGLib to generate proxy classes to wrap your domain classes, and this is how it does lazy loading and keeps track of dirty fields and changes in the relationships between associated object instances. The problem is that the proxies generated by Hibernate cannot be registered on the client using [RemoteClass..] metadata.

                      Here's a snippet from Lee's log:
                      [0] = (Typed Object #4 'com.imagemaker.olimpo.beans.Empresa$$EnhancerByCGLIB$$df39c9ea')

                      The class name gen'ed by Hibernate is: Empresa$$EnhancerByCGLIB$$df39c9ea

                      So when it reaches the client it is deserialized as an anonymous Object because there's no registered AS class that correlates.

                      Here's more detail along with suggestions to resolve this courtesy of Jeff:


                      We ran into this problem with the HibernateAssembler used by the Data Management Services. The issue is that by default, hibernate creates a sub-class of your VO which it generates using CGLIB. This class overrides any “getX” method for an association property to first fetch that value before returning it. This is hibernate’s “lazy loading” feature.

                      The class name of the VO is being sent over and so this is likely not matching your RemoteClass alias on the client side. This thing also has other properties like the implementation and probably some stuff which is not serializable.

                      I think that there is a way to turn of the use of CGLIB proxies in hibernate though I don’t know the exact configuration. This would be one way to workaround the problem. In the hibernate assembler, we register a class called the HiberatePropertyProxy for any objects encountered in the AMF stream which implement the HibernateProxy interface. In this case, the proxy object is used to unwrap and send the original instance instead of sending the proxy. You can also just unwrap the proxy before sending it to us with:

                      return ((HibernateProxy)instance).getHibernateLazyInitializer().getImplementation();

                      One issue is that for any association properties you have (i.e. references to other objects), you’ll need to make sure those instances have been fetched before your transaction is closed.

                      The code for the hibernate assembler is included in the product in:

                      .../fds2/resources/samples/assemblers/flex-messaging-dist-src.zip

                      Another option is to just use the hibernate assembler instead of using remote object and we’ll take care of this for you.

                      Jeff