package org.infinispan.spring.provider.sample; import java.util.Random; import org.infinispan.Cache; import org.infinispan.notifications.Listener; import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated; import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved; import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent; import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent; import org.infinispan.spring.provider.SpringEmbeddedCacheManager; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * <p> * A test that tries to illustrate how Spring handles the caching aspects we added to * {@link JdbcBookDao <code>JdbcBookDao</code>}. It calls each method defined on {@link BookDao * <code>BookDao</code>} and verifies that book instances are indeed cached and removed from the * cache as specified. * </p> * * @author <a href="mailto:olaf DOT bergner AT gmx DOT de">Olaf Bergner</a> * @author Marius Bogoevici * @since 5.1 */ @Test(testName = "spring.provider.CachingBookDaoContextTest", groups = "integration") @DirtiesContext(classMode = ClassMode.AFTER_CLASS) @ContextConfiguration("classpath:/org/infinispan/spring/provider/sample/CachingBookDaoContextTest.xml") public class CachingBookDaoContextTest extends AbstractTestNGSpringContextTests { private final Log log = LogFactory.getLog(getClass()); @Autowired(required = true) private BookDao bookDao; @Autowired(required = true) private SpringEmbeddedCacheManager booksCacheManager; @BeforeClass public void installCacheListener() { booksCache().addListener(this.new LoggingListener()); } @AfterMethod public void clearBookCache() { booksCache().clear(); } @Listener public class LoggingListener { @CacheEntryCreated public void onCacheEntryCreated(CacheEntryCreatedEvent<Object, Object> cacheEntryCreated) { if (!cacheEntryCreated.isPre()) log.infof("Object cached: [Key = %s | Event = %s]", cacheEntryCreated.getKey(), cacheEntryCreated); } @CacheEntryRemoved public void onCacheEntryRemoved(CacheEntryRemovedEvent<Object, Object> cacheEntryRemoved) { if (cacheEntryRemoved.isPre()) log.infof("Object removed from cache: [Key = %s | Event = %s]", cacheEntryRemoved.getKey(), cacheEntryRemoved); } } /** * Demonstrates that loading a {@link Book <code>book</code>} via * {@link JdbcBookDao#findBook(Integer)} does indeed cache the returned book instance under the * supplied bookId. * */ @Test public void demonstrateCachingLoadedBooks() { final Integer bookToCacheId = Integer.valueOf(5); assert booksCache().isEmpty() : "Cache should initially not contain any books"; final Book cachedBook = this.bookDao.findBook(bookToCacheId); this.log.infof("Book [%s] cached", cachedBook); assert booksCache().values().contains(cachedBook) : "findBook(" + bookToCacheId + ") should have cached book"; } /** * Demonstrate that removing a {@link Book <code>book</code>} from database via * {@link JdbcBookDao#deleteBook(Integer)} does indeed remove it from cache also. * */ @Test public void demonstrateRemovingBookFromCache() { final Integer bookToDeleteId = Integer.valueOf(new Random().nextInt(10) + 1); assert booksCache().isEmpty() : "Cache should initially not contain any books"; final Book bookToDelete = this.bookDao.findBook(bookToDeleteId); this.log.infof("Book [%s] cached", bookToDelete); assert booksCache().values().contains(bookToDelete) : "findBook(" + bookToDeleteId + ") should have cached book"; this.log.infof("Deleting book [%s] ...", bookToDelete); this.bookDao.deleteBook(bookToDeleteId); this.log.infof("Book [%s] deleted", bookToDelete); assert !booksCache().values().contains(bookToDelete) : "deleteBook(" + bookToDelete + ") should have evicted book from cache."; } /** * Demonstrates that updating a {@link Book <code>book</code>} that has already been persisted to * database via {@link JdbcBookDao#storeBook(Book)} does indeed evict that book from cache. * */ @Test public void demonstrateCacheEvictionUponUpdate() { final Integer bookToUpdateId = Integer.valueOf(2); assert booksCache().isEmpty() : "Cache should initially not contain any books"; this.log.infof("Caching book [ID = %d]", bookToUpdateId); final Book bookToUpdate = this.bookDao.findBook(bookToUpdateId); assert booksCache().values().contains(bookToUpdate) : "findBook(" + bookToUpdateId + ") should have cached book"; this.log.infof("Updating book [%s] ...", bookToUpdate); bookToUpdate.setTitle("Work in Progress"); this.bookDao.storeBook(bookToUpdate); this.log.infof("Book [%s] updated", bookToUpdate); assert !booksCache().values().contains(bookToUpdate) : "storeBook(" + bookToUpdate + ") should have removed updated book from cache"; } private Cache<?,?> booksCache() { return (Cache)this.booksCacheManager.getCache("books").getNativeCache(); } }