BAEL-1368: infinispan article (#3633)

This commit is contained in:
Allan Vital 2018-02-11 11:36:33 -02:00 committed by Predrag Maric
parent 1c043dc202
commit 6eeff13c45
9 changed files with 494 additions and 1 deletions

View File

@ -649,6 +649,11 @@
<artifactId>google-http-client-gson</artifactId>
<version>${googleclient.version}</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<version>${infinispan.version}</version>
</dependency>
<!--Java Docker API Client-->
<dependency>
@ -811,5 +816,6 @@
<docker.version>3.0.14</docker.version>
<tomcat.version>8.5.24</tomcat.version>
<async.http.client.version>2.2.0</async.http.client.version>
<infinispan.version>9.1.5.Final</infinispan.version>
</properties>
</project>
</project>

View File

@ -0,0 +1,85 @@
package com.baeldung.infinispan;
import com.baeldung.infinispan.listener.CacheListener;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.eviction.EvictionType;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.transaction.LockingMode;
import org.infinispan.transaction.TransactionMode;
import java.util.concurrent.TimeUnit;
public class CacheConfiguration {
public static final String SIMPLE_HELLO_WORLD_CACHE = "simple-hello-world-cache";
public static final String EXPIRING_HELLO_WORLD_CACHE = "expiring-hello-world-cache";
public static final String EVICTING_HELLO_WORLD_CACHE = "evicting-hello-world-cache";
public static final String PASSIVATING_HELLO_WORLD_CACHE = "passivating-hello-world-cache";
public static final String TRANSACTIONAL_CACHE = "transactional-cache";
public DefaultCacheManager cacheManager() {
DefaultCacheManager cacheManager = new DefaultCacheManager();
return cacheManager;
}
public Cache<String, Integer> transactionalCache(DefaultCacheManager cacheManager, CacheListener listener) {
return this.buildCache(TRANSACTIONAL_CACHE, cacheManager, listener, transactionalConfiguration());
}
public Cache<String, String> simpleHelloWorldCache(DefaultCacheManager cacheManager, CacheListener listener) {
return this.buildCache(SIMPLE_HELLO_WORLD_CACHE, cacheManager, listener, new ConfigurationBuilder().build());
}
public Cache<String, String> expiringHelloWorldCache(DefaultCacheManager cacheManager, CacheListener listener) {
return this.buildCache(EXPIRING_HELLO_WORLD_CACHE, cacheManager, listener, expiringConfiguration());
}
public Cache<String, String> evictingHelloWorldCache(DefaultCacheManager cacheManager, CacheListener listener) {
return this.buildCache(EVICTING_HELLO_WORLD_CACHE, cacheManager, listener, evictingConfiguration());
}
public Cache<String, String> passivatingHelloWorldCache(DefaultCacheManager cacheManager, CacheListener listener) {
return this.buildCache(PASSIVATING_HELLO_WORLD_CACHE, cacheManager, listener, passivatingConfiguration());
}
private <K, V> Cache<K, V> buildCache(String cacheName, DefaultCacheManager cacheManager,
CacheListener listener, Configuration configuration) {
cacheManager.defineConfiguration(cacheName, configuration);
Cache<K, V> cache = cacheManager.getCache(cacheName);
cache.addListener(listener);
return cache;
}
private Configuration expiringConfiguration() {
return new ConfigurationBuilder().expiration().lifespan(1, TimeUnit.SECONDS)
.build();
}
private Configuration evictingConfiguration() {
return new ConfigurationBuilder()
.memory().evictionType(EvictionType.COUNT).size(1)
.build();
}
private Configuration passivatingConfiguration() {
return new ConfigurationBuilder()
.memory().evictionType(EvictionType.COUNT).size(1)
.persistence()
.passivation(true)
.addSingleFileStore()
.purgeOnStartup(true)
.location(System.getProperty("java.io.tmpdir"))
.build();
}
private Configuration transactionalConfiguration() {
return new ConfigurationBuilder()
.transaction().transactionMode(TransactionMode.TRANSACTIONAL)
.lockingMode(LockingMode.PESSIMISTIC)
.build();
}
}

View File

@ -0,0 +1,55 @@
package com.baeldung.infinispan.listener;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.*;
import org.infinispan.notifications.cachelistener.event.*;
@Listener
public class CacheListener {
@CacheEntryCreated
public void entryCreated(CacheEntryCreatedEvent<String, String> event) {
this.printLog("Adding key '" + event.getKey() + "' to cache", event);
}
@CacheEntryExpired
public void entryExpired(CacheEntryExpiredEvent<String, String> event) {
this.printLog("Expiring key '" + event.getKey() + "' from cache", event);
}
@CacheEntryVisited
public void entryVisited(CacheEntryVisitedEvent<String, String> event) {
this.printLog("Key '" + event.getKey() + "' was visited", event);
}
@CacheEntryActivated
public void entryActivated(CacheEntryActivatedEvent<String, String> event) {
this.printLog("Activating key '" + event.getKey() + "' on cache", event);
}
@CacheEntryPassivated
public void entryPassivated(CacheEntryPassivatedEvent<String, String> event) {
this.printLog("Passivating key '" + event.getKey() + "' from cache", event);
}
@CacheEntryLoaded
public void entryLoaded(CacheEntryLoadedEvent<String, String> event) {
this.printLog("Loading key '" + event.getKey() + "' to cache", event);
}
@CacheEntriesEvicted
public void entriesEvicted(CacheEntriesEvictedEvent<String, String> event) {
final StringBuilder builder = new StringBuilder();
event.getEntries().entrySet().forEach((e) ->
builder.append(e.getKey() + ", ")
);
System.out.println("Evicting following entries from cache: " + builder.toString());
}
private void printLog(String log, CacheEntryEvent event) {
if (!event.isPre()) {
System.out.println(log);
}
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.infinispan.repository;
public class HelloWorldRepository {
public String getHelloWorld() {
try {
System.out.println("Executing some heavy query");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello World!";
}
}

View File

@ -0,0 +1,90 @@
package com.baeldung.infinispan.service;
import com.baeldung.infinispan.listener.CacheListener;
import com.baeldung.infinispan.repository.HelloWorldRepository;
import org.infinispan.Cache;
import java.util.concurrent.TimeUnit;
public class HelloWorldService {
private final HelloWorldRepository repository;
private final Cache<String, String> simpleHelloWorldCache;
private final Cache<String, String> expiringHelloWorldCache;
private final Cache<String, String> evictingHelloWorldCache;
private final Cache<String, String> passivatingHelloWorldCache;
public HelloWorldService(HelloWorldRepository repository, CacheListener listener,
Cache<String, String> simpleHelloWorldCache,
Cache<String, String> expiringHelloWorldCache,
Cache<String, String> evictingHelloWorldCache,
Cache<String, String> passivatingHelloWorldCache) {
this.repository = repository;
this.simpleHelloWorldCache = simpleHelloWorldCache;
this.expiringHelloWorldCache = expiringHelloWorldCache;
this.evictingHelloWorldCache = evictingHelloWorldCache;
this.passivatingHelloWorldCache = passivatingHelloWorldCache;
}
public String findSimpleHelloWorld() {
String cacheKey = "simple-hello";
String helloWorld = simpleHelloWorldCache.get(cacheKey);
if (helloWorld == null) {
helloWorld = repository.getHelloWorld();
simpleHelloWorldCache.put(cacheKey, helloWorld);
}
return helloWorld;
}
public String findExpiringHelloWorld() {
String cacheKey = "expiring-hello";
String helloWorld = simpleHelloWorldCache.get(cacheKey);
if (helloWorld == null) {
helloWorld = repository.getHelloWorld();
simpleHelloWorldCache.put(cacheKey, helloWorld, 1, TimeUnit.SECONDS);
}
return helloWorld;
}
public String findIdleHelloWorld() {
String cacheKey = "idle-hello";
String helloWorld = simpleHelloWorldCache.get(cacheKey);
if (helloWorld == null) {
helloWorld = repository.getHelloWorld();
simpleHelloWorldCache.put(cacheKey, helloWorld, -1, TimeUnit.SECONDS, 10, TimeUnit.SECONDS);
}
return helloWorld;
}
public String findSimpleHelloWorldInExpiringCache() {
String cacheKey = "simple-hello";
String helloWorld = expiringHelloWorldCache.get(cacheKey);
if (helloWorld == null) {
helloWorld = repository.getHelloWorld();
expiringHelloWorldCache.put(cacheKey, helloWorld);
}
return helloWorld;
}
public String findEvictingHelloWorld(String key) {
String value = evictingHelloWorldCache.get(key);
if(value == null) {
value = repository.getHelloWorld();
evictingHelloWorldCache.put(key, value);
}
return value;
}
public String findPassivatingHelloWorld(String key) {
String value = passivatingHelloWorldCache.get(key);
if(value == null) {
value = repository.getHelloWorld();
passivatingHelloWorldCache.put(key, value);
}
return value;
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.infinispan.service;
import org.infinispan.Cache;
import org.springframework.util.StopWatch;
import javax.transaction.TransactionManager;
public class TransactionalService {
private final Cache<String, Integer> transactionalCache;
private static final String KEY = "key";
public TransactionalService(Cache<String, Integer> transactionalCache) {
this.transactionalCache = transactionalCache;
transactionalCache.put(KEY, 0);
}
public Integer getQuickHowManyVisits() {
try {
TransactionManager tm = transactionalCache.getAdvancedCache().getTransactionManager();
tm.begin();
Integer howManyVisits = transactionalCache.get(KEY);
howManyVisits++;
System.out.println("Ill try to set HowManyVisits to " + howManyVisits);
StopWatch watch = new StopWatch();
watch.start();
transactionalCache.put(KEY, howManyVisits);
watch.stop();
System.out.println("I was able to set HowManyVisits to " + howManyVisits +
" after waiting " + watch.getTotalTimeSeconds() + " seconds");
tm.commit();
return howManyVisits;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public void startBackgroundBatch() {
try {
TransactionManager tm = transactionalCache.getAdvancedCache().getTransactionManager();
tm.begin();
transactionalCache.put(KEY, 1000);
System.out.println("HowManyVisits should now be 1000, " +
"but we are holding the transaction");
Thread.sleep(1000L);
tm.rollback();
System.out.println("The slow batch suffered a rollback");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,56 @@
package com.baeldung.infinispan;
import com.baeldung.infinispan.listener.CacheListener;
import com.baeldung.infinispan.repository.HelloWorldRepository;
import com.baeldung.infinispan.service.HelloWorldService;
import com.baeldung.infinispan.service.TransactionalService;
import org.infinispan.Cache;
import org.infinispan.manager.DefaultCacheManager;
import org.junit.After;
import org.junit.Before;
public class ConfigurationTest {
private DefaultCacheManager cacheManager;
private HelloWorldRepository repository = new HelloWorldRepository();
protected HelloWorldService helloWorldService;
protected TransactionalService transactionalService;
@Before
public void setup() {
CacheConfiguration configuration = new CacheConfiguration();
CacheListener listener = new CacheListener();
cacheManager = configuration.cacheManager();
Cache<String, Integer> transactionalCache =
configuration.transactionalCache(cacheManager, listener);
Cache<String, String> simpleHelloWorldCache =
configuration.simpleHelloWorldCache(cacheManager, listener);
Cache<String, String> expiringHelloWorldCache =
configuration.expiringHelloWorldCache(cacheManager, listener);
Cache<String, String> evictingHelloWorldCache =
configuration.evictingHelloWorldCache(cacheManager, listener);
Cache<String, String> passivatingHelloWorldCache =
configuration.passivatingHelloWorldCache(cacheManager, listener);
this.helloWorldService = new HelloWorldService(repository,
listener, simpleHelloWorldCache, expiringHelloWorldCache, evictingHelloWorldCache,
passivatingHelloWorldCache);
this.transactionalService = new TransactionalService(transactionalCache);
}
@After
public void tearDown() {
cacheManager.stop();
}
}

View File

@ -0,0 +1,105 @@
package com.baeldung.infinispan.service;
import com.baeldung.infinispan.ConfigurationTest;
import org.junit.Test;
import static org.assertj.core.api.Java6Assertions.assertThat;
public class HelloWorldServiceUnitTest extends ConfigurationTest {
@Test
public void whenGetIsCalledTwoTimes_thenTheSecondShouldHitTheCache() {
long milis = System.currentTimeMillis();
helloWorldService.findSimpleHelloWorld();
long executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
milis = System.currentTimeMillis();
helloWorldService.findSimpleHelloWorld();
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isLessThan(100);
}
@Test
public void whenGetIsCalledTwoTimesQuickly_thenTheSecondShouldHitTheCache() {
long milis = System.currentTimeMillis();
helloWorldService.findExpiringHelloWorld();
long executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
milis = System.currentTimeMillis();
helloWorldService.findExpiringHelloWorld();
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isLessThan(100);
}
@Test
public void whenGetIsCalledTwoTimesSparsely_thenNeitherShouldHitTheCache()
throws InterruptedException {
long milis = System.currentTimeMillis();
helloWorldService.findSimpleHelloWorldInExpiringCache();
long executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
Thread.sleep(1100);
milis = System.currentTimeMillis();
helloWorldService.findSimpleHelloWorldInExpiringCache();
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
}
@Test
public void givenOneEntryIsConfigured_whenTwoAreAdded_thenFirstShouldntBeAvailable()
throws InterruptedException {
long milis = System.currentTimeMillis();
helloWorldService.findEvictingHelloWorld("key 1");
long executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
milis = System.currentTimeMillis();
helloWorldService.findEvictingHelloWorld("key 2");
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
milis = System.currentTimeMillis();
helloWorldService.findEvictingHelloWorld("key 1");
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
}
@Test
public void givenOneEntryIsConfigured_whenTwoAreAdded_thenTheFirstShouldBeAvailable()
throws InterruptedException {
long milis = System.currentTimeMillis();
helloWorldService.findPassivatingHelloWorld("key 1");
long executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
milis = System.currentTimeMillis();
helloWorldService.findPassivatingHelloWorld("key 2");
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThanOrEqualTo(1000);
milis = System.currentTimeMillis();
helloWorldService.findPassivatingHelloWorld("key 1");
executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isLessThan(100);
}
}

View File

@ -0,0 +1,24 @@
package com.baeldung.infinispan.service;
import com.baeldung.infinispan.ConfigurationTest;
import org.junit.Test;
import static org.assertj.core.api.Java6Assertions.assertThat;
public class TransactionalServiceUnitTest extends ConfigurationTest {
@Test
public void whenLockingAnEntry_thenItShouldBeInaccessible() throws InterruptedException {
Runnable backGroundJob = () -> transactionalService.startBackgroundBatch();
Thread backgroundThread = new Thread(backGroundJob);
transactionalService.getQuickHowManyVisits();
backgroundThread.start();
Thread.sleep(100); //lets wait our thread warm up
long milis = System.currentTimeMillis();
transactionalService.getQuickHowManyVisits();
long executionTime = System.currentTimeMillis() - milis;
assertThat(executionTime).isGreaterThan(500).isLessThan(1000);
}
}