Return-Path: X-Original-To: apmail-openejb-commits-archive@www.apache.org Delivered-To: apmail-openejb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CAAC89484 for ; Wed, 30 Nov 2011 15:07:19 +0000 (UTC) Received: (qmail 40068 invoked by uid 500); 30 Nov 2011 15:07:19 -0000 Delivered-To: apmail-openejb-commits-archive@openejb.apache.org Received: (qmail 40017 invoked by uid 500); 30 Nov 2011 15:07:19 -0000 Mailing-List: contact commits-help@openejb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openejb.apache.org Delivered-To: mailing list commits@openejb.apache.org Received: (qmail 40010 invoked by uid 99); 30 Nov 2011 15:07:19 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Nov 2011 15:07:19 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Nov 2011 15:07:17 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 517802388860 for ; Wed, 30 Nov 2011 15:06:57 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1208464 - in /openejb/trunk/openejb/container/openejb-core/src: main/java/org/apache/openejb/assembler/classic/ test/java/org/apache/openejb/persistence/ Date: Wed, 30 Nov 2011 15:06:56 -0000 To: commits@openejb.apache.org From: rmannibucau@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111130150657.517802388860@eris.apache.org> Author: rmannibucau Date: Wed Nov 30 15:06:55 2011 New Revision: 1208464 URL: http://svn.apache.org/viewvc?rev=1208464&view=rev Log: adding ReloadableEntityManagerFactory Added: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/persistence/ openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/persistence/ReloadableEntityManagerFactoryTest.java Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java?rev=1208464&r1=1208463&r2=1208464&view=diff ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java (original) +++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java Wed Nov 30 15:06:55 2011 @@ -18,10 +18,16 @@ package org.apache.openejb.assembler.cla import org.apache.openejb.persistence.PersistenceUnitInfoImpl; +import javax.persistence.Cache; +import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceUnitUtil; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.metamodel.Metamodel; import javax.persistence.spi.PersistenceProvider; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import java.util.concurrent.Callable; public class EntityManagerFactoryCallable implements Callable { @@ -44,4 +50,8 @@ public class EntityManagerFactoryCallabl EntityManagerFactory emf = persistenceProvider.createContainerEntityManagerFactory(unitInfo, properties); return emf; } + + public PersistenceUnitInfoImpl getUnitInfo() { + return unitInfo; + } } Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java?rev=1208464&r1=1208463&r2=1208464&view=diff ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java (original) +++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PersistenceBuilder.java Wed Nov 30 15:06:55 2011 @@ -32,10 +32,7 @@ import javax.persistence.ValidationMode; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; public class PersistenceBuilder { public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, PersistenceBuilder.class); @@ -134,11 +131,8 @@ public class PersistenceBuilder { final long start = System.nanoTime(); try { - final ExecutorService executor = Executors.newSingleThreadExecutor(new EntityManagerFactoryThreadFactory(classLoader)); - final Future future = executor.submit( - new EntityManagerFactoryCallable(persistenceProviderClassName, unitInfo) - ); - return future.get(10, TimeUnit.MINUTES); + final EntityManagerFactoryCallable callable = new EntityManagerFactoryCallable(persistenceProviderClassName, unitInfo); + return new ReloadableEntityManagerFactory(classLoader, createEmf(classLoader, callable), callable); } finally { final long time = TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS); logger.info("assembler.buildingPersistenceUnit", unitInfo.getPersistenceUnitName(), unitInfo.getPersistenceProviderClassName(), time+""); @@ -153,4 +147,10 @@ public class PersistenceBuilder { public static String getOpenEJBJndiName(String unit) { return Assembler.PERSISTENCE_UNIT_NAMING_CONTEXT + unit; } + + public static EntityManagerFactory createEmf(ClassLoader classLoader, Callable callable) throws ExecutionException, TimeoutException, InterruptedException { + final ExecutorService executor = Executors.newSingleThreadExecutor(new EntityManagerFactoryThreadFactory(classLoader)); + final Future future = executor.submit(callable); + return future.get(10, TimeUnit.MINUTES); + } } Added: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java?rev=1208464&view=auto ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java (added) +++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ReloadableEntityManagerFactory.java Wed Nov 30 15:06:55 2011 @@ -0,0 +1,102 @@ +package org.apache.openejb.assembler.classic; + +import org.apache.openejb.persistence.PersistenceUnitInfoImpl; +import org.apache.openejb.util.LogCategory; +import org.apache.openejb.util.Logger; + +import javax.persistence.Cache; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceUnitUtil; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.metamodel.Metamodel; +import java.util.Map; +import java.util.Properties; + +/** + * @author rmannibucau + */ +public class ReloadableEntityManagerFactory implements EntityManagerFactory { + private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB, ReloadableEntityManagerFactory.class); + + private ClassLoader classLoader; + private EntityManagerFactory delegate; + private EntityManagerFactoryCallable entityManagerFactoryCallable; + + public ReloadableEntityManagerFactory(final ClassLoader cl, final EntityManagerFactory emf, EntityManagerFactoryCallable callable) { + classLoader = cl; + delegate = emf; + this.entityManagerFactoryCallable = callable; + } + + @Override public EntityManager createEntityManager() { + return delegate.createEntityManager(); + } + + @Override + public EntityManager createEntityManager(Map map) { + return delegate.createEntityManager(map); + } + + @Override + public CriteriaBuilder getCriteriaBuilder() { + return delegate.getCriteriaBuilder(); + } + + @Override + public Metamodel getMetamodel() { + return delegate.getMetamodel(); + } + + @Override + public boolean isOpen() { + return delegate.isOpen(); + } + + @Override + public void close() { + delegate.close(); + } + + @Override + public Map getProperties() { + return delegate.getProperties(); + } + + @Override + public Cache getCache() { + return delegate.getCache(); + } + + @Override + public PersistenceUnitUtil getPersistenceUnitUtil() { + return delegate.getPersistenceUnitUtil(); + } + + public EntityManagerFactory getDelegate() { + return delegate; + } + + // only this method is synchronized since we want to avoid locks on other methods. + // it is just to avoid problems due to the "double click syndrom" + // + // Note: it uses the old unitInfo but properties can be modified (not managed classes, provider...) + public synchronized void reload() { + if (classLoader == null) { + classLoader = Thread.currentThread().getContextClassLoader(); + } + try { + delegate = PersistenceBuilder.createEmf(classLoader, entityManagerFactoryCallable); + } catch (Exception e) { + LOGGER.error("can't replace EntityManagerFactory " + delegate); + } + } + + public synchronized void setProperty(String key , String value) { + PersistenceUnitInfoImpl unitInfo = entityManagerFactoryCallable.getUnitInfo(); + if (unitInfo.getProperties() == null) { + unitInfo.setProperties(new Properties()); + } + unitInfo.getProperties().setProperty(key, value); + } +} Added: openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/persistence/ReloadableEntityManagerFactoryTest.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/persistence/ReloadableEntityManagerFactoryTest.java?rev=1208464&view=auto ============================================================================== --- openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/persistence/ReloadableEntityManagerFactoryTest.java (added) +++ openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/persistence/ReloadableEntityManagerFactoryTest.java Wed Nov 30 15:06:55 2011 @@ -0,0 +1,86 @@ +package org.apache.openejb.persistence; + +import org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory; +import org.apache.openejb.jee.jpa.unit.Persistence; +import org.apache.openejb.jee.jpa.unit.PersistenceUnit; +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.junit.Configuration; +import org.apache.openejb.junit.Module; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.persistence.Entity; +import javax.persistence.EntityManagerFactory; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import java.util.Properties; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotSame; + +/** + * @author rmannibucau + */ +@RunWith(ApplicationComposer.class) +public class ReloadableEntityManagerFactoryTest { + @javax.persistence.PersistenceUnit + private EntityManagerFactory emf; + + @Module + public Persistence persistence() throws Exception { + PersistenceUnit unit = new PersistenceUnit("foo-unit"); + unit.addClass(MyEntity.class); + unit.setProperty("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)"); + unit.getProperties().setProperty("openjpa.RuntimeUnenhancedClasses", "supported"); + unit.getProperties().setProperty("openjpa.DatCache", "false"); + unit.setExcludeUnlistedClasses(true); + + Persistence persistence = new org.apache.openejb.jee.jpa.unit.Persistence(unit); + persistence.setVersion("2.0"); + return persistence; + } + + @Configuration + public Properties config() { + final Properties p = new Properties(); + p.put("ReloadableEntityManagerFactoryTest", "new://Resource?type=DataSource"); + p.put("ReloadableEntityManagerFactoryTest.JdbcDriver", "org.hsqldb.jdbcDriver"); + p.put("ReloadableEntityManagerFactoryTest.JdbcUrl", "jdbc:hsqldb:mem:bval"); + return p; + } + + @Test public void reload() { + final ReloadableEntityManagerFactory remft = (ReloadableEntityManagerFactory) emf; + final EntityManagerFactory originalEmf = remft.getDelegate(); + assertEquals("false", emf.getProperties().get("openjpa.DataCache")); + select(); + + remft.setProperty("openjpa.DataCache", "true(Types=" + MyEntity.class.getName() + ")"); + remft.reload(); + select(); + assertEquals("true(Types=" + MyEntity.class.getName() + ")", emf.getProperties().get("openjpa.DataCache")); + + final EntityManagerFactory reloadedEmf = remft.getDelegate(); + assertNotSame(originalEmf, reloadedEmf); + } + + private void select() { + emf.createEntityManager() + .createQuery("select m from ReloadableEntityManagerFactoryTest$MyEntity m") + .getResultList(); + } + + @Entity + public static class MyEntity { + @Id @GeneratedValue + private long id; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } +}