[seam-commits] Seam SVN: r13555 - in modules/persistence/trunk: impl and 3 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Aug 5 06:07:06 EDT 2010


Author: swd847
Date: 2010-08-05 06:07:05 -0400 (Thu, 05 Aug 2010)
New Revision: 13555

Added:
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeManager.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeType.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/HibernatePersistenceProvider.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContext.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContexts.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceProvider.java
Modified:
   modules/persistence/trunk/impl/pom.xml
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/AbstractManagedPersistenceContextBeanLifecycle.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextExtension.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextProxyHandler.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContextProxyHandler.java
   modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/transaction/EntityTransaction.java
   modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionAttributeInterceptorTest.java
   modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionInterceptorTest.java
   modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionScopedTest.java
   modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/UserTransactionTest.java
   modules/persistence/trunk/pom.xml
Log:
port more stuff from seam 2, it compiles but needs to be tested



Modified: modules/persistence/trunk/impl/pom.xml
===================================================================
--- modules/persistence/trunk/impl/pom.xml	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/pom.xml	2010-08-05 10:07:05 UTC (rev 13555)
@@ -114,6 +114,13 @@
          <artifactId>arquillian-junit</artifactId>
          <scope>test</scope>
       </dependency>
+      
+      <dependency>
+         <groupId>org.hibernate</groupId>
+         <artifactId>hibernate-core</artifactId>
+         <scope>provided</scope>
+      </dependency>
+      
    </dependencies>
 
 

Modified: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/AbstractManagedPersistenceContextBeanLifecycle.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/AbstractManagedPersistenceContextBeanLifecycle.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/AbstractManagedPersistenceContextBeanLifecycle.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -44,7 +44,7 @@
 public abstract class AbstractManagedPersistenceContextBeanLifecycle implements BeanLifecycle<EntityManager>
 {
 
-   static final Class<?> proxyClass = Proxy.getProxyClass(EntityManager.class.getClassLoader(), EntityManager.class, Serializable.class);
+   static final Class<?> proxyClass = Proxy.getProxyClass(PersistenceContext.class.getClassLoader(), EntityManager.class, Serializable.class, PersistenceContext.class);
 
    static final Constructor<?> proxyConstructor;
 
@@ -76,7 +76,7 @@
       {
          EntityManagerFactory emf = getEntityManagerFactory();
          EntityManager entityManager = emf.createEntityManager();
-         ManagedPersistenceContextProxyHandler handler = new ManagedPersistenceContextProxyHandler(entityManager, manager);
+         ManagedPersistenceContextProxyHandler handler = new ManagedPersistenceContextProxyHandler(entityManager, manager, bean.getQualifiers());
          EntityManager proxy = (EntityManager) proxyConstructor.newInstance(handler);
          return proxy;
       }

Added: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeManager.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeManager.java	                        (rev 0)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeManager.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.persistence;
+
+import java.io.Serializable;
+
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * Provides for programmatic configuration of the default flush mode.
+ * 
+ * TODO: implement this
+ * 
+ * @author Stuart Douglas
+ * 
+ */
+ at ApplicationScoped
+public class FlushModeManager implements Serializable
+{
+   FlushModeType flushModeType = FlushModeType.AUTO;
+
+   public FlushModeType getFlushModeType()
+   {
+      return flushModeType;
+   }
+
+   public void setFlushModeType(FlushModeType flushModeType)
+   {
+      this.flushModeType = flushModeType;
+   }
+
+}

Added: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeType.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeType.java	                        (rev 0)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/FlushModeType.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -0,0 +1,42 @@
+package org.jboss.seam.persistence;
+
+/**
+ * A full set of flush modes, including MANUAL,
+ * which is a glaring missing feature of the JPA
+ * spec.
+ * 
+ * @author Gavin King
+ *
+ */
+public enum FlushModeType
+{
+   
+   /**
+    * Flushing never occurs automatically, all changes are queued 
+    * until the application calls flush() explicitly.
+    */
+   MANUAL,
+
+   /**
+    * Flushing occurs automatically at commit time and when necessary
+    * before query executions.
+    */
+   AUTO,
+   
+   /**
+    * Flushing occurs automatically at transaction commit time.
+    */
+   COMMIT;
+   
+   /**
+    * Does this flush mode keep unflushed changes past a 
+    * transaction commit?
+    * 
+    * @return false for all flush modes except for MANUAL
+    */
+   public boolean dirtyBetweenTransactions() 
+   { 
+      return this==MANUAL;
+   }
+    
+}

Added: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/HibernatePersistenceProvider.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/HibernatePersistenceProvider.java	                        (rev 0)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/HibernatePersistenceProvider.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -0,0 +1,289 @@
+package org.jboss.seam.persistence;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.transaction.Synchronization;
+
+import org.hibernate.EntityMode;
+import org.hibernate.FlushMode;
+import org.hibernate.Session;
+import org.hibernate.StaleStateException;
+import org.hibernate.TransientObjectException;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.VersionType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Support for non-standardized features of Hibernate, when used as the JPA
+ * persistence provider.
+ * 
+ * @author Gavin King
+ * @author Pete Muir
+ * @author Stuart Douglas
+ * 
+ */
+public class HibernatePersistenceProvider extends PersistenceProvider
+{
+
+   @Inject
+   Instance<PersistenceContexts> persistenceContexts;
+
+   private static Logger log = LoggerFactory.getLogger(HibernatePersistenceProvider.class);
+   private static Class FULL_TEXT_SESSION_PROXY_CLASS;
+   private static Method FULL_TEXT_SESSION_CONSTRUCTOR;
+   private static Class FULL_TEXT_ENTITYMANAGER_PROXY_CLASS;
+   private static Method FULL_TEXT_ENTITYMANAGER_CONSTRUCTOR;
+   static
+   {
+      try
+      {
+         String version = null;
+         try
+         {
+            Class searchVersionClass = Class.forName("org.hibernate.search.Version");
+            Field versionField = searchVersionClass.getDeclaredField("VERSION");
+            version = (String) versionField.get(null);
+         }
+         catch (Exception e)
+         {
+            log.debug("no Hibernate Search, sorry :-(", e);
+         }
+         if (version != null)
+         {
+            Class searchClass = Class.forName("org.hibernate.search.Search");
+            try
+            {
+               FULL_TEXT_SESSION_CONSTRUCTOR = searchClass.getDeclaredMethod("getFullTextSession", Session.class);
+            }
+            catch (NoSuchMethodException noSuchMethod)
+            {
+               log.debug("org.hibernate.search.Search.getFullTextSession(Session) not found, trying deprecated method name createFullTextSession");
+               FULL_TEXT_SESSION_CONSTRUCTOR = searchClass.getDeclaredMethod("createFullTextSession", Session.class);
+            }
+            FULL_TEXT_SESSION_PROXY_CLASS = Class.forName("org.jboss.seam.persistence.FullTextHibernateSessionProxy");
+            Class jpaSearchClass = Class.forName("org.hibernate.search.jpa.Search");
+            try
+            {
+               FULL_TEXT_ENTITYMANAGER_CONSTRUCTOR = jpaSearchClass.getDeclaredMethod("getFullTextEntityManager", EntityManager.class);
+            }
+            catch (NoSuchMethodException noSuchMethod)
+            {
+               log.debug("org.hibernate.search.jpa.getFullTextSession(EntityManager) not found, trying deprecated method name createFullTextEntityManager");
+               FULL_TEXT_ENTITYMANAGER_CONSTRUCTOR = jpaSearchClass.getDeclaredMethod("createFullTextEntityManager", EntityManager.class);
+            }
+            FULL_TEXT_ENTITYMANAGER_PROXY_CLASS = Class.forName("org.jboss.seam.persistence.FullTextEntityManagerProxy");
+            log.debug("Hibernate Search is available :-)");
+         }
+      }
+      catch (Exception e)
+      {
+         log.debug("no Hibernate Search, sorry :-(", e);
+      }
+   }
+
+   @Inject
+   public void init()
+   {
+      featureSet.add(Feature.WILDCARD_AS_COUNT_QUERY_SUBJECT);
+   }
+
+   @Override
+   public void setFlushModeManual(EntityManager entityManager)
+   {
+      try
+      {
+         getSession(entityManager).setFlushMode(FlushMode.MANUAL);
+      }
+      catch (NotHibernateException nhe)
+      {
+         super.setFlushModeManual(entityManager);
+      }
+   }
+
+   @Override
+   public void setRenderFlushMode()
+   {
+      persistenceContexts.get().changeFlushMode(FlushModeType.MANUAL, true);
+   }
+
+   @Override
+   public boolean isDirty(EntityManager entityManager)
+   {
+      try
+      {
+         return getSession(entityManager).isDirty();
+      }
+      catch (NotHibernateException nhe)
+      {
+         return super.isDirty(entityManager);
+      }
+   }
+
+   @Override
+   public Object getId(Object bean, EntityManager entityManager)
+   {
+      try
+      {
+         return getSession(entityManager).getIdentifier(bean);
+      }
+      catch (NotHibernateException nhe)
+      {
+         return super.getId(bean, entityManager);
+      }
+      catch (TransientObjectException e)
+      {
+         if (bean instanceof HibernateProxy)
+         {
+            return super.getId(((HibernateProxy) bean).getHibernateLazyInitializer().getImplementation(), entityManager);
+         }
+         else
+         {
+            return super.getId(bean, entityManager);
+         }
+      }
+   }
+
+   @Override
+   public Object getVersion(Object bean, EntityManager entityManager)
+   {
+      try
+      {
+         return getVersion(bean, getSession(entityManager));
+      }
+      catch (NotHibernateException nhe)
+      {
+         return super.getVersion(bean, 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);
+      }
+   }
+
+   @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);
+      }
+
+   }
+
+   @Override
+   public String getName(Object bean, EntityManager entityManager) throws IllegalArgumentException
+   {
+      try
+      {
+         return getSession(entityManager).getEntityName(bean);
+      }
+      catch (NotHibernateException nhe)
+      {
+         return super.getName(bean, entityManager);
+      }
+      catch (TransientObjectException e)
+      {
+         return super.getName(bean, entityManager);
+      }
+   }
+
+   public static void checkVersion(Object value, Session session, Object oldVersion, Object version)
+   {
+      ClassMetadata classMetadata = getClassMetadata(value, session);
+      VersionType versionType = (VersionType) classMetadata.getPropertyTypes()[classMetadata.getVersionProperty()];
+      if (!versionType.isEqual(oldVersion, version))
+      {
+         throw new StaleStateException("current database version number does not match passivated version number");
+      }
+   }
+
+   public static Object getVersion(Object value, Session session)
+   {
+      ClassMetadata classMetadata = getClassMetadata(value, session);
+      return classMetadata != null && classMetadata.isVersioned() ? classMetadata.getVersion(value, EntityMode.POJO) : null;
+   }
+
+   private static ClassMetadata getClassMetadata(Object value, Session session)
+   {
+      Class entityClass = getEntityClass(value);
+      ClassMetadata classMetadata = null;
+      if (entityClass != null)
+      {
+         classMetadata = session.getSessionFactory().getClassMetadata(entityClass);
+         if (classMetadata == null)
+         {
+            throw new IllegalArgumentException("Could not find ClassMetadata object for entity class: " + entityClass.getName());
+         }
+      }
+      return classMetadata;
+   }
+
+   /**
+    * Returns the class of the specified Hibernate entity
+    */
+   @Override
+   public Class getBeanClass(Object bean)
+   {
+      return getEntityClass(bean);
+   }
+
+   public static Class getEntityClass(Object bean)
+   {
+      /*
+       * Class clazz = null; try { clazz = Entity.forBean(bean).getBeanClass();
+       * } catch (NotEntityException e) { // It's ok, try some other methods }
+       * 
+       * if (clazz == null) { clazz = Hibernate.getClass(bean); }
+       * 
+       * return clazz;
+       */
+      return null;
+   }
+
+   private Session getSession(EntityManager entityManager)
+   {
+      Object delegate = entityManager.getDelegate();
+      if (delegate instanceof Session)
+      {
+         return (Session) delegate;
+      }
+      else
+      {
+         throw new NotHibernateException();
+      }
+   }
+
+   /**
+    * Occurs when Hibernate is in the classpath, but this particular
+    * EntityManager is not from Hibernate
+    * 
+    * @author Gavin King
+    * 
+    */
+   static class NotHibernateException extends IllegalArgumentException
+   {
+   }
+
+}

Modified: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextExtension.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextExtension.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextExtension.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -117,6 +117,7 @@
       BeanBuilder<EntityManager> builder = new BeanBuilder<EntityManager>(manager).defineBeanFromAnnotatedType(typeBuilder.create());
       builder.setQualifiers(qualifiers);
       builder.setScope(scope);
+      builder.getTypes().add(PersistenceContext.class);
       builder.setBeanLifecycle(new ManagedPersistenceContextBeanLifecycle(qualifiers, manager));
       beans.add(builder.create());
    }

Modified: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextProxyHandler.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextProxyHandler.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/ManagedPersistenceContextProxyHandler.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -22,8 +22,12 @@
 package org.jboss.seam.persistence;
 
 import java.io.Serializable;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.enterprise.inject.Instance;
 import javax.enterprise.inject.spi.BeanManager;
@@ -54,15 +58,18 @@
 
    private final Instance<SeamTransaction> userTransactionInstance;
 
+   private final Set<Annotation> qualifiers;
+
    private transient boolean synchronizationRegistered;
 
    static final Logger log = LoggerFactory.getLogger(ManagedPersistenceContextProxyHandler.class);
 
-   public ManagedPersistenceContextProxyHandler(EntityManager delegate, BeanManager beanManager)
+   public ManagedPersistenceContextProxyHandler(EntityManager delegate, BeanManager beanManager, Set<Annotation> qualifiers)
    {
       super(delegate, beanManager);
       this.delegate = delegate;
       this.userTransactionInstance = InstanceResolver.getInstance(SeamTransaction.class, beanManager, DefaultTransactionLiteral.INSTANCE);
+      this.qualifiers = new HashSet<Annotation>(qualifiers);
    }
 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
@@ -105,4 +112,9 @@
 
    }
 
+   public Set<Annotation> getQualifiers()
+   {
+      return Collections.unmodifiableSet(qualifiers);
+   }
+
 }

Added: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContext.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContext.java	                        (rev 0)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContext.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.persistence;
+
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+/**
+ * Support for changing flushmodes for an existing persistence context.
+ * 
+ * @author Gavin King
+ * @author Stuart Douglas
+ * 
+ */
+public interface PersistenceContext
+{
+   public void changeFlushMode(FlushModeType flushMode);
+
+   public Set<Annotation> getQualifiers();
+
+   public Class<?> getBeanType();
+}

Modified: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContextProxyHandler.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContextProxyHandler.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContextProxyHandler.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -50,12 +50,15 @@
 
    private final Instance<Expressions> expressionsInstance;
 
+   private final Instance<PersistenceProvider> persistenceProvider;
+
    static final Logger log = LoggerFactory.getLogger(ManagedPersistenceContextProxyHandler.class);
 
    public PersistenceContextProxyHandler(EntityManager delegate, BeanManager beanManager)
    {
       this.delegate = delegate;
       expressionsInstance = InstanceResolver.getInstance(Expressions.class, beanManager);
+      persistenceProvider = InstanceResolver.getInstance(PersistenceProvider.class, beanManager);
    }
 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
@@ -64,9 +67,23 @@
       {
          return handleCreateQueryWithString(method, args);
       }
+      if ("changeFlushMode".equals(method.getName()) && method.getParameterTypes().length == 1 && method.getParameterTypes()[0].equals(FlushModeType.class))
+      {
+         changeFushMode((FlushModeType) args[0]);
+         return null;
+      }
+      if ("getBeanType".equals(method.getName()) && method.getParameterTypes().length == 0)
+      {
+         return EntityManager.class;
+      }
       return method.invoke(delegate, args);
    }
 
+   private void changeFushMode(FlushModeType flushModeType)
+   {
+      persistenceProvider.get().setFlushMode(delegate, flushModeType);
+   }
+
    protected Object handleCreateQueryWithString(Method method, Object[] args) throws Throwable
    {
       if (args[0] == null)

Added: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContexts.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContexts.java	                        (rev 0)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceContexts.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -0,0 +1,205 @@
+package org.jboss.seam.persistence;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.ConversationScoped;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Maintains the set of persistence contexts that have been touched in a
+ * conversation. Also controls the flush mode used by the persistence contexts
+ * during the render phase.
+ * 
+ * @author Gavin King
+ */
+ at ConversationScoped
+public class PersistenceContexts implements Serializable
+{
+   private static final long serialVersionUID = -4897350516435283182L;
+   private static final Logger log = LoggerFactory.getLogger(PersistenceContexts.class);
+   /**
+    * persistences contexts are referenced by their qualifiers
+    */
+   private Set<PersistenceContextDefintition> set = new HashSet<PersistenceContextDefintition>();
+
+   private FlushModeType flushMode;
+
+   // the real flush mode is a backup of the flush mode when doing a temporary
+   // switch (such as during render)
+   private FlushModeType realFlushMode;
+
+   @Inject
+   BeanManager beanManager;
+
+   @Inject
+   @Any
+   Instance<PersistenceContext> persistenceContexts;
+
+   @Inject
+   Instance<PersistenceProvider> persistenceProvider;
+
+   @Inject
+   public void create(FlushModeManager manager)
+   {
+      FlushModeType defaultFlushMode = manager.getFlushModeType();
+      if (defaultFlushMode != null)
+      {
+         flushMode = defaultFlushMode;
+      }
+      else
+      {
+         flushMode = FlushModeType.AUTO;
+      }
+   }
+
+   public FlushModeType getFlushMode()
+   {
+      return flushMode;
+   }
+
+   public Set<PersistenceContextDefintition> getTouchedContexts()
+   {
+      return Collections.unmodifiableSet(set);
+   }
+
+   public void touch(PersistenceContext context)
+   {
+      set.add(new PersistenceContextDefintition(context.getQualifiers(), context.getBeanType()));
+   }
+
+   public void untouch(PersistenceContext context)
+   {
+      set.remove(new PersistenceContextDefintition(context.getQualifiers(), context.getBeanType()));
+   }
+
+   public void changeFlushMode(FlushModeType flushMode)
+   {
+      changeFlushMode(flushMode, false);
+   }
+
+   public void changeFlushMode(FlushModeType flushMode, boolean temporary)
+   {
+      if (temporary)
+      {
+         realFlushMode = this.flushMode;
+      }
+      this.flushMode = flushMode;
+      changeFlushModes();
+   }
+
+   /**
+    * Restore the previous flush mode if the current flush mode is marked as
+    * temporary.
+    */
+   public void restoreFlushMode()
+   {
+      if (realFlushMode != null && realFlushMode != flushMode)
+      {
+         flushMode = realFlushMode;
+         realFlushMode = null;
+         changeFlushModes();
+      }
+   }
+
+   private void changeFlushModes()
+   {
+
+      for (PersistenceContext context : persistenceContexts)
+      {
+         if (set.contains(new PersistenceContextDefintition(context.getQualifiers(), context.getBeanType())))
+            try
+            {
+               context.changeFlushMode(flushMode);
+            }
+            catch (UnsupportedOperationException uoe)
+            {
+               // we won't be nasty and throw and exception, but we'll log a
+               // warning to the developer
+               log.warn(uoe.getMessage());
+            }
+      }
+   }
+
+   public void beforeRender()
+   {
+      // some JPA providers may not support MANUAL flushing
+      // defer the decision to the provider manager component
+      persistenceProvider.get().setRenderFlushMode();
+   }
+
+   public void afterRender()
+   {
+      restoreFlushMode();
+   }
+
+   public static class PersistenceContextDefintition
+   {
+      private final Set<Annotation> qualifiers;
+      private final Class<?> type;
+
+      public PersistenceContextDefintition(Set<Annotation> qualifiers, Class<?> type)
+      {
+         this.qualifiers = new HashSet<Annotation>(qualifiers);
+         this.type = type;
+      }
+
+      public Set<Annotation> getQualifiers()
+      {
+         return qualifiers;
+      }
+
+      public Class<?> getType()
+      {
+         return type;
+      }
+
+      @Override
+      public int hashCode()
+      {
+         final int prime = 31;
+         int result = 1;
+         result = prime * result + ((qualifiers == null) ? 0 : qualifiers.hashCode());
+         result = prime * result + ((type == null) ? 0 : type.hashCode());
+         return result;
+      }
+
+      @Override
+      public boolean equals(Object obj)
+      {
+         if (this == obj)
+            return true;
+         if (obj == null)
+            return false;
+         if (getClass() != obj.getClass())
+            return false;
+         PersistenceContextDefintition other = (PersistenceContextDefintition) obj;
+         if (qualifiers == null)
+         {
+            if (other.qualifiers != null)
+               return false;
+         }
+         else if (!qualifiers.equals(other.qualifiers))
+            return false;
+         if (type == null)
+         {
+            if (other.type != null)
+               return false;
+         }
+         else if (!type.equals(other.type))
+            return false;
+         return true;
+      }
+
+   }
+
+}

Added: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceProvider.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceProvider.java	                        (rev 0)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/PersistenceProvider.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -0,0 +1,265 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.seam.persistence;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.OptimisticLockException;
+import javax.persistence.PersistenceContexts;
+import javax.transaction.Synchronization;
+
+/**
+ * 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.
+ * 
+ * The methods on this class are a great todo list for the next rev of the JPA
+ * spec ;-)
+ * 
+ * @author Gavin King
+ * @author Pete Muir
+ * @author Stuart Douglas
+ * 
+ */
+public class PersistenceProvider
+{
+   public enum Feature
+   {
+      /**
+       * Identifies whether this JPA provider supports using a wildcard as the
+       * subject of a count query.
+       * 
+       * <p>
+       * Here's a count query that uses a wildcard as the subject.
+       * </p>
+       * 
+       * <pre>
+       * select count(*) from Vehicle v
+       * </pre>
+       * <p>
+       * Per the JPA 1.0 spec, using a wildcard as a subject of a count query is
+       * not permitted. Instead, the subject must be the entity or the alias, as
+       * in this count query:
+       * </p>
+       * 
+       * <pre>
+       * select count(v) from Vehicle v
+       * </pre>
+       * <p>
+       * Hibernate supports the wildcard syntax as an vendor extension.
+       * Furthermore, Hibernate produces an invalid SQL query when using the
+       * compliant subject if the entity has a composite primary key. Therefore,
+       * we prefer to use the wildcard syntax if it is supported.
+       * </p>
+       */
+      WILDCARD_AS_COUNT_QUERY_SUBJECT
+   }
+
+   protected Set<Feature> featureSet = new HashSet<Feature>();
+
+   /**
+    * Indicate whether this JPA provider supports the feature defined by the
+    * provided Feature enum value.
+    */
+   public boolean supportsFeature(Feature feature)
+   {
+      return featureSet.contains(feature);
+   }
+
+   /**
+    * sets the flush mode
+    */
+   public void setFlushMode(EntityManager entityManager, FlushModeType type)
+   {
+      switch (type)
+      {
+      case AUTO:
+         entityManager.setFlushMode(javax.persistence.FlushModeType.AUTO);
+         break;
+      case COMMIT:
+         entityManager.setFlushMode(javax.persistence.FlushModeType.COMMIT);
+      case MANUAL:
+         setFlushModeManual(entityManager);
+      default:
+         throw new RuntimeException("Unkown flush mode: " + type);
+      }
+   }
+
+   /**
+    * Set the flush mode to manual-only flushing. Called when an atomic
+    * persistence context is required.
+    */
+   public void setFlushModeManual(EntityManager entityManager)
+   {
+      throw new UnsupportedOperationException("Use of FlushMode.MANUAL requires Hibernate as the persistence provider. Please use Hibernate, a custom persistenceProvider, or remove the MANUAL flush mode setting.");
+   }
+
+   /**
+    * <p>
+    * Set the FlushMode the persistence contexts should use during rendering by
+    * calling {@link PersistenceContexts#changeFlushMode(FlushModeType, true)}.
+    * The actual changing of the flush mode is handled by the
+    * {@link PersistenceContexts} instance. The boolean argument should be true
+    * to indicate that this is a temporary change and that the old flush mode
+    * should be restored after render.
+    * </p>
+    * <p>
+    * Ideally, this should be MANUAL since changes should never flush to the
+    * database while in render response and the cost of a dirty check can be
+    * avoided. However, since the MANUAL mode is not officially part of the JPA
+    * specification, the default implementation will perform no operation.
+    * </p>
+    */
+   public void setRenderFlushMode()
+   {
+      // no-op in default implementation
+   }
+
+   /**
+    * 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 boolean isDirty(EntityManager entityManager)
+   {
+      return true; // best we can do!
+   }
+
+   /**
+    * Get the value of the entity identifier attribute.
+    * 
+    * @param bean a managed entity instance
+    */
+   public Object getId(Object bean, EntityManager entityManager)
+   {
+      // return Entity.forBean(bean).getIdentifier(bean);
+      return null;
+   }
+
+   /**
+    * 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 null;
+      // return Entity.forBean(bean).getName();
+   }
+
+   /**
+    * Get the value of the entity version attribute.
+    * 
+    * @param bean a managed entity instance
+    */
+   public Object getVersion(Object bean, EntityManager entityManager)
+   {
+      return null;
+      // return Entity.forBean(bean).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 void enableFilter(Filter filter, EntityManager entityManager) {
+    * throw new UnsupportedOperationException("Use of filters requires Hibernate as the persistence provider. Please use Hibernate or remove the filters configuration."
+    * ); }
+    */
+   /**
+    * Register a Synchronization with the current transaction.
+    */
+   public boolean registerSynchronization(Synchronization sync, EntityManager entityManager)
+   {
+      return false; // best we can do!
+   }
+
+   /**
+    * Wrap the delegate before returning it to the application
+    */
+   public Object proxyDelegate(Object delegate)
+   {
+      return delegate;
+   }
+
+   /**
+    * 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 null;
+      // return Entity.forBean(bean).getBeanClass();
+   }
+
+   public Method getPostLoadMethod(Object bean, EntityManager entityManager)
+   {
+      return null;
+      // return Entity.forBean(bean).getPostLoadMethod();
+   }
+
+   public Method getPrePersistMethod(Object bean, EntityManager entityManager)
+   {
+      return null;
+      // return Entity.forBean(bean).getPrePersistMethod();
+   }
+
+   public Method getPreUpdateMethod(Object bean, EntityManager entityManager)
+   {
+      return null;
+      // return Entity.forBean(bean).getPreUpdateMethod();
+   }
+
+   public Method getPreRemoveMethod(Object bean, EntityManager entityManager)
+   {
+      return null;
+      // return Entity.forBean(bean).getPreRemoveMethod();
+   }
+
+}

Modified: modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/transaction/EntityTransaction.java
===================================================================
--- modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/transaction/EntityTransaction.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/main/java/org/jboss/seam/persistence/transaction/EntityTransaction.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -22,6 +22,7 @@
 package org.jboss.seam.persistence.transaction;
 
 import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Instance;
 import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.transaction.HeuristicMixedException;
@@ -32,6 +33,7 @@
 import javax.transaction.Synchronization;
 import javax.transaction.SystemException;
 
+import org.jboss.seam.persistence.PersistenceProvider;
 import org.jboss.weld.extensions.core.Veto;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -39,8 +41,8 @@
 /**
  * Support for the JPA EntityTransaction API.
  * 
- * Adapts JPA transaction management to a Seam UserTransaction 
- * interface.For use in non-JTA-capable environments.
+ * Adapts JPA transaction management to a Seam UserTransaction interface.For use
+ * in non-JTA-capable environments.
  * 
  * @author Gavin King
  * 
@@ -50,12 +52,14 @@
 public class EntityTransaction extends AbstractUserTransaction
 {
    private static final Logger log = LoggerFactory.getLogger(EntityTransaction.class);
-   
+
    @Inject
    private EntityManager entityManager;
-   
-   
+
    @Inject
+   private Instance<PersistenceProvider> persistenceProvider;
+
+   @Inject
    public EntityTransaction(Synchronizations sync)
    {
       super(sync);
@@ -69,7 +73,7 @@
    public void begin() throws NotSupportedException, SystemException
    {
       log.debug("beginning JPA resource-local transaction");
-      //TODO: translate exceptions that occur into the correct JTA exception
+      // TODO: translate exceptions that occur into the correct JTA exception
       try
       {
          getDelegate().begin();
@@ -81,15 +85,14 @@
       }
    }
 
-   public void commit() throws RollbackException, HeuristicMixedException,
-            HeuristicRollbackException, SecurityException, IllegalStateException, SystemException
+   public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException
    {
       log.debug("committing JPA resource-local transaction");
       javax.persistence.EntityTransaction delegate = getDelegate();
       boolean success = false;
       try
       {
-         if ( delegate.getRollbackOnly() )
+         if (delegate.getRollbackOnly())
          {
             delegate.rollback();
             throw new RollbackException();
@@ -110,7 +113,7 @@
    public void rollback() throws IllegalStateException, SecurityException, SystemException
    {
       log.debug("rolling back JPA resource-local transaction");
-      //TODO: translate exceptions that occur into the correct JTA exception
+      // TODO: translate exceptions that occur into the correct JTA exception
       javax.persistence.EntityTransaction delegate = getDelegate();
       try
       {
@@ -152,18 +155,17 @@
    @Override
    public void registerSynchronization(Synchronization sync)
    {
-      if ( log.isDebugEnabled() )
+      if (log.isDebugEnabled())
       {
          log.debug("registering synchronization: " + sync);
       }
-      //try to register the synchronization directly with the
-      //persistence provider, but if this fails, just hold
-      //on to it myself
-      // if ( !PersistenceProvider.instance().registerSynchronization(sync,
-      // currentEntityManager) )
-      // {
-      // getSynchronizations().registerSynchronization(sync);
-      // }
+      // try to register the synchronization directly with the
+      // persistence provider, but if this fails, just hold
+      // on to it myself
+      if (!persistenceProvider.get().registerSynchronization(sync, entityManager))
+      {
+         getSynchronizations().registerSynchronization(sync);
+      }
    }
 
    @Override
@@ -175,7 +177,7 @@
    @Override
    public void enlist(EntityManager entityManager)
    {
-      //no-op
+      // no-op
    }
 
 }

Modified: modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionAttributeInterceptorTest.java
===================================================================
--- modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionAttributeInterceptorTest.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionAttributeInterceptorTest.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -37,6 +37,7 @@
 
 import org.jboss.arquillian.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.seam.persistence.PersistenceProvider;
 import org.jboss.seam.persistence.transaction.DefaultTransaction;
 import org.jboss.seam.persistence.transaction.SeamTransaction;
 import org.jboss.seam.persistence.transaction.TransactionExtension;
@@ -74,6 +75,7 @@
       war.addLibraries(MavenArtifactResolver.resolve(ArtifactNames.WELD_EXTENSIONS));
       war.addLibraries(MavenArtifactResolver.resolve(ArtifactNames.SEAM_PERSISTENCE_API));
       war.addPackage(TransactionExtension.class.getPackage());
+      war.addPackage(PersistenceProvider.class.getPackage());
       war.addPackage(NamingUtils.class.getPackage());
       war.addClasses(TransactionAttributeInterceptorTest.class, TransactionAttributeManagedBean.class, HelloService.class, Hotel.class, EntityManagerProvider.class, DontRollBackException.class);
       war.addWebResource("META-INF/persistence.xml", "classes/META-INF/persistence.xml");

Modified: modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionInterceptorTest.java
===================================================================
--- modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionInterceptorTest.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionInterceptorTest.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -37,6 +37,7 @@
 
 import org.jboss.arquillian.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.seam.persistence.PersistenceProvider;
 import org.jboss.seam.persistence.transaction.DefaultTransaction;
 import org.jboss.seam.persistence.transaction.SeamTransaction;
 import org.jboss.seam.persistence.transaction.TransactionExtension;
@@ -75,6 +76,7 @@
       war.addLibraries(MavenArtifactResolver.resolve(ArtifactNames.SEAM_PERSISTENCE_API));
       war.addPackage(TransactionExtension.class.getPackage());
       war.addPackage(NamingUtils.class.getPackage());
+      war.addPackage(PersistenceProvider.class.getPackage());
       war.addClasses(TransactionInterceptorTest.class, TransactionManagedBean.class, HelloService.class, Hotel.class, EntityManagerProvider.class, DontRollBackException.class);
       war.addWebResource("META-INF/persistence.xml", "classes/META-INF/persistence.xml");
       war.addWebResource(new ByteArrayAsset(("<beans><interceptors><class>" + TransactionInterceptor.class.getName() + "</class></interceptors></beans>").getBytes()), "beans.xml");

Modified: modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionScopedTest.java
===================================================================
--- modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionScopedTest.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/TransactionScopedTest.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -13,6 +13,7 @@
 
 import org.jboss.arquillian.api.Deployment;
 import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.seam.persistence.PersistenceProvider;
 import org.jboss.seam.persistence.transaction.DefaultTransaction;
 import org.jboss.seam.persistence.transaction.SeamTransaction;
 import org.jboss.seam.persistence.transaction.TransactionExtension;
@@ -40,6 +41,7 @@
       war.addLibraries(MavenArtifactResolver.resolve(ArtifactNames.SEAM_PERSISTENCE_API));
       war.addPackage(TransactionExtension.class.getPackage());
       war.addPackage(TransactionScopeExtension.class.getPackage());
+      war.addPackage(PersistenceProvider.class.getPackage());
       war.addPackage(NamingUtils.class.getPackage());
       war.addClasses(TransactionScopedTest.class, Hotel.class, HelloService.class, TransactionScopedObject.class);
       war.addWebResource("META-INF/persistence.xml", "classes/META-INF/persistence.xml");

Modified: modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/UserTransactionTest.java
===================================================================
--- modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/UserTransactionTest.java	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/impl/src/test/java/org/jboss/seam/persistence/transactions/test/UserTransactionTest.java	2010-08-05 10:07:05 UTC (rev 13555)
@@ -5,6 +5,7 @@
 import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceException;
 import javax.transaction.HeuristicMixedException;
 import javax.transaction.HeuristicRollbackException;
 import javax.transaction.NotSupportedException;
@@ -40,6 +41,7 @@
       war.addLibraries(MavenArtifactResolver.resolve(ArtifactNames.WELD_EXTENSIONS));
       war.addLibraries(MavenArtifactResolver.resolve(ArtifactNames.SEAM_PERSISTENCE_API));
       war.addPackage(TransactionExtension.class.getPackage());
+      war.addPackage(PersistenceException.class.getPackage());
       war.addClasses(UserTransactionTest.class, Hotel.class, HelloService.class);
       war.addPackage(NamingUtils.class.getPackage());
       war.addWebResource("META-INF/persistence.xml", "classes/META-INF/persistence.xml");

Modified: modules/persistence/trunk/pom.xml
===================================================================
--- modules/persistence/trunk/pom.xml	2010-08-04 17:40:14 UTC (rev 13554)
+++ modules/persistence/trunk/pom.xml	2010-08-05 10:07:05 UTC (rev 13555)
@@ -65,6 +65,12 @@
             <artifactId>seam-persistence</artifactId>
             <version>${project.version}</version>
          </dependency>
+         
+         <dependency>
+	         <groupId>org.hibernate</groupId>
+	         <artifactId>hibernate-core</artifactId>
+	         <version>3.5.1-Final</version>
+	      </dependency>
 
       </dependencies>
    </dependencyManagement>



More information about the seam-commits mailing list