package org.infinispan.expiry; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.TransactionManager; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.expiration.ExpirationManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.notifications.Listener; import org.infinispan.notifications.cachelistener.annotation.CacheEntryExpired; import org.infinispan.notifications.cachelistener.event.CacheEntryExpiredEvent; import org.infinispan.test.SingleCacheManagerTest; import org.infinispan.test.TestingUtil; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.infinispan.transaction.TransactionMode; import org.infinispan.transaction.lookup.EmbeddedTransactionManagerLookup; import org.infinispan.util.ControlledTimeService; import org.infinispan.util.TimeService; import org.infinispan.util.concurrent.IsolationLevel; import org.testng.annotations.Test; @Test(groups = "functional", testName = "expiry.AutoCommitExpiryTest") public abstract class AutoCommitExpiryTest extends SingleCacheManagerTest { private final CacheMode mode; private final boolean autoCommit; protected ControlledTimeService timeService; protected AutoCommitExpiryTest(CacheMode mode, boolean autoCommit) { this.mode = mode; this.autoCommit = autoCommit; } @Test public void testNoAutCommitAndExpiryListener() throws SystemException, NotSupportedException, HeuristicRollbackException, HeuristicMixedException, RollbackException { ExpiryListener expiryListener = new ExpiryListener(); Cache<String, String> applicationCache = cacheManager.getCache(); applicationCache.addListener(expiryListener); TransactionManager tm = applicationCache.getAdvancedCache().getTransactionManager(); tm.begin(); applicationCache.put("test1", "value1", 1, TimeUnit.SECONDS); tm.commit(); tm.begin(); applicationCache.put("test2", "value2", 1, TimeUnit.SECONDS); tm.commit(); timeService.advance(TimeUnit.SECONDS.toMillis(10)); ExpirationManager manager = applicationCache.getAdvancedCache().getExpirationManager(); manager.processExpiration(); eventually(() -> 2 == expiryListener.getCount()); } @Override protected EmbeddedCacheManager createCacheManager() throws Exception { ConfigurationBuilder builder = new ConfigurationBuilder(); if (mode.isClustered()) { builder.clustering().cacheMode(mode); } builder .jmxStatistics().enable() .transaction() .transactionMode(TransactionMode.TRANSACTIONAL) .transactionManagerLookup(new EmbeddedTransactionManagerLookup()) .autoCommit(autoCommit) .locking().isolationLevel(IsolationLevel.READ_COMMITTED); EmbeddedCacheManager cm = TestCacheManagerFactory.createClusteredCacheManager(builder); timeService = new ControlledTimeService(); TestingUtil.replaceComponent(cm, TimeService.class, timeService, true); return cm; } @Listener(primaryOnly = true, observation = Listener.Observation.POST) public class ExpiryListener { private final AtomicInteger counter = new AtomicInteger(); public int getCount() { return counter.get(); } @CacheEntryExpired public void expired(CacheEntryExpiredEvent<String, String> event) { counter.incrementAndGet(); } } }