-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: hibernate objects over RMI-IIOP
PostPosted: Thu Aug 04, 2005 4:06 am 
Newbie

Joined: Wed Nov 17, 2004 1:06 pm
Posts: 4
Hi,

We are developing an app that exposes several EJB over RMI-IIOP. We are using hibernate 2.1 for persistence, so the return value for the EJBs are objects retrieved with hibernate.

The problem is that the objects retrieved with hibernate uses is own Collections implementation classes (net.sf.hibernate.collection.*) and other helper classes (net.sf.hibernate.impl.SessionImpl$CollectionEntry).

When the EJB client tries to invoke the EJB methods it throws ClassNotFoundException for the hibernate classes that get marshalled with the return value.

To make it worst, one of the clients is an app no developed by us, that uses hibernate itself, but with a diferent version, so instead of a ClassNotFoundException it gets a

java.io.InvalidClassException: net.sf.hibernate.impl.SessionImpl$CollectionEntry; local class incompatible: stream classdesc serialVersionUID = -2218466429640624909, local class serialVersionUID = -447926591643750087

The question is: Is there any way to "clean" the objects retrieved with hibernate to remove any references to hibernate classes?

Are there any docs that describe the classes that one should be aware off if trying to "clean" an object retrieved with hibernate?

Thanks.

_________________
-- Antoni Reus


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 04, 2005 9:53 am 
Regular
Regular

Joined: Wed May 11, 2005 11:57 pm
Posts: 80
Here's some verbatim code (may have non-applicable sections) that we used to accomplish this. As you can see from the fix comments, it's still a work in progress:

Code:
   private static Object processJavaBean( Object bean ) {
      try {
         BeanInfo beanInfo = Introspector.getBeanInfo( bean.getClass() );
         PropertyDescriptor[] properties = beanInfo.getPropertyDescriptors();
         Class propertyType;
         for( int n=0; n<properties.length; n++ ) {
            propertyType = properties[n].getPropertyType();
            if( Collection.class.isAssignableFrom(propertyType) ) {
               List hibernateList = (List)properties[n].getReadMethod().invoke( bean, new Object[0] ); //FIX!! What do we do with this?
               ListLoader loader = null;
               try {
                  loader = new ListLoaderImpl(hibernateList);
               } catch (RemoteException e) {
                  e.printStackTrace();
               }
               List replacementList = new LazyList( loader );
               properties[n].getWriteMethod().invoke( bean, new Object[] { replacementList } ); //FIX!!! Just a temporary test
            }
         }
         return bean;
      } catch( IntrospectionException e ) {
         throw new RuntimeException( e );
      } catch( IllegalAccessException e ) {
         throw new RuntimeException( e );
      } catch( InvocationTargetException e ) {
         throw new RuntimeException( e );
      }
   }


Top
 Profile  
 
 Post subject: some kind of solution
PostPosted: Fri Aug 05, 2005 7:37 am 
Newbie

Joined: Wed Nov 17, 2004 1:06 pm
Posts: 4
I extended your code, and made this that works for me.

- I replaces hibernate List, Set and Map for java.util. ones.
- Processes recursively all initialized objects.
- For uninitailized objects returns an instance of the object original class with only the identifier property set.

Limitations:
- It lacks processing of hibernate Arrays (I don't have any one in my mappings)
- All my persistent objects implement the "tag" interface ValueObject (no methods), so I used it to control which classes need to be processed.
- It's a crap.

A good enhancement for hibernate could be to implement this behaviour with the serialization methods readResolve and writeReplace in PersistentCollection and HibernateProxy, when a config property (say clean_on_serialize) is set.


Code:
    private static final Log log = LogFactory.getLog(HBUtils.class);

    /**
     * Procesa un bean eliminando las referencias a classes Hibernate.
     * @param bean Objeto a procesar.
     */
    public static void processHibernatedBean(final Object bean, final Session session) {
        processHibernatedBean(bean, new HashSet(), session);
    }

    private static void processHibernatedBean(final Object bean, final Set processed, final Session session) {
        if (processed.contains(bean)) {
            return;
        } else {
            try {
                session.evict(bean);
            } catch (HibernateException e) {
                log.warn("Error a session.evict",e);
            }
            processed.add(bean);
        }
        final BeanInfo beanInfo = getBeanInfo(bean.getClass());
        if (beanInfo == null) return;
        final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (int i = 0; i < propertyDescriptors.length; i++) {
            final PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
            final Class type = propertyDescriptor.getPropertyType();
            Object value;
            try {
                value = propertyDescriptor.getReadMethod().invoke(bean, new Object[0]);
            } catch (Exception e) {
                log.warn("Error leyendo propiedad", e);
                value = null;
            }
            if (value != null) {
                final Class clazz = value.getClass();
                if ((Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)) && clazz.getName().startsWith("net.sf.hibernate")) {

                    final Object newValue;
                    final boolean inicialitzat = Hibernate.isInitialized(value);
                    switch (getCollectionType(clazz)) {
                        case TYPE_LIST:
                            newValue = inicialitzat ? new LinkedList((Collection) value) : Collections.EMPTY_LIST;
                            break;
                        case TYPE_SET:
                            newValue = inicialitzat ? new HashSet((Collection) value) : Collections.EMPTY_SET;
                            break;
                        case TYPE_MAP:
                            newValue = inicialitzat ? new HashMap((Map) value) : Collections.EMPTY_MAP;
                            break;
                        default:
                            log.info("Tipus desconegut? " + clazz.getName());
                            newValue = null;
                            break;
                    }
                    try {
                        propertyDescriptor.getWriteMethod().invoke(bean, new Object[]{newValue});
                    } catch (Exception e) {
                        log.warn("Error fijando propiedad", e);
                    }
                    if (inicialitzat) {
                        Collection values = Collection.class.isAssignableFrom(type) ? (Collection) newValue : ((Map) newValue).values();
                        for (Iterator iterator = values.iterator(); iterator.hasNext();) {
                            final Object o = iterator.next();
                            if (o != null) {
                                if (ValueObject.class.isAssignableFrom(o.getClass())) {
                                    processHibernatedBean(o, processed, session);
                                }
                            }
                        }
                    }
                } else if (ValueObject.class.isAssignableFrom(type)) {
                    if (Hibernate.isInitialized(value)) {
                        processHibernatedBean(value, processed, session);
                    } else {
                        Object newValue = null;
                        try {
                            Class newClazz = HibernateProxyHelper.getClass(value);
                            newValue = newClazz.newInstance();
                            ClassMetadata clazzMetaData = session.getSessionFactory().getClassMetadata(newClazz);
                            Serializable id = clazzMetaData.getIdentifier(value);
                            clazzMetaData.setIdentifier(newValue, id);
                        } catch (Exception e) {
                            log.warn("Error intentant recrear lazy", e);
                        }
                        try {
                            propertyDescriptor.getWriteMethod().invoke(bean, new Object[] {newValue});
                        } catch (Exception e) {
                            log.warn("Error fijando propiedad", e);
                        }
                    }
                }
            }
        }
    }

    private static final int TYPE_LIST = 1;
    private static final int TYPE_SET = 2;
    private static final int TYPE_MAP = 3;
    private static final int TYPE_UNKNOWN = 4;

    private static int getCollectionType(final Class clazz) {
        if (List.class.isAssignableFrom(clazz)) {
            return TYPE_LIST;
        } else if (Set.class.isAssignableFrom(clazz)) {
            return TYPE_SET;
        } else if (Map.class.isAssignableFrom(clazz)) {
            return TYPE_MAP;
        }
        return TYPE_UNKNOWN;
    }

    private static final Map beanInfoMap = new HashMap();

    private static BeanInfo getBeanInfo(final Class clazz) {
        if (!beanInfoMap.containsKey(clazz)) {
            try {
                final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
                beanInfoMap.put(clazz, beanInfo);
                return beanInfo;
            } catch (IntrospectionException e) {
                log.warn("Error en getBeanInfo()", e);
                return null;
            }
        } else {
            return (BeanInfo) beanInfoMap.get(clazz);
        }
    }

_________________
-- Antoni Reus


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.