diff --git a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/JndiInfinispanRegionFactory.java b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/JndiInfinispanRegionFactory.java index 94fa837ad6..75480ba5a3 100644 --- a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/JndiInfinispanRegionFactory.java +++ b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/JndiInfinispanRegionFactory.java @@ -22,17 +22,15 @@ package org.hibernate.cache.infinispan; import java.util.Properties; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; import org.hibernate.cache.CacheException; +import org.hibernate.engine.jndi.JndiException; +import org.hibernate.engine.jndi.spi.JndiService; import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.internal.util.jndi.JndiHelper; +import org.hibernate.service.spi.ServiceRegistryAwareService; +import org.hibernate.service.spi.ServiceRegistryImplementor; import org.infinispan.manager.EmbeddedCacheManager; -import org.infinispan.util.logging.Log; -import org.infinispan.util.logging.LogFactory; /** * A {@link org.hibernate.cache.spi.RegionFactory} for Infinispan-backed cache @@ -41,9 +39,7 @@ import org.infinispan.util.logging.LogFactory; * @author Galder ZamarreƱo * @since 3.5 */ -public class JndiInfinispanRegionFactory extends InfinispanRegionFactory { - - private static final Log log = LogFactory.getLog( JndiInfinispanRegionFactory.class ); +public class JndiInfinispanRegionFactory extends InfinispanRegionFactory implements ServiceRegistryAwareService { /** * Specifies the JNDI name under which the {@link EmbeddedCacheManager} to use is bound. @@ -51,6 +47,13 @@ public class JndiInfinispanRegionFactory extends InfinispanRegionFactory { */ public static final String CACHE_MANAGER_RESOURCE_PROP = "hibernate.cache.infinispan.cachemanager"; + private JndiService jndiService; + + @Override + public void injectServices(ServiceRegistryImplementor serviceRegistry) { + this.jndiService = serviceRegistry.getService( JndiService.class ); + } + /** * Constructs a JndiInfinispanRegionFactory */ @@ -75,34 +78,18 @@ public class JndiInfinispanRegionFactory extends InfinispanRegionFactory { if ( name == null ) { throw new CacheException( "Configuration property " + CACHE_MANAGER_RESOURCE_PROP + " not set" ); } - return locateCacheManager( name, JndiHelper.extractJndiProperties( properties ) ); - } - private EmbeddedCacheManager locateCacheManager(String jndiNamespace, Properties jndiProperties) { - Context ctx = null; try { - ctx = new InitialContext( jndiProperties ); - return (EmbeddedCacheManager) ctx.lookup( jndiNamespace ); + return (EmbeddedCacheManager) jndiService.locate( name ); } - catch (NamingException ne) { - final String msg = "Unable to retrieve CacheManager from JNDI [" + jndiNamespace + "]"; - log.info( msg, ne ); - throw new CacheException( msg ); - } - finally { - if ( ctx != null ) { - try { - ctx.close(); - } - catch (NamingException ne) { - log.info( "Unable to release initial context", ne ); - } - } + catch (JndiException e) { + throw new CacheException( "Unable to retrieve CacheManager from JNDI [" + name + "]", e ); } } @Override public void stop() { // Do not attempt to stop a cache manager because it wasn't created by this region factory. + jndiService = null; } } diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java index a084fcf85d..a3390c6379 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java @@ -23,6 +23,8 @@ */ package org.hibernate.test.cache.infinispan.functional; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; @@ -31,28 +33,41 @@ import javax.naming.NameNotFoundException; import javax.naming.Reference; import javax.naming.StringRefAddr; +import org.hibernate.ConnectionReleaseMode; +import org.hibernate.Session; +import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; +import org.hibernate.boot.registry.StandardServiceRegistry; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cache.infinispan.InfinispanRegionFactory; +import org.hibernate.cache.infinispan.JndiInfinispanRegionFactory; +import org.hibernate.cfg.Environment; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; +import org.hibernate.metamodel.Metadata; +import org.hibernate.metamodel.MetadataSources; +import org.hibernate.metamodel.spi.MetadataImplementor; +import org.hibernate.stat.Statistics; + +import org.hibernate.testing.jta.TestingJtaBootstrap; +import org.hibernate.testing.jta.TestingJtaPlatformImpl; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.junit4.BaseUnitTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + import org.infinispan.Cache; import org.infinispan.lifecycle.ComponentStatus; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; + import org.jboss.util.naming.NonSerializableFactory; + import org.jnp.server.Main; import org.jnp.server.SingletonNamingServer; -import org.junit.Test; - -import org.hibernate.Session; -import org.hibernate.cache.infinispan.InfinispanRegionFactory; -import org.hibernate.cache.infinispan.JndiInfinispanRegionFactory; -import org.hibernate.cache.spi.RegionFactory; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.cfg.Mappings; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.stat.Statistics; - import static org.junit.Assert.assertEquals; /** @@ -61,121 +76,40 @@ import static org.junit.Assert.assertEquals; * @author Galder ZamarreƱo * @since // TODO */ -public class JndiRegionFactoryTestCase extends SingleNodeTestCase { +public class JndiRegionFactoryTestCase extends BaseUnitTestCase { private static final Log log = LogFactory.getLog( JndiRegionFactoryTestCase.class ); + private static final String JNDI_NAME = "java:CacheManager"; + + // Naming private Main namingMain; private SingletonNamingServer namingServer; - private Properties props; - private boolean bindToJndi = true; private EmbeddedCacheManager manager; - @Override - protected void cleanupTest() throws Exception { - Context ctx = new InitialContext( props ); - unbind( JNDI_NAME, ctx ); - namingServer.destroy(); - namingMain.stop(); - manager.stop(); // Need to stop cos JNDI region factory does not stop it. - } - @Override - protected Class getCacheRegionFactory() { - return JndiInfinispanRegionFactory.class; - } - - @Override - public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) { - if ( bindToJndi ) { - try { - // Create an in-memory jndi - namingServer = new SingletonNamingServer(); - namingMain = new Main(); - namingMain.setInstallGlobalService( true ); - namingMain.setPort( -1 ); - namingMain.start(); - props = new Properties(); - props.put( "java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory" ); - props.put( "java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" ); - - manager = new DefaultCacheManager( InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE, false ); - Context ctx = new InitialContext( props ); - bind( JNDI_NAME, manager, EmbeddedCacheManager.class, ctx ); - } - catch (Exception e) { - throw new RuntimeException( "Failure to set up JNDI", e ); - } - } - } - - @Override - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( JndiInfinispanRegionFactory.CACHE_MANAGER_RESOURCE_PROP, JNDI_NAME ); - cfg.setProperty( Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory" ); - cfg.setProperty( "java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" ); - } - - @Test - public void testRedeployment() throws Exception { - addEntityCheckCache( sessionFactory() ); - sessionFactory().close(); - bindToJndi = false; - - SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) configuration().buildSessionFactory( serviceRegistry() ); - addEntityCheckCache( sessionFactory ); - JndiInfinispanRegionFactory regionFactory = (JndiInfinispanRegionFactory) sessionFactory.getSettings().getRegionFactory(); - Cache cache = regionFactory.getCacheManager().getCache( "org.hibernate.test.cache.infinispan.functional.Item" ); - assertEquals( ComponentStatus.RUNNING, cache.getStatus() ); - } - - private void addEntityCheckCache(SessionFactoryImplementor sessionFactory) throws Exception { - Item item = new Item( "chris", "Chris's Item" ); - beginTx(); + @Before + public void setUp() { try { - Session s = sessionFactory.openSession(); - s.getTransaction().begin(); - s.persist( item ); - s.getTransaction().commit(); - s.close(); + // Create an in-memory jndi + namingServer = new SingletonNamingServer(); + namingMain = new Main(); + namingMain.setInstallGlobalService( true ); + namingMain.setPort( -1 ); + namingMain.start(); + + final Properties props = new Properties(); + props.put( "java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory" ); + props.put( "java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" ); + + manager = new DefaultCacheManager( InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE, false ); + Context ctx = new InitialContext( props ); + bind( JNDI_NAME, manager, EmbeddedCacheManager.class, ctx ); } catch (Exception e) { - setRollbackOnlyTx( e ); + throw new RuntimeException( "Failure to set up JNDI", e ); } - finally { - commitOrRollbackTx(); - } - - beginTx(); - try { - Session s = sessionFactory.openSession(); - Item found = (Item) s.load( Item.class, item.getId() ); - Statistics stats = sessionFactory.getStatistics(); - log.info( stats.toString() ); - assertEquals( item.getDescription(), found.getDescription() ); - assertEquals( 0, stats.getSecondLevelCacheMissCount() ); - assertEquals( 1, stats.getSecondLevelCacheHitCount() ); - s.delete( found ); - s.close(); - } - catch (Exception e) { - setRollbackOnlyTx( e ); - } - finally { - commitOrRollbackTx(); - } - } - /** - * Helper method that binds the a non serializable object to the JNDI tree. - * - * @param jndiName Name under which the object must be bound - * @param who Object to bind in JNDI - * @param classType Class type under which should appear the bound object - * @param ctx Naming context under which we bind the object - * @throws Exception Thrown if a naming exception occurs during binding - */ private void bind(String jndiName, Object who, Class classType, Context ctx) throws Exception { // Ah ! This service isn't serializable, so we use a helper class NonSerializableFactory.bind( jndiName, who ); @@ -199,9 +133,98 @@ public class JndiRegionFactoryTestCase extends SingleNodeTestCase { ctx.rebind( n.get( 0 ), ref ); } - private void unbind(String jndiName, Context ctx) throws Exception { - NonSerializableFactory.unbind( jndiName ); -// ctx.unbind(jndiName); + @After + public void tearDown() { + try { + NonSerializableFactory.unbind( JNDI_NAME ); + namingServer.destroy(); + namingMain.stop(); + manager.stop(); // Need to stop cos JNDI region factory does not stop it. + } + catch (Exception e) { + throw new RuntimeException( "Failure to clean up JNDI", e ); + } } + @Test + public void testRedeployment() throws Exception { + SessionFactoryImplementor sf = (SessionFactoryImplementor) buildMetadata().buildSessionFactory(); + addEntityCheckCache( sf ); + sf.close(); + + sf = (SessionFactoryImplementor) buildMetadata().buildSessionFactory(); + addEntityCheckCache( sf ); + JndiInfinispanRegionFactory regionFactory = (JndiInfinispanRegionFactory) sf.getSettings().getRegionFactory(); + Cache cache = regionFactory.getCacheManager().getCache( "org.hibernate.test.cache.infinispan.functional.Item" ); + assertEquals( ComponentStatus.RUNNING, cache.getStatus() ); + } + + @SuppressWarnings("unchecked") + private Metadata buildMetadata() { + Map config = new HashMap(); + config.put( Environment.HBM2DDL_AUTO, "create-drop" ); + config.put( Environment.USE_SECOND_LEVEL_CACHE, "true" ); + config.put( Environment.GENERATE_STATISTICS, "true" ); + config.put( Environment.USE_QUERY_CACHE, "true" ); + config.put( Environment.CACHE_REGION_FACTORY, JndiInfinispanRegionFactory.class.getName() ); + config.put( JndiInfinispanRegionFactory.CACHE_MANAGER_RESOURCE_PROP, JNDI_NAME ); + config.put( Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory" ); + config.put( "java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" ); + + TestingJtaBootstrap.prepare( config ); + config.put( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class.getName() ); + config.put( Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.AFTER_STATEMENT.toString() ); + + BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build(); + StandardServiceRegistry ssr = new StandardServiceRegistryBuilder( bsr ).applySettings( config ).build(); + + MetadataSources sources = new MetadataSources( bsr ); + sources.addResource( "org/hibernate/test/cache/infinispan/functional/Item.hbm.xml" ); + sources.addResource( "org/hibernate/test/cache/infinispan/functional/Customer.hbm.xml" ); + sources.addResource( "org/hibernate/test/cache/infinispan/functional/Contact.hbm.xml" ); + + MetadataImplementor metadata = (MetadataImplementor) sources.getMetadataBuilder( ssr ).build(); + BaseCoreFunctionalTestCase.overrideCacheSettings( metadata, "transactional" ); + return metadata; + } + + private void addEntityCheckCache(SessionFactoryImplementor sessionFactory) throws Exception { + Item item = new Item( "chris", "Chris's Item" ); + TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); + try { + Session s = sessionFactory.openSession(); + s.getTransaction().begin(); + s.persist( item ); + s.getTransaction().commit(); + s.close(); + } + catch (Exception e) { + log.error( "Error", e ); + TestingJtaPlatformImpl.INSTANCE.getTransactionManager().setRollbackOnly(); + } + finally { + TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); + } + + TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); + try { + Session s = sessionFactory.openSession(); + Item found = (Item) s.load( Item.class, item.getId() ); + Statistics stats = sessionFactory.getStatistics(); + log.info( stats.toString() ); + assertEquals( item.getDescription(), found.getDescription() ); + assertEquals( 0, stats.getSecondLevelCacheMissCount() ); + assertEquals( 1, stats.getSecondLevelCacheHitCount() ); + s.delete( found ); + s.close(); + } + catch (Exception e) { + log.error( "Error", e ); + TestingJtaPlatformImpl.INSTANCE.getTransactionManager().setRollbackOnly(); + } + finally { + TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); + } + + } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java index fcef5b11e9..c948df8cae 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java @@ -23,8 +23,6 @@ */ package org.hibernate.testing.junit4; -import static org.junit.Assert.fail; - import java.io.InputStream; import java.sql.Blob; import java.sql.Clob; @@ -66,16 +64,19 @@ import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.hibernate.type.Type; + import org.hibernate.testing.AfterClassOnce; import org.hibernate.testing.BeforeClassOnce; import org.hibernate.testing.OnExpectedFailure; import org.hibernate.testing.OnFailure; import org.hibernate.testing.SkipLog; import org.hibernate.testing.cache.CachingRegionFactory; -import org.hibernate.type.Type; import org.junit.After; import org.junit.Before; +import static org.junit.Assert.fail; + /** * Applies functional testing logic for core Hibernate testing on top of {@link BaseUnitTestCase} * @@ -212,15 +213,19 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { return; } - for ( EntityBinding entityBinding : metadataImplementor.getEntityBindings() ) { + overrideCacheSettings( metadataImplementor, getCacheConcurrencyStrategy() ); + } + + public static void overrideCacheSettings(MetadataImplementor metadata, String accessType) { + for ( EntityBinding entityBinding : metadata.getEntityBindings() ) { if ( entityBinding.getSuperEntityBinding() == null ) { - overrideEntityCache( entityBinding ); + overrideEntityCache( entityBinding, accessType ); } - overrideCollectionCachesForEntity( entityBinding ); + overrideCollectionCachesForEntity( entityBinding, accessType ); } } - private void overrideEntityCache(EntityBinding entityBinding) { + private static void overrideEntityCache(EntityBinding entityBinding, String accessType) { boolean hasLob = false; for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { if ( attributeBinding.getAttribute().isSingular() ) { @@ -240,15 +245,11 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { entityBinding.getHierarchyDetails().getCaching().setRequested( TruthValue.TRUE ); entityBinding.getHierarchyDetails().getCaching().setRegion( entityBinding.getEntityName() ); entityBinding.getHierarchyDetails().getCaching().setCacheLazyProperties( true ); - entityBinding.getHierarchyDetails().getCaching().setAccessType( - AccessType.fromExternalName( - getCacheConcurrencyStrategy() - ) - ); + entityBinding.getHierarchyDetails().getCaching().setAccessType( AccessType.fromExternalName( accessType ) ); } } - private void overrideCollectionCachesForEntity(EntityBinding entityBinding) { + private static void overrideCollectionCachesForEntity(EntityBinding entityBinding, String accessType) { for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) { if ( !attributeBinding.getAttribute().isSingular() ) { AbstractPluralAttributeBinding binding = AbstractPluralAttributeBinding.class.cast( attributeBinding ); @@ -261,7 +262,7 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { ) ); binding.getCaching().setCacheLazyProperties( true ); - binding.getCaching().setAccessType( AccessType.fromExternalName( getCacheConcurrencyStrategy() ) ); + binding.getCaching().setAccessType( AccessType.fromExternalName( accessType ) ); } } }