package org.infinispan.persistence.jdbc.stringbased; import static org.infinispan.test.TestingUtil.clearCacheLoader; import static org.infinispan.test.TestingUtil.withCacheManager; import static org.testng.AssertJUnit.assertEquals; import java.sql.Connection; import org.infinispan.AdvancedCache; import org.infinispan.Cache; import org.infinispan.commons.CacheException; import org.infinispan.commons.configuration.Builder; import org.infinispan.commons.configuration.BuiltBy; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfiguration; import org.infinispan.eviction.EvictionStrategy; import org.infinispan.persistence.jdbc.configuration.AbstractJdbcStoreConfigurationBuilder; import org.infinispan.persistence.jdbc.configuration.AbstractJdbcStoreConfigurationChildBuilder; import org.infinispan.persistence.jdbc.configuration.ConnectionFactoryConfiguration; import org.infinispan.persistence.jdbc.configuration.ConnectionFactoryConfigurationBuilder; import org.infinispan.persistence.jdbc.configuration.JdbcStringBasedStoreConfigurationBuilder; import org.infinispan.persistence.jdbc.configuration.PooledConnectionFactoryConfiguration; import org.infinispan.persistence.jdbc.connectionfactory.ConnectionFactory; import org.infinispan.persistence.jdbc.connectionfactory.PooledConnectionFactory; import org.infinispan.persistence.spi.PersistenceException; import org.infinispan.test.AbstractInfinispanTest; import org.infinispan.test.CacheManagerCallable; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.infinispan.test.fwk.UnitTestDatabaseManager; import org.testng.annotations.Test; /** * Tester for https://jira.jboss.org/browse/ISPN-579. * * @author Mircea.Markus@jboss.com * @since 4.1 */ @Test(groups = "functional", testName = "persistence.jdbc.stringbased.NonStringKeyPreloadTest") public class NonStringKeyPreloadTest extends AbstractInfinispanTest { public void testPreloadWithKey2StringMapper() throws Exception { String mapperName = PersonKey2StringMapper.class.getName(); ConfigurationBuilder cfg = createCacheStoreConfig(mapperName, false, true); withCacheManager(new CacheManagerCallable( TestCacheManagerFactory.createCacheManager(cfg)) { @Override public void call() { try { cm.getCache(); assert false : " Preload with Key2StringMapper is not supported. Specify an TwoWayKey2StringMapper if you want to support it (or disable preload)."; } catch (CacheException e) { log.debugf("Ignoring expected exception", e); } } }); } public void testPreloadWithTwoWayKey2StringMapper() throws Exception { String mapperName = TwoWayPersonKey2StringMapper.class.getName(); ConfigurationBuilder config = createCacheStoreConfig(mapperName, true, true); final Person mircea = new Person("Markus", "Mircea", 30); final Person dan = new Person("Dan", "Dude", 30); withCacheManager(new CacheManagerCallable( TestCacheManagerFactory.createCacheManager(config)) { @Override public void call() { Cache<Object, Object> cache = cm.getCache(); cache.put(mircea, "me"); cache.put(dan, "mate"); } }); withCacheManager(new CacheManagerCallable( TestCacheManagerFactory.createCacheManager(config)) { @Override public void call() { Cache<Object, Object> cache = null; try { cache = cm.getCache(); assert cache.containsKey(mircea); assert cache.containsKey(dan); } finally { clearCacheLoader(cache); } } }); } public void testPreloadWithTwoWayKey2StringMapperAndBoundedCache() throws Exception { String mapperName = TwoWayPersonKey2StringMapper.class.getName(); ConfigurationBuilder config = createCacheStoreConfig(mapperName, true, true); config.eviction().strategy(EvictionStrategy.LRU).maxEntries(3); withCacheManager(new CacheManagerCallable( TestCacheManagerFactory.createCacheManager(config)) { @Override public void call() { AdvancedCache<Object, Object> cache = cm.getCache().getAdvancedCache(); for (int i = 0; i < 10; i++) { Person p = new Person("name" + i, "surname" + i, 30); cache.put(p, "" + i); } } }); withCacheManager(new CacheManagerCallable( TestCacheManagerFactory.createCacheManager(config)) { @Override public void call() { AdvancedCache<Object, Object> cache = cm.getCache().getAdvancedCache(); assertEquals(3, cache.getDataContainer().size()); int found = 0; for (int i = 0; i < 10; i++) { Person p = new Person("name" + i, "surname" + i, 30); if (cache.getDataContainer().containsKey(p)) { found++; } } assertEquals(3, found); } }); } static ConfigurationBuilder createCacheStoreConfig(String mapperName, boolean wrap, boolean preload) { ConfigurationBuilder cfg = TestCacheManagerFactory.getDefaultCacheConfiguration(false); JdbcStringBasedStoreConfigurationBuilder store = cfg .persistence() .addStore(JdbcStringBasedStoreConfigurationBuilder.class) .fetchPersistentState(true) .preload(preload) .key2StringMapper(mapperName); UnitTestDatabaseManager.buildTableManipulation(store.table()); if (wrap) { ConnectionFactoryConfigurationBuilder<?> tmp = UnitTestDatabaseManager.configureUniqueConnectionFactory(new ConfigurationBuilder().persistence().addStore(JdbcStringBasedStoreConfigurationBuilder.class)); store.connectionFactory(new SharedConnectionFactoryConfigurationBuilder(store)).read((PooledConnectionFactoryConfiguration)tmp.create()); } else { UnitTestDatabaseManager.configureUniqueConnectionFactory(store); } return cfg; } public static class SharedConnectionFactory extends ConnectionFactory { static PooledConnectionFactory sharedFactory; static boolean started = false; @Override public void start(ConnectionFactoryConfiguration config, ClassLoader classLoader) throws PersistenceException { if (!started) { sharedFactory = new PooledConnectionFactory(); sharedFactory.start(config, classLoader); started = true; } } @Override public void stop() { //ignores } @Override public Connection getConnection() throws PersistenceException { return sharedFactory.getConnection(); } @Override public void releaseConnection(Connection conn) { sharedFactory.releaseConnection(conn); } } @BuiltBy(SharedConnectionFactoryConfigurationBuilder.class) public static class SharedConnectionFactoryConfiguration extends PooledConnectionFactoryConfiguration { SharedConnectionFactoryConfiguration(String connectionUrl, String driverClass, String username, String password) { super(null, connectionUrl, driverClass, username, password); } @Override public Class<? extends ConnectionFactory> connectionFactoryClass() { return SharedConnectionFactory.class; } } public static class SharedConnectionFactoryConfigurationBuilder<S extends AbstractJdbcStoreConfigurationBuilder<?, S>> extends AbstractJdbcStoreConfigurationChildBuilder<S> implements ConnectionFactoryConfigurationBuilder<SharedConnectionFactoryConfiguration> { public SharedConnectionFactoryConfigurationBuilder(AbstractJdbcStoreConfigurationBuilder<?, S> builder) { super(builder); } private String connectionUrl; private String driverClass; private String username; private String password; @Override public void validate() { } @Override public void validate(GlobalConfiguration globalConfig) { } @Override public SharedConnectionFactoryConfiguration create() { return new SharedConnectionFactoryConfiguration(connectionUrl, driverClass, username, password); } @Override public Builder<?> read(SharedConnectionFactoryConfiguration template) { this.connectionUrl = template.connectionUrl(); this.driverClass = template.driverClass(); this.username = template.username(); this.password = template.password(); return this; } public Builder<?> read(PooledConnectionFactoryConfiguration template) { this.connectionUrl = template.connectionUrl(); this.driverClass = template.driverClass(); this.username = template.username(); this.password = template.password(); return this; } } }