[seam-commits] Seam SVN: r7710 - in trunk/src/main/org/jboss/seam: util and 1 other directory.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Wed Mar 26 13:50:29 EDT 2008


Author: pete.muir at jboss.org
Date: 2008-03-26 13:50:29 -0400 (Wed, 26 Mar 2008)
New Revision: 7710

Added:
   trunk/src/main/org/jboss/seam/persistence/AbstractPersistenceProvider.java
   trunk/src/main/org/jboss/seam/persistence/JpaPersistenceProvider.java
Modified:
   trunk/src/main/org/jboss/seam/persistence/EntityManagerProxy.java
   trunk/src/main/org/jboss/seam/persistence/HibernatePersistenceProvider.java
   trunk/src/main/org/jboss/seam/persistence/PersistenceProvider.java
   trunk/src/main/org/jboss/seam/util/Reflections.java
Log:
First pass at runtime persistence provider detection

Added: trunk/src/main/org/jboss/seam/persistence/AbstractPersistenceProvider.java
===================================================================
--- trunk/src/main/org/jboss/seam/persistence/AbstractPersistenceProvider.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/persistence/AbstractPersistenceProvider.java	2008-03-26 17:50:29 UTC (rev 7710)
@@ -0,0 +1,147 @@
+package org.jboss.seam.persistence;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import javax.persistence.EntityManager;
+import javax.persistence.OptimisticLockException;
+import javax.transaction.Synchronization;
+
+import org.jboss.seam.Entity;
+
+/**
+ * Provides a default implementation of PersistenceProvider methods where possible
+ * 
+ * Other methods must be implemented
+ * 
+ * @author Pete Muir
+ *
+ */
+public abstract class AbstractPersistenceProvider
+{
+
+   /**
+    *  Set the flush mode to manual-only flushing. Called when
+    *  an atomic persistence context is required.
+    */
+   public abstract void setFlushModeManual(EntityManager entityManager);
+
+   /**
+    * Does the persistence context have unflushed changes? If
+    * it does not, persistence context replication can be
+    * optimized.
+    * 
+    * @return true to indicate that there are unflushed changes
+    */
+   public abstract boolean isDirty(EntityManager entityManager);
+
+   /**
+    * Get the value of the entity identifier attribute.
+    * 
+    * @param bean a managed entity instance
+    */
+   public Object getId(Object bean, EntityManager entityManager)
+   {
+      return Entity.forClass( bean.getClass() ).getIdentifier(bean);
+   }
+
+   /**
+    * Get the name of the entity
+    * 
+    * @param bean
+    * @param entityManager
+    * 
+    * @throws IllegalArgumentException if the passed object is not an entity
+    */
+   public String getName(Object bean, EntityManager entityManager) throws IllegalArgumentException
+   {
+      return Entity.forClass(bean.getClass()).getName();
+   }
+
+   /**
+    * Get the value of the entity version attribute.
+    * 
+    * @param bean a managed entity instance
+    */
+   public Object getVersion(Object bean, EntityManager entityManager)
+   {
+      return Entity.forClass( bean.getClass() ).getVersion(bean);
+   }
+
+   public void checkVersion(Object bean, EntityManager entityManager, Object oldVersion, Object version)
+   {
+      boolean equal;
+      if (oldVersion instanceof Date)
+      {
+         equal = ( (Date) oldVersion ).getTime() == ( (Date) version ).getTime();
+      }
+      else
+      {
+         equal = oldVersion.equals(version);
+      }
+      if ( !equal )
+      {
+         throw new OptimisticLockException("current database version number does not match passivated version number");
+      }
+   }
+
+   /**
+    * Enable a Filter. This is here just especially for Hibernate,
+    * since we well know that other products don't have such cool
+    * features. 
+    */
+   public abstract void enableFilter(Filter filter, EntityManager entityManager);
+
+   /**
+    * Register a Synchronization with the current transaction.
+    */
+   public abstract boolean registerSynchronization(Synchronization sync, EntityManager entityManager);
+
+   /**
+    * Wrap the delegate before returning it to the application
+    */
+   public Object proxyDelegate(Object delegate)
+   {
+      return delegate;
+   }
+
+   /**
+    * Wrap the entityManager before returning it to the application
+    */
+   public EntityManager proxyEntityManager(EntityManager entityManager)
+   {
+      return new EntityManagerProxy(entityManager);
+   }
+
+   /**
+    * Returns the class of an entity bean instance
+    * 
+    * @param bean The entity bean instance
+    * @return The class of the entity bean
+    */
+   public Class getBeanClass(Object bean)
+   {
+      return Entity.forClass(bean.getClass()).getBeanClass();
+   }
+
+   public Method getPostLoadMethod(Class beanClass, EntityManager entityManager)
+   {
+      return Entity.forClass(beanClass).getPostLoadMethod();      
+   }
+
+   public Method getPrePersistMethod(Class beanClass, EntityManager entityManager)
+   {
+      return Entity.forClass(beanClass).getPrePersistMethod();
+   }
+
+   public Method getPreUpdateMethod(Class beanClass, EntityManager entityManager)
+   {
+      return Entity.forClass(beanClass).getPreUpdateMethod();
+   }
+
+   public Method getPreRemoveMethod(Class beanClass, EntityManager entityManager)
+   {
+      return Entity.forClass(beanClass).getPreRemoveMethod();
+   }
+
+}
\ No newline at end of file


Property changes on: trunk/src/main/org/jboss/seam/persistence/AbstractPersistenceProvider.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/src/main/org/jboss/seam/persistence/EntityManagerProxy.java
===================================================================
--- trunk/src/main/org/jboss/seam/persistence/EntityManagerProxy.java	2008-03-26 15:27:37 UTC (rev 7709)
+++ trunk/src/main/org/jboss/seam/persistence/EntityManagerProxy.java	2008-03-26 17:50:29 UTC (rev 7710)
@@ -92,7 +92,7 @@
 
    public Object getDelegate()
    {
-      return PersistenceProvider.instance().proxyDelegate( delegate.getDelegate() );
+      return PersistenceProvider.instance().proxyDelegate( delegate, delegate.getDelegate() );
    }
 
    public FlushModeType getFlushMode()

Modified: trunk/src/main/org/jboss/seam/persistence/HibernatePersistenceProvider.java
===================================================================
--- trunk/src/main/org/jboss/seam/persistence/HibernatePersistenceProvider.java	2008-03-26 15:27:37 UTC (rev 7709)
+++ trunk/src/main/org/jboss/seam/persistence/HibernatePersistenceProvider.java	2008-03-26 17:50:29 UTC (rev 7710)
@@ -1,4 +1,5 @@
 package org.jboss.seam.persistence;
+import static org.jboss.seam.ScopeType.STATELESS;
 import static org.jboss.seam.annotations.Install.FRAMEWORK;
 
 import java.lang.reflect.Constructor;
@@ -23,6 +24,7 @@
 import org.hibernate.event.PostLoadEventListener;
 import org.hibernate.metadata.ClassMetadata;
 import org.hibernate.type.VersionType;
+import org.jboss.seam.Component;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.Seam;
 import org.jboss.seam.annotations.Install;
@@ -40,11 +42,11 @@
  * @author Pete Muir
  *
  */
- at Name("org.jboss.seam.persistence.persistenceProvider")
+ at Name("org.jboss.seam.persistence.hibernatePersistenceProvider")
 @Scope(ScopeType.STATELESS)
 @BypassInterceptors
 @Install(precedence=FRAMEWORK, classDependencies={"org.hibernate.Session", "javax.persistence.EntityManager"})
-public class HibernatePersistenceProvider extends PersistenceProvider
+public class HibernatePersistenceProvider extends AbstractPersistenceProvider
 {
    
    private static Log log = Logging.getLog(HibernatePersistenceProvider.class);
@@ -121,10 +123,6 @@
       {
          return proxySession( (Session) delegate );
       }
-      catch (NotHibernateException nhe)
-      {
-         return super.proxyDelegate(delegate);
-      }
       catch (Exception e)
       {
          throw new RuntimeException("could not proxy delegate", e);
@@ -134,27 +132,13 @@
    @Override
    public void setFlushModeManual(EntityManager entityManager)
    {
-       try
-       {
-          getSession(entityManager).setFlushMode(FlushMode.MANUAL);
-       }
-       catch (NotHibernateException nhe)
-       {
-          super.setFlushModeManual(entityManager);
-       }
+       getSession(entityManager).setFlushMode(FlushMode.MANUAL);
    }
    
    @Override
    public boolean isDirty(EntityManager entityManager)
    {
-       try
-       {
-          return getSession(entityManager).isDirty();
-       }
-       catch (NotHibernateException nhe)
-       {
-          return super.isDirty(entityManager);
-       }
+       return getSession(entityManager).isDirty();
    }
    
    @Override
@@ -164,10 +148,6 @@
        {
           return getSession(entityManager).getIdentifier(bean);
        }
-       catch (NotHibernateException nhe)
-       {
-          return super.getId(bean, entityManager);
-       }
        catch (TransientObjectException e) 
        {
           return super.getId(bean, entityManager);
@@ -177,63 +157,32 @@
    @Override
    public Object getVersion(Object bean, EntityManager entityManager) 
    {
-       try
-       {
-          return getVersion( bean, getSession(entityManager) );
-       }
-       catch (NotHibernateException nhe)
-       {
-          return super.getVersion(bean, entityManager);
-       }
+       return getVersion( bean, getSession(entityManager) );
    }
    
    @Override
    public void checkVersion(Object bean, EntityManager entityManager, Object oldVersion, Object version)
    {
-       try
-       {
-          checkVersion(bean, getSession(entityManager), oldVersion, version);
-       }
-       catch (NotHibernateException nhe)
-       {
-          super.checkVersion(bean, entityManager, oldVersion, version);
-       }
+       checkVersion(bean, getSession(entityManager), oldVersion, version);
    }
    
    @Override
    public void enableFilter(Filter f, EntityManager entityManager)
    {
-      try
+      org.hibernate.Filter filter = getSession(entityManager).enableFilter( f.getName() );
+      for ( Map.Entry<String, ValueExpression> me: f.getParameters().entrySet() )
       {
-         org.hibernate.Filter filter = getSession(entityManager).enableFilter( f.getName() );
-         for ( Map.Entry<String, ValueExpression> me: f.getParameters().entrySet() )
-         {
-            filter.setParameter( me.getKey(), me.getValue().getValue() );
-         }
-         filter.validate();
+         filter.setParameter( me.getKey(), me.getValue().getValue() );
       }
-      catch (NotHibernateException nhe)
-      {
-         super.enableFilter(f, entityManager);
-      }
-
    }
    
    @Override
    public boolean registerSynchronization(Synchronization sync, EntityManager entityManager)
    {
-      try
-      {
-         //TODO: just make sure that a Hibernate JPA EntityTransaction
-         //      delegates to the Hibernate Session transaction
-         getSession(entityManager).getTransaction().registerSynchronization(sync);
-         return true;
-      }
-      catch (NotHibernateException nhe)
-      {
-         return super.registerSynchronization(sync, entityManager);
-      }
-
+      //TODO: just make sure that a Hibernate JPA EntityTransaction
+      //      delegates to the Hibernate Session transaction
+      getSession(entityManager).getTransaction().registerSynchronization(sync);
+      return true;
    }
 
    @Override
@@ -243,10 +192,6 @@
       {
          return getSession(entityManager).getEntityName(bean);
       } 
-      catch (NotHibernateException nhe)
-      {
-         return super.getName(bean, entityManager);
-      }
       catch (TransientObjectException e) 
       {
          return super.getName(bean, entityManager);
@@ -424,23 +369,12 @@
    
    private Session getSession(EntityManager entityManager)
    {
-      Object delegate = entityManager.getDelegate();
-      if ( delegate instanceof Session )
-      {
-         return (Session) delegate;
-      }
-      else
-      {
-         throw new NotHibernateException();
-      }
+      return (Session) entityManager.getDelegate(); 
    }
    
-   /**
-    * Occurs when Hibernate is in the classpath, but this particular
-    * EntityManager is not from Hibernate
-    * 
-    * @author Gavin King
-    *
-    */
-   static class NotHibernateException extends IllegalArgumentException {}
+   public static HibernatePersistenceProvider instance()
+   {
+      return (HibernatePersistenceProvider) Component.getInstance(HibernatePersistenceProvider.class, STATELESS);
+   }
+   
 }

Added: trunk/src/main/org/jboss/seam/persistence/JpaPersistenceProvider.java
===================================================================
--- trunk/src/main/org/jboss/seam/persistence/JpaPersistenceProvider.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/persistence/JpaPersistenceProvider.java	2008-03-26 17:50:29 UTC (rev 7710)
@@ -0,0 +1,59 @@
+package org.jboss.seam.persistence;
+
+import static org.jboss.seam.ScopeType.STATELESS;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import javax.persistence.EntityManager;
+import javax.transaction.Synchronization;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+
+/**
+ * PersistenceProvider for any JPA implementation. Many methods are unusable
+ * or use naive implementations
+ * 
+ * @author Gavin King
+ * @author Pete Muir
+ *
+ */
+ at Name("org.jboss.seam.persistence.jpaPersistenceProvider")
+ at Scope(STATELESS)
+ at BypassInterceptors
+ at Install(precedence=BUILT_IN, classDependencies="javax.persistence.EntityManager")
+public class JpaPersistenceProvider extends AbstractPersistenceProvider
+{
+
+   @Override
+   public void enableFilter(Filter filter, EntityManager entityManager)
+   {
+      throw new UnsupportedOperationException("You must use Hibernate to use Filters");
+   }
+
+   @Override
+   public boolean isDirty(EntityManager entityManager)
+   {
+      return true;
+   }
+
+   @Override
+   public boolean registerSynchronization(Synchronization sync, EntityManager entityManager)
+   {
+      return false;
+   }
+
+   @Override
+   public void setFlushModeManual(EntityManager entityManager)
+   {
+      throw new UnsupportedOperationException("You must use Hibernate to use Manual Flush Mode");
+   }
+   
+   public static JpaPersistenceProvider instance()
+   {
+      return (JpaPersistenceProvider) Component.getInstance(JpaPersistenceProvider.class, STATELESS);
+   }
+   
+}


Property changes on: trunk/src/main/org/jboss/seam/persistence/JpaPersistenceProvider.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/src/main/org/jboss/seam/persistence/PersistenceProvider.java
===================================================================
--- trunk/src/main/org/jboss/seam/persistence/PersistenceProvider.java	2008-03-26 15:27:37 UTC (rev 7709)
+++ trunk/src/main/org/jboss/seam/persistence/PersistenceProvider.java	2008-03-26 17:50:29 UTC (rev 7710)
@@ -1,11 +1,10 @@
 package org.jboss.seam.persistence;
 import static org.jboss.seam.annotations.Install.BUILT_IN;
+import static org.jboss.seam.util.Reflections.isInstanceOf;
 
 import java.lang.reflect.Method;
-import java.util.Date;
 
 import javax.persistence.EntityManager;
-import javax.persistence.OptimisticLockException;
 import javax.transaction.Synchronization;
 
 import org.jboss.seam.Component;
@@ -17,9 +16,8 @@
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
 /**
  * Abstraction layer for persistence providers (JPA implementations).
- * This class provides a working base implementation that can be
- * optimized for performance and non-standardized features by extending
- * and overriding the methods. 
+ * This class delegates to either the generic JpaPersistenceProvider or a more
+ * specific one if available.
  * 
  * The methods on this class are a great todo list for the next rev
  * of the JPA spec ;-)
@@ -40,7 +38,7 @@
     */
    public void setFlushModeManual(EntityManager entityManager)
    {
-      throw new UnsupportedOperationException("For use of FlushMode.MANUAL, please use Hibernate as the persistence provider or use a custom PersistenceProvider");
+      getPersistenceProvider(entityManager).setFlushModeManual(entityManager);
    }
    /**
     * Does the persistence context have unflushed changes? If
@@ -51,7 +49,7 @@
     */
    public boolean isDirty(EntityManager entityManager)
    {
-      return true; //best we can do!
+      return getPersistenceProvider(entityManager).isDirty(entityManager);
    }
    
    /**
@@ -61,7 +59,7 @@
     */
    public Object getId(Object bean, EntityManager entityManager)
    {
-      return Entity.forClass( bean.getClass() ).getIdentifier(bean);
+      return getPersistenceProvider(entityManager).getId(bean, entityManager);
    }
    
    /**
@@ -74,7 +72,7 @@
     */
    public String getName(Object bean, EntityManager entityManager) throws IllegalArgumentException
    {
-      return Entity.forClass(bean.getClass()).getName();
+      return getPersistenceProvider(entityManager).getName(bean, entityManager);
    }
    
    /**
@@ -84,24 +82,12 @@
     */
    public Object getVersion(Object bean, EntityManager entityManager)
    {
-      return Entity.forClass( bean.getClass() ).getVersion(bean);
+      return getPersistenceProvider(entityManager).getVersion(bean, entityManager);
    }
    
    public void checkVersion(Object bean, EntityManager entityManager, Object oldVersion, Object version)
    {
-      boolean equal;
-      if (oldVersion instanceof Date)
-      {
-         equal = ( (Date) oldVersion ).getTime() == ( (Date) version ).getTime();
-      }
-      else
-      {
-         equal = oldVersion.equals(version);
-      }
-      if ( !equal )
-      {
-         throw new OptimisticLockException("current database version number does not match passivated version number");
-      }
+      getPersistenceProvider(entityManager).checkVersion(bean, entityManager, oldVersion, version);
    }
    /**
     * Enable a Filter. This is here just especially for Hibernate,
@@ -110,7 +96,7 @@
     */
    public void enableFilter(Filter filter, EntityManager entityManager)
    {
-      throw new UnsupportedOperationException("For filters, please use Hibernate as the persistence provider");
+      getPersistenceProvider(entityManager).enableFilter(filter, entityManager);
    }
    
    /**
@@ -118,7 +104,7 @@
     */
    public boolean registerSynchronization(Synchronization sync, EntityManager entityManager)
    {
-      return false; //best we can do!
+      return getPersistenceProvider(entityManager).registerSynchronization(sync, entityManager);
    }
    
    public static PersistenceProvider instance()
@@ -129,15 +115,22 @@
    /**
     * Wrap the delegate before returning it to the application
     */
+   @Deprecated
    public Object proxyDelegate(Object delegate)
    {
-      return delegate;
+      return getPersistenceProvider(delegate).proxyDelegate(delegate);
    }
+   
+   public Object proxyDelegate(EntityManager entityManager, Object delegate)
+   {
+      return getPersistenceProvider(entityManager).proxyDelegate(delegate);
+   }
+   
    /**
     * Wrap the entityManager before returning it to the application
     */
    public EntityManager proxyEntityManager(EntityManager entityManager) {
-      return new EntityManagerProxy(entityManager);
+      return getPersistenceProvider(entityManager).proxyEntityManager(entityManager);
    }
    
    /**
@@ -146,29 +139,71 @@
     * @param bean The entity bean instance
     * @return The class of the entity bean
     */
+   @Deprecated
    public Class getBeanClass(Object bean)
    {
       return Entity.forClass(bean.getClass()).getBeanClass();
    }
    
+   public Class getBeanClass(EntityManager entityManager, Object bean)
+   {
+      return getPersistenceProvider(entityManager).getBeanClass(bean);
+   }
+   
    public Method getPostLoadMethod(Class beanClass, EntityManager entityManager)
    {
-      return Entity.forClass(beanClass).getPostLoadMethod();      
+      return getPersistenceProvider(entityManager).getPostLoadMethod(beanClass, entityManager);     
    }
    
    public Method getPrePersistMethod(Class beanClass, EntityManager entityManager)
    {
-      return Entity.forClass(beanClass).getPrePersistMethod();
+      return getPersistenceProvider(entityManager).getPrePersistMethod(beanClass, entityManager);
    }
    
    public Method getPreUpdateMethod(Class beanClass, EntityManager entityManager)
    {
-      return Entity.forClass(beanClass).getPreUpdateMethod();
+      return getPersistenceProvider(entityManager).getPreUpdateMethod(beanClass, entityManager);
    }
    
    public Method getPreRemoveMethod(Class beanClass, EntityManager entityManager)
    {
-      return Entity.forClass(beanClass).getPreRemoveMethod();
+      return getPersistenceProvider(entityManager).getPreRemoveMethod(beanClass, entityManager);
    }
    
+   /**
+    * Do runtime detection of PersistenceProvider
+    */
+   private AbstractPersistenceProvider getPersistenceProvider(EntityManager entityManager)
+   {
+      // Work around EJBTHREE-912 (don't you just love random NPEs!)
+      if (isInstanceOf(entityManager.getClass(), "org.jboss.ejb3.entity.HibernateSession"))
+      {
+         return HibernatePersistenceProvider.instance();
+      }
+      else if(isInstanceOf(entityManager.getDelegate().getClass(), "org.hibernate.Session"))
+      {
+         return HibernatePersistenceProvider.instance();
+      }
+      else
+      {
+         return JpaPersistenceProvider.instance();
+      }
+   }
+   
+   /**
+    * Do runtime detection of PersistenceProvider
+    */
+   @Deprecated
+   private AbstractPersistenceProvider getPersistenceProvider(Object delegate)
+   {
+      if (isInstanceOf(delegate.getClass(), "org.hibernate.Session"))
+      {
+         return HibernatePersistenceProvider.instance();
+      }
+      else
+      {
+         return JpaPersistenceProvider.instance();
+      }
+   }
+   
 }

Modified: trunk/src/main/org/jboss/seam/util/Reflections.java
===================================================================
--- trunk/src/main/org/jboss/seam/util/Reflections.java	2008-03-26 15:27:37 UTC (rev 7709)
+++ trunk/src/main/org/jboss/seam/util/Reflections.java	2008-03-26 17:50:29 UTC (rev 7710)
@@ -326,19 +326,31 @@
       }
       for (Class c = clazz; c != Object.class; c = c.getSuperclass())
       {
-         if (name.equals(c.getName()))
+         if (instanceOf(c, name))
          {
             return true;
          }
       }
-      for (Class c : clazz.getInterfaces())
+      return false;
+   }
+   
+   private static boolean instanceOf(Class clazz, String name)
+   {  
+      if (name.equals(clazz.getName()))
       {
-         if (name.equals(c.getName()))
+         return true;
+      }
+      else
+      {
+         boolean found = false;
+         Class[] interfaces = clazz.getInterfaces();
+         for (int i = 0; i < interfaces.length && !found; i++)
          {
-            return true;
+            found = instanceOf(interfaces[i], name);
          }
+         return found;
       }
-      return false;
+      
    }
 
 }




More information about the seam-commits mailing list