/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.test.cache.infinispan.functional; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.NameNotFoundException; import javax.naming.Reference; import javax.naming.StringRefAddr; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.cache.infinispan.InfinispanRegionFactory; import org.hibernate.cache.infinispan.JndiInfinispanRegionFactory; import org.hibernate.cache.infinispan.util.InfinispanMessageLogger; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cfg.Environment; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.stat.Statistics; import org.hibernate.test.cache.infinispan.functional.entities.Item; 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.jboss.util.naming.NonSerializableFactory; import org.jnp.server.Main; import org.jnp.server.SingletonNamingServer; import static org.junit.Assert.assertEquals; /** * @author Galder ZamarreƱo */ public class JndiRegionFactoryTest extends SingleNodeTest { private static final InfinispanMessageLogger log = InfinispanMessageLogger.Provider.getLog( JndiRegionFactoryTest.class ); private static final String JNDI_NAME = "java:CacheManager"; private Main namingMain; private SingletonNamingServer namingServer; private Properties props; private boolean bindToJndi = true; private EmbeddedCacheManager manager; @Override public List<Object[]> getParameters() { return Collections.singletonList(READ_WRITE_INVALIDATION); } @Override protected Class<? extends RegionFactory> getRegionFactoryClass() { return JndiInfinispanRegionFactory.class; } @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 void afterStandardServiceRegistryBuilt(StandardServiceRegistry ssr) { 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" ); final String cfgFileName = (String) ssr.getService( ConfigurationService.class ).getSettings().get( InfinispanRegionFactory.INFINISPAN_CONFIG_RESOURCE_PROP ); manager = new DefaultCacheManager( cfgFileName == null ? InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE : cfgFileName, 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 @SuppressWarnings("unchecked") protected void addSettings(Map settings) { super.addSettings( settings ); settings.put( JndiInfinispanRegionFactory.CACHE_MANAGER_RESOURCE_PROP, JNDI_NAME ); settings.put( Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory" ); settings.put( "java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces" ); } @Test public void testRedeployment() throws Exception { addEntityCheckCache( sessionFactory() ); bindToJndi = false; rebuildSessionFactory(); addEntityCheckCache( sessionFactory() ); JndiInfinispanRegionFactory regionFactory = (JndiInfinispanRegionFactory) sessionFactory().getSettings().getRegionFactory(); Cache cache = regionFactory.getCacheManager().getCache( Item.class.getName() ); assertEquals( ComponentStatus.RUNNING, cache.getStatus() ); } private void addEntityCheckCache(SessionFactoryImplementor sessionFactory) throws Exception { Item item = new Item( "chris", "Chris's Item" ); withTxSession(s -> s.persist( item )); withTxSession(s -> { Item found = 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); }); } /** * 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 ); Name n = ctx.getNameParser( "" ).parse( jndiName ); while ( n.size() > 1 ) { String ctxName = n.get( 0 ); try { ctx = (Context) ctx.lookup( ctxName ); } catch (NameNotFoundException e) { log.debug( "creating Subcontext " + ctxName ); ctx = ctx.createSubcontext( ctxName ); } n = n.getSuffix( 1 ); } // The helper class NonSerializableFactory uses address type nns, we go on to // use the helper class to bind the service object in JNDI StringRefAddr addr = new StringRefAddr( "nns", jndiName ); Reference ref = new Reference( classType.getName(), addr, NonSerializableFactory.class.getName(), null ); ctx.rebind( n.get( 0 ), ref ); } private void unbind(String jndiName, Context ctx) throws Exception { NonSerializableFactory.unbind( jndiName ); // ctx.unbind(jndiName); } }