-->
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.  [ 2 posts ] 
Author Message
 Post subject: Removing Hibernate Collections Impl from Detached POJO
PostPosted: Wed Sep 06, 2006 12:07 pm 
Newbie

Joined: Wed Sep 06, 2006 11:49 am
Posts: 5
Hi.

We've been discussing methods to send a managed entity to remote clients over in the JBoss EJB3 forum, and I was hoping for some feedback here on the proposed solutions we've been contemplating. Apologies in advance for the crosspost and lengthy thread. This started:

http://www.jboss.org/index.html?module=bb&op=viewtopic&t=89436

The issue is - because EJB3 Entities are POJOs, I'd like to use as a DTO/VO as well. The only barrier is in the managed collections and the LazyInitializationException that occurs when the remote client attempts to access associations outside the context of the initial transaction/session.

So I made a method that takes a Collection, and ensures that the Impl is in the standard Java Collections API (All code below). Additionally, I added a method to an Entity Base Class (which I call PersistedEntity) which, through reflection, ensures all internal members of the object are not Hibernate Collections, and if they are, replaces 'em.

Questions:

1) Is there a better way to send detached Hibernate objects for use outside of the session?
2) This approach seems to necessitate a Base Entity class from which all entities will extend. Is there a better way to make this a Utility method that accepts an entity of any type and does the same thing?

Code follows.

S,
ALR

PersistenceUtils.java - Utility Class

Code:
/**
    * Returns a Collection of all objects in the specified persistentCollection
    * without binding to any persistence context or session.
    *
    * @param <T>
    * @param targetCollection
    * @param persistentCollection
    * @return
    */
   public static <T> Collection<T> removeCollectionItemsFromPersistenceContext(
         Collection<T> targetCollection, Collection<T> persistentCollection) {
      // If runtime type of persistentCollection is not PersistentCollection,
      // take no action
      if (!(persistentCollection instanceof PersistentCollection))
         return persistentCollection;

      // Clear existing target
      targetCollection.clear();

      // Place all items in persistent collection into target
      for (T item : persistentCollection) {
         targetCollection.add(item);
      }

      // Return target
      return targetCollection;
   }


PersistedEntity.java - Base Entity Class

Code:
/**
    * Strips the entity of all data binding it to a specific persistence
    * context, leaving intact only model-centric data
    *
    * @author ALR
    */
   public void removePersistenceContext() {
      // Initialize
      Collection<Integer> visitedObjectHashCodes = new ArrayList<Integer>();

      // Run
      this.removePersistenceContext(this, visitedObjectHashCodes);
   }

   /**
    * If the specified object's identity hash code is not in the specified
    * collection of visited hash codes, removes of all data binding the object
    * (and its members) to a specific persistence context, leaving intact only
    * model-centric data
    *
    * @param visitedObjectHashCodes
    * @param obj
    * @author ALR
    */
   private Object removePersistenceContext(Object obj,
         Collection<Integer> visitedObjectHashCodes) {

      // Ensure the current object has not been visited
      if (visitedObjectHashCodes.contains(System.identityHashCode(obj))) {
         return obj;
      }

      // Add the current object's hash to the Collection of visited hash codes
      visitedObjectHashCodes.add(System.identityHashCode(obj));

      // If the current object is of type Collection
      if (Collection.class.isInstance(obj)) {
         // Remove persistence context
         obj = PersistenceUtils.removeCollectionItemsFromPersistenceContext(
               new ArrayList(), (Collection) obj);
      }

      // Only traverse into types of PersistedEntity
      if (!(PersistedEntity.class.isInstance(obj))) {
         return obj;
      }

      // Remove persistence context of all members
      Map allMembers = this.getInternalMembers();
      for (Object member : allMembers.entrySet()) {
         Map.Entry m = (Map.Entry) member;
         try {
            PropertyUtils.setProperty((Object) obj, m.getKey().toString(),
                  this.removePersistenceContext((m.getValue()),
                        visitedObjectHashCodes));
         } catch (IllegalAccessException e) {
            throw new ApplicationException(e);
         } catch (InvocationTargetException e) {
            throw new ApplicationException(e);
         } catch (NoSuchMethodException e) {
         }
      }

      // Return
      return obj;
   }

   // Internal Helper Methods
   /**
    * Returns a Map of all internal members of the specified object
    *
    * @param obj
    *            The object for which to obtain internal members
    *
    * @author ALR
    * @see http://jakarta.apache.org/commons/beanutils/
    */
   protected Map getInternalMembers(PersistedEntity obj) {
      try {
         // Return a map of all visible properties
         return PropertyUtils.describe(obj);
      }
      // Throw as unchecked exceptions up the stack trace
      catch (IllegalAccessException iae) {
         throw new ApplicationException(iae);
      } catch (NoSuchMethodException nsme) {
         throw new ApplicationException(nsme);
      } catch (InvocationTargetException ite) {
         throw new ApplicationException(ite);
      }
   }

   /**
    * Returns a Map of all internal members of this PersistedEntitys
    *
    * @author ALR
    * @see http://jakarta.apache.org/commons/beanutils/
    */
   protected Map getInternalMembers() {
      return getInternalMembers(this);
   }


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 20, 2007 5:23 am 
Regular
Regular

Joined: Thu Oct 13, 2005 4:19 am
Posts: 98
I am also in need of stripping the hibernate collections implementations before sending it to the client (in a different VM),
but I was hoping that there was a much easier solution, maybe a DetachIntercepter which can replace them by ArrayList etc.

_________________
http://www.ohloh.net/accounts/ge0ffrey


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.