anonymous wrote : Which got me to thinking.  Why, if we're using EJB3 to manage 
our POJO Entities, it is acceptable to return an object with Hibernate classes 
to the client in the first place?  JBoss itself is requiring EJB3 clients to 
know Hibernate's involved?!  Shouldn't the container be removing all of that 
stuff for us once the object leaves the session/transaction?  Then Hibernate 
would be completely transparent as the storage mechanism for CMP, and the 
application wouldn't need to know anything about it.

I agree that was one of my main points - Is a Pojo really a Pojo if its depends 
on specific 3rd party classes?  Not in my book its not.


I've removed the @Entity requirement as we don't actually care if the object is 
an entity or not, its only the presence of PersistentCollection members that we 
must check for, and we can only do that by checking each field or each object.
I've kept a check to eleminate classes that are definitely not going to contain 
PersistentCollection fields for performance reasons.

This new implementation allows us to recurse any object graph looking for 
PersistentCollection fields that might be hidden within it, as long as they are 
accessible via a get* method.

package org.hibernate.collection;
  | 
  | import java.lang.reflect.InvocationTargetException;
  | import java.util.ArrayList;
  | import java.util.Collection;
  | import java.util.Map;
  | 
  | import org.apache.commons.beanutils.PropertyUtils;
  | import org.hibernate.LazyInitializationException;
  | 
  | /**
  |  * Some utils methods to get a complete clean POJO from an entity bean with 
hibernate specific 
  |  * fields stripped out. Note this class is not meant as a way of avoid 
LazyInitializationException's.  
  |  * Its purpose to strip out data before sending the object to a remote 
client so that does not have 
  |  * knowledge of hibernate classes. 
  |  * @author ALR 5/9/2006
  |  * @author modified by James Adams 6/9/2006, 7/9/2006
  |  *
  |  */
  | public class HibernateCleaner {
  | 
  |     /**
  |      * Traverse through the object removing all fields of type 
org.hibernate.collection.PersistentCollection.
  |      * by following all bean style get* methods.
  |      * *Note* the object cannot be reattached after calling this method.
  |      * 
  |      * @param obj
  |      * @return obj with no PersistentCollection objects within it.
  |      */
  |     public static void clean(Object obj){           
  |             try {
  |                     removePersistenceContext(obj, new ArrayList<Integer>());
  |             } catch (IllegalAccessException e) {
  |                     throw new RuntimeException(e);
  |             } catch (InvocationTargetException e) {
  |                     throw new RuntimeException(e);
  |             } catch (NoSuchMethodException e) {
  |                     throw new RuntimeException(e);
  |             }
  |     }
  |     
  |     /**
  |      * Checks if the object MIGHT contain PersistentCollection fields by 
checking if its not a primative, or if its in package
  |      * java.* or javax.*.  **NOTE** - This relies on there not being an 
entity within those packages.
  |      * A more conservative aproach is to only check if its a primative.
  |      * @param obj
  |      * @author James Adams
  |      */
  |     public static boolean couldObjectContainPersistentCollections(Object 
obj){
  |             
  |             if(obj.getClass().isPrimitive()){ return false; }
  |             
  |             //TODO - This is not full proof and relys on people not using 
package with names below.  More conservative approach
  |             //is to remove this
  |             if(obj.getClass().getName().startsWith("java.") || 
obj.getClass().getName().startsWith("javax.")){
  |                     return false;
  |             }
  |             
  |             return true;    //If we got here it might be a hiberate 
persisted object
  |     }
  |     
  |     /**
  |      * 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
  |      * @author James Adams, modified 6/9/2006,7/9/2006
  |      * @throws NoSuchMethodException 
  |      * @throws InvocationTargetException 
  |      * @throws IllegalAccessException 
  |      */
  |     private static Object removePersistenceContext(Object obj, 
Collection<Integer> visitedObjectHashCodes) 
  |             throws IllegalAccessException, InvocationTargetException, 
NoSuchMethodException{
  |             if(obj==null){
  |                     return null;
  |             }
  | 
  |             
if(visitedObjectHashCodes.contains(System.identityHashCode(obj))){
  |                     return obj;
  |             }
  |             
  |             //Add the object's hash to the Collection of visited hash codes
  |             visitedObjectHashCodes.add(System.identityHashCode(obj));
  | 
  |             try{                    
  |                     // If runtime type of persistentCollection is 
PersistentCollection we get the inner collection
  |                     //from within the hibernate proxy
  |                     if ((obj instanceof PersistentCollection)){             
                
  |                             obj = 
getInnerCollection((PersistentCollection)obj);
  |                     }
  |             }catch(LazyInitializationException e){
  |                     return null;            
  |             }
  |             
  |             if(obj==null){
  |                     return null;
  |             }
  |             
  |             if(obj instanceof Collection){          
  |                     for(Object o : (Collection)obj){
  |                             //recurse into each element of the collection.  
We don't need to set the value 
  |                             //of the object in the Collection as the 
reference will be adjusted, doing so within this 
  |                             //iterable loop would result in a 
ConcurrentModificationException anyway. 
  |                             removePersistenceContext(o, 
visitedObjectHashCodes);
  |                             //TODO - Does Hibernate support Collections of 
primatives? As this will not work when the 
  |                             //Collection is of types that Java does not 
pass by reference; primatives, String, Integer, 
  |                             //Float etc.  In this case we need to create a 
new Collection and populate it. 
  |                     }
  |             }else if(!couldObjectContainPersistentCollections(obj) ){       
//we don't need to investigate all fields if its not an entity
  |                     return obj;
  |             }else{  
  |                     Map allMembers = PropertyUtils.describe(obj);
  |                     for(Object member : allMembers.entrySet()){
  |                             Map.Entry m = (Map.Entry)member;
  |                             try {
  |                                     try{
  |                                             PropertyUtils.setProperty(obj, 
m.getKey().toString(), removePersistenceContext(m.getValue(), 
visitedObjectHashCodes));                  
  |                                     }catch (LazyInitializationException e){
  |                                             PropertyUtils.setProperty(obj, 
m.getKey().toString(), null);
  |                                     }
  |                             } catch (IllegalAccessException e) {
  |                                     throw new RuntimeException(e);
  |                             } catch (InvocationTargetException e) {
  |                                     throw new RuntimeException(e);
  |                             } catch (NoSuchMethodException e) {             
                
  |                             }
  |                     }
  |             }
  |             return obj;
  |     }
  |     
  |     /**
  |      * Because this class is in package org.hibernate.collection this method
  |      * allows us to access the inner protected fields of the hibernate 
collections
  |      * @param obj
  |      * @return The inner collection object of the PersistentCollection 
parameter
  |      * @author James Adams
  |      */
  |     protected static Object getInnerCollection(PersistentCollection obj){
  |             if(obj instanceof PersistentBag){
  |                     return ((PersistentBag)obj).bag;
  |             }else if(obj instanceof PersistentList){
  |                     return ((PersistentList)obj).list;                      
  |             }else if(obj instanceof PersistentSet){
  |                     return ((PersistentSet)obj).set;                        
  |             }else if(obj instanceof PersistentMap){
  |                     return ((PersistentMap)obj).map;                        
  |             }else if(obj instanceof PersistentSortedMap){
  |                     return ((PersistentSortedMap)obj).map;                  
  |             }else if(obj instanceof PersistentSortedSet){
  |                     return ((PersistentSortedSet)obj).set;                  
  |             }else{
  |                     return null;
  |             }               
  |     }       
  |     
  | }
  | 

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3970058#3970058

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3970058
_______________________________________________
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to