Skip to content

Commit 52e33e7

Browse files
committed
Initial commit
0 parents  commit 52e33e7

File tree

8 files changed

+391
-0
lines changed

8 files changed

+391
-0
lines changed

.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
target/
2+
!.mvn/wrapper/maven-wrapper.jar
3+
4+
### STS ###
5+
.apt_generated
6+
.classpath
7+
.factorypath
8+
.project
9+
.settings
10+
.springBeans
11+
12+
### IntelliJ IDEA ###
13+
.idea
14+
*.iws
15+
*.iml
16+
*.ipr
17+
18+
### NetBeans ###
19+
nbproject/private/
20+
build/
21+
nbbuild/
22+
dist/
23+
nbdist/
24+
.nb-gradle/

pom.xml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.mvpjava</groupId>
7+
<artifactId>cacheTutorial</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
<packaging>jar</packaging>
10+
11+
<name>cacheTutorial</name>
12+
<description>Demo project for Spring Boot</description>
13+
14+
<parent>
15+
<groupId>org.springframework.boot</groupId>
16+
<artifactId>spring-boot-starter-parent</artifactId>
17+
<version>1.4.1.RELEASE</version>
18+
<relativePath/> <!-- lookup parent from repository -->
19+
</parent>
20+
21+
<properties>
22+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24+
<java.version>1.8</java.version>
25+
</properties>
26+
27+
<dependencies>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-cache</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-data-mongodb</artifactId>
35+
</dependency>
36+
37+
<dependency>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-starter-test</artifactId>
40+
<scope>test</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>com.github.ben-manes.caffeine</groupId>
44+
<artifactId>caffeine</artifactId>
45+
<version>2.3.3</version>
46+
</dependency>
47+
</dependencies>
48+
49+
<build>
50+
<plugins>
51+
<plugin>
52+
<groupId>org.springframework.boot</groupId>
53+
<artifactId>spring-boot-maven-plugin</artifactId>
54+
</plugin>
55+
</plugins>
56+
</build>
57+
58+
59+
</project>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.mvpjava;
2+
3+
import java.util.Objects;
4+
import org.springframework.data.annotation.Id;
5+
import org.springframework.data.mongodb.core.index.Indexed;
6+
import org.springframework.data.mongodb.core.mapping.Document;
7+
8+
@Document
9+
public class Aircraft {
10+
11+
@Id private String id; //mongoID
12+
@Indexed(unique = true) private final String model;
13+
private int topSpeed;
14+
15+
public Aircraft(String model) {
16+
this.model = model;
17+
}
18+
19+
public String getId() {
20+
return id;
21+
}
22+
23+
public String getModel() {
24+
return model;
25+
}
26+
27+
public int getTopSpeed() {
28+
return topSpeed;
29+
}
30+
31+
public Aircraft setTopSpeed(int topSpeed) {
32+
this.topSpeed = topSpeed;
33+
return this;
34+
}
35+
36+
37+
@Override
38+
public int hashCode() {
39+
int hash = 7;
40+
hash = 89 * hash + Objects.hashCode(this.model);
41+
hash = 89 * hash + this.topSpeed;
42+
return hash;
43+
}
44+
45+
@Override
46+
public boolean equals(Object obj) {
47+
if (this == obj) {
48+
return true;
49+
}
50+
if (obj == null) {
51+
return false;
52+
}
53+
if (getClass() != obj.getClass()) {
54+
return false;
55+
}
56+
final Aircraft other = (Aircraft) obj;
57+
if (this.topSpeed != other.topSpeed) {
58+
return false;
59+
}
60+
if (!Objects.equals(this.model, other.model)) {
61+
return false;
62+
}
63+
return true;
64+
}
65+
66+
@Override
67+
public String toString() {
68+
return "Aircraft{" + "model=" + model + ", topSpeed=" + topSpeed + '}';
69+
}
70+
71+
72+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.mvpjava;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.cache.annotation.CacheConfig;
7+
import org.springframework.cache.annotation.CacheEvict;
8+
import org.springframework.cache.annotation.CachePut;
9+
import org.springframework.cache.annotation.Cacheable;
10+
import org.springframework.cache.annotation.Caching;
11+
import org.springframework.dao.DuplicateKeyException;
12+
import org.springframework.data.mongodb.core.MongoTemplate;
13+
import org.springframework.data.mongodb.core.query.Criteria;
14+
import org.springframework.data.mongodb.core.query.Query;
15+
import org.springframework.stereotype.Component;
16+
17+
@Component
18+
@CacheConfig(cacheNames = {"AIRCRAFTS"})
19+
public class AircraftService {
20+
21+
private static final Logger logger = LoggerFactory.getLogger(AircraftService.class);
22+
private final MongoTemplate template;
23+
private final String mongoCollection = "aircraft";
24+
25+
@Autowired
26+
public AircraftService(MongoTemplate template) {
27+
this.template = template;
28+
}
29+
30+
@Cacheable(unless = "#result == null")
31+
public Aircraft getAircraftByModelName(String modelName) {
32+
logger.info("Executing getAircraftByModelName for model:{} \tCache MISS!", modelName);
33+
slowDownForDemo();
34+
Query query = new Query(Criteria.where("model").is(modelName));
35+
return template.findOne(query, Aircraft.class, mongoCollection);
36+
}
37+
38+
@CachePut(key = "#aircraft.model", condition = "#aircraft.topSpeed > 0", unless = "#result == null")
39+
public Aircraft createAircraft(Aircraft aircraft) {
40+
logger.info("Executing createAircraft, model:{}", aircraft.getModel());
41+
try {
42+
template.insert(aircraft, mongoCollection);
43+
} catch (DuplicateKeyException dke) {
44+
//OK for demo
45+
}
46+
return template.findOne(
47+
new Query(Criteria.where("model").is(aircraft.getModel())),
48+
Aircraft.class, mongoCollection);//has id
49+
}
50+
51+
@CacheEvict(key = "#aircraft.model")
52+
public void updateAircraft(Aircraft aircraft) {
53+
logger.info("Executing updateAircraft, model:{} topSpeed: {} Cache Evict!",
54+
aircraft.getModel(), aircraft.getTopSpeed());
55+
try {
56+
template.save(aircraft, mongoCollection);
57+
} catch (DuplicateKeyException dke) {
58+
//OK for demo
59+
}
60+
}
61+
62+
@CacheEvict(key = "#aircraft.model")
63+
public void removeAircraft(Aircraft aircraft) {
64+
logger.info("Executing removeAircraft, model:{} \tCache Evict!", aircraft.getModel());
65+
template.remove(aircraft, mongoCollection);
66+
}
67+
68+
@Caching(evict = {
69+
@CacheEvict(value = "AIRCRAFTS", allEntries = true),
70+
@CacheEvict(value = "SECOND_CACHE", allEntries = true)
71+
})
72+
public void clearAllCaches() {
73+
logger.info("Cleared all caches");
74+
}
75+
76+
77+
private void slowDownForDemo() {
78+
try {
79+
Thread.sleep(2000L);
80+
} catch (Exception e) {
81+
}
82+
}
83+
84+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.mvpjava;
2+
3+
import com.github.benmanes.caffeine.cache.Caffeine;
4+
import com.github.benmanes.caffeine.cache.CaffeineSpec;
5+
import com.github.benmanes.caffeine.cache.RemovalCause;
6+
import com.github.benmanes.caffeine.cache.RemovalListener;
7+
import java.util.concurrent.TimeUnit;
8+
import org.springframework.cache.CacheManager;
9+
import org.springframework.cache.caffeine.CaffeineCacheManager;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
13+
@Configuration
14+
public class CacheJavaConfig {
15+
/**
16+
* initialCapacity
17+
* maximumSize
18+
* maximumWeight
19+
* expireAfterAccess
20+
* expireAfterWrite
21+
* refreshAfterWrite
22+
* weakKeys
23+
* weakValues
24+
* softValues
25+
* recordStats
26+
*/
27+
@Bean
28+
public CacheManager cacheManager() {
29+
String specAsString = "initialCapacity=100,maximumSize=500,expireAfterAccess=5m,recordStats";
30+
CaffeineCacheManager cacheManager = new CaffeineCacheManager("AIRCRAFTS", "SECOND_CACHE");
31+
cacheManager.setAllowNullValues(false); //can happen if you get a value from a @Cachable that returns null
32+
//cacheManager.setCacheSpecification(specAsString);
33+
//cacheManager.setCaffeineSpec(caffeineSpec());
34+
cacheManager.setCaffeine(caffeineCacheBuilder());
35+
return cacheManager;
36+
}
37+
38+
CaffeineSpec caffeineSpec() {
39+
return CaffeineSpec.parse
40+
("initialCapacity=100,maximumSize=500,expireAfterAccess=5m,recordStats");
41+
}
42+
43+
Caffeine<Object, Object> caffeineCacheBuilder() {
44+
return Caffeine.newBuilder()
45+
.initialCapacity(100)
46+
.maximumSize(150)
47+
.expireAfterAccess(5, TimeUnit.MINUTES)
48+
.weakKeys()
49+
.removalListener(new CustomRemovalListener())
50+
.recordStats();
51+
}
52+
53+
class CustomRemovalListener implements RemovalListener<Object, Object>{
54+
@Override
55+
public void onRemoval(Object key, Object value, RemovalCause cause) {
56+
System.out.format("removal listerner called with key [%s], cause [%s], evicted [%S]\n",
57+
key, cause.toString(), cause.wasEvicted());
58+
}
59+
}
60+
61+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.mvpjava;
2+
3+
import com.github.benmanes.caffeine.cache.Cache;
4+
import com.github.benmanes.caffeine.cache.stats.CacheStats;
5+
import org.slf4j.*;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.boot.CommandLineRunner;
8+
import org.springframework.cache.CacheManager;
9+
import org.springframework.stereotype.Component;
10+
11+
@Component
12+
public class CacheTutorial implements CommandLineRunner {
13+
14+
private static final Logger logger = LoggerFactory.getLogger(CacheTutorial.class);
15+
private final AircraftService aircraftService;
16+
private final CacheManager cacheManager;
17+
18+
@Autowired
19+
public CacheTutorial(AircraftService dataService, CacheManager cacheManager) {
20+
this.aircraftService = dataService;
21+
this.cacheManager = cacheManager;
22+
}
23+
24+
@Override
25+
public void run(String... args) throws Exception {
26+
logger.info("================================================================");
27+
logger.info("Using cache Manager {}", cacheManager.getClass().getSimpleName());
28+
29+
Aircraft cessna = new Aircraft("Cessna 650").setTopSpeed(478);
30+
Aircraft aerostar = new Aircraft("Aerostar PA-602P").setTopSpeed(262);
31+
Aircraft piper = new Aircraft("Piper PA-31-300").setTopSpeed(195);
32+
33+
//store in cache upon creation
34+
aircraftService.createAircraft(cessna);
35+
aircraftService.createAircraft(aerostar);
36+
aircraftService.createAircraft(piper);
37+
38+
logger.info("Calling getAircraftByModelName() ...");
39+
aircraftService.getAircraftByModelName(cessna.getModel()); //hit
40+
logger.info("Calling getAircraftByModelName() ...");
41+
aircraftService.getAircraftByModelName(aerostar.getModel());//hit
42+
logger.info("Calling getAircraftByModelName() ...");
43+
aircraftService.getAircraftByModelName(piper.getModel());//hit
44+
45+
piper.setTopSpeed(200);
46+
47+
aircraftService.updateAircraft(piper);//evict
48+
aircraftService.getAircraftByModelName(piper.getModel());//miss
49+
aircraftService.getAircraftByModelName(piper.getModel());//hit
50+
51+
aircraftService.removeAircraft(piper);//evict
52+
aircraftService.getAircraftByModelName(piper.getModel());//miss
53+
54+
aircraftService.clearAllCaches();//evict all caches
55+
aircraftService.getAircraftByModelName(cessna.getModel()); //miss
56+
aircraftService.getAircraftByModelName(aerostar.getModel());//miss
57+
58+
logger.info(getCoffeeCacheStats().toString());
59+
logger.info("================================================================");
60+
}
61+
62+
63+
public CacheStats getCoffeeCacheStats() {
64+
org.springframework.cache.Cache cache = cacheManager.getCache("AIRCRAFTS");
65+
Cache nativeCoffeeCache = (Cache) cache.getNativeCache();
66+
// System.out.println(nativeCoffeeCache.asMap().toString());
67+
return nativeCoffeeCache.stats();
68+
}
69+
70+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.mvpjava;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.cache.annotation.EnableCaching;
6+
7+
@SpringBootApplication
8+
@EnableCaching
9+
public class Main {
10+
11+
public static void main(String[] args) {
12+
SpringApplication.run(Main.class, args);
13+
}
14+
15+
}

0 commit comments

Comments
 (0)