diff --git a/pom.xml b/pom.xml
index d96b6c77..9431c5d4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,7 +35,7 @@
UTF-8
UTF-8
- -ea -Xms128m -Xmx512m -Dspring.profiles.active=test,metrics -Dfile.encoding=UTF-8
+ -ea -Xms128m -Xmx512m -Dspring.profiles.active=test,metrics,embeddedcache -Dfile.encoding=UTF-8
-Djava.awt.headless=true -XX:CompileThreshold=1500
@@ -69,6 +69,9 @@
1.8.13
+
+ 2.9.0
+
2.0.0.RELEASE
5.0.4.RELEASE
@@ -77,6 +80,7 @@
5.0.3.RELEASE
4.0.1.RELEASE
2.0.0.RELEASE
+ 2.0.5.RELEASE
3.7
2.7.0
@@ -200,6 +204,20 @@
${aspectjrt.version}
+
+
+
+
+ org.springframework.data
+ spring-data-redis
+ ${spring-data-redis.version}
+
+
+ redis.clients
+ jedis
+ ${jedis.version}
+
+
diff --git a/src/main/java/manon/Application.java b/src/main/java/manon/Application.java
index 70317d84..0fc4fe95 100644
--- a/src/main/java/manon/Application.java
+++ b/src/main/java/manon/Application.java
@@ -11,6 +11,8 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.EnableCaching;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
import org.springframework.scheduling.annotation.EnableScheduling;
@@ -20,12 +22,14 @@
import java.util.List;
import static manon.app.config.SpringProfiles.METRICS;
+import static manon.app.info.service.InfoServiceImpl.CACHE_GET_APPVERSION;
import static manon.app.trace.document.AppTrace.Event.APP_START;
import static manon.app.trace.document.AppTrace.Level.INFO;
@SpringBootApplication
@EnableMongoAuditing
@EnableScheduling
+@EnableCaching
@Slf4j
@RequiredArgsConstructor
public class Application extends SpringBootServletInitializer {
@@ -45,6 +49,7 @@ protected SpringApplicationBuilder configure(SpringApplicationBuilder applicatio
}
@PostConstruct
+ @CacheEvict(value = CACHE_GET_APPVERSION, allEntries = true)
public void initApp() throws UserExistsException {
String initAppEvent = "Admin username is " + userAdminService.ensureAdmin().getUsername();
appTraceService.log(INFO, APP_START, initAppEvent);
diff --git a/src/main/java/manon/app/cache/CommonCacheConfig.java b/src/main/java/manon/app/cache/CommonCacheConfig.java
new file mode 100644
index 00000000..98d742e4
--- /dev/null
+++ b/src/main/java/manon/app/cache/CommonCacheConfig.java
@@ -0,0 +1,28 @@
+package manon.app.cache;
+
+import org.jetbrains.annotations.NotNull;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class CommonCacheConfig {
+
+ /** Key generator name: generate a unique key of the class name, the method name, and all method parameters appended. */
+ public static final String KEY_GENERATOR_FULL = "KEY_GENERATOR_FULL";
+
+ /** Generate a unique key of the class name, the method name, and all method parameters appended. */
+ @NotNull
+ @Bean(name = KEY_GENERATOR_FULL)
+ public KeyGenerator keyGenerator() {
+ return (o, method, objects) -> {
+ StringBuilder sb = new StringBuilder();
+ sb.append(o.getClass().getName());
+ sb.append(method.getName());
+ for (Object obj : objects) {
+ sb.append(obj.toString());
+ }
+ return sb.toString();
+ };
+ }
+}
diff --git a/src/main/java/manon/app/cache/EmbeddedCacheConfig.java b/src/main/java/manon/app/cache/EmbeddedCacheConfig.java
new file mode 100644
index 00000000..f9f6d6e1
--- /dev/null
+++ b/src/main/java/manon/app/cache/EmbeddedCacheConfig.java
@@ -0,0 +1,22 @@
+package manon.app.cache;
+
+import org.jetbrains.annotations.NotNull;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import static manon.app.config.SpringProfiles.EMBEDDED_CACHE;
+
+@Configuration
+@Profile(EMBEDDED_CACHE)
+public class EmbeddedCacheConfig extends CachingConfigurerSupport {
+
+ @NotNull
+ @Bean
+ public CacheManager cacheManager() {
+ return new ConcurrentMapCacheManager();
+ }
+}
diff --git a/src/main/java/manon/app/cache/RedisCacheConfig.java b/src/main/java/manon/app/cache/RedisCacheConfig.java
new file mode 100644
index 00000000..34bf2f4e
--- /dev/null
+++ b/src/main/java/manon/app/cache/RedisCacheConfig.java
@@ -0,0 +1,28 @@
+package manon.app.cache;
+
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import java.time.Duration;
+
+import static manon.app.config.SpringProfiles.REDIS_CACHE;
+
+@Configuration
+@Profile(REDIS_CACHE)
+public class RedisCacheConfig extends CachingConfigurerSupport {
+
+ @Bean
+ public RedisCacheManager cacheManager(RedisTemplate redisTemplate) {
+ RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofDays(1))
+ .prefixKeysWith("manon_");
+ return RedisCacheManager.builder(redisTemplate.getConnectionFactory())
+ .cacheDefaults(config)
+ .build();
+ }
+}
diff --git a/src/main/java/manon/app/config/SpringProfiles.java b/src/main/java/manon/app/config/SpringProfiles.java
index 7071b870..1477b79e 100644
--- a/src/main/java/manon/app/config/SpringProfiles.java
+++ b/src/main/java/manon/app/config/SpringProfiles.java
@@ -7,5 +7,11 @@ public interface SpringProfiles {
String METRICS = "metrics";
/** {@value}. */
- String NO_METRICS = "!metrics";
+ String NOT_METRICS = "!metrics";
+
+ /** {@value}. */
+ String REDIS_CACHE = "!embeddedcache";
+
+ /** {@value}. */
+ String EMBEDDED_CACHE = "embeddedcache";
}
diff --git a/src/main/java/manon/app/config/WebConfig.java b/src/main/java/manon/app/config/WebConfig.java
index 8f5ab1ed..8238fffb 100644
--- a/src/main/java/manon/app/config/WebConfig.java
+++ b/src/main/java/manon/app/config/WebConfig.java
@@ -6,13 +6,13 @@
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@EnableAsync
-public class WebConfig extends WebMvcConfigurerAdapter {
+public class WebConfig implements WebMvcConfigurer {
public WebConfig() {
super();
diff --git a/src/main/java/manon/app/info/service/InfoServiceImpl.java b/src/main/java/manon/app/info/service/InfoServiceImpl.java
index 27758ae2..b9899464 100644
--- a/src/main/java/manon/app/info/service/InfoServiceImpl.java
+++ b/src/main/java/manon/app/info/service/InfoServiceImpl.java
@@ -2,6 +2,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
@@ -10,9 +11,12 @@
@PropertySource(value = "classpath:info.properties")
public class InfoServiceImpl implements InfoService {
+ public static final String CACHE_GET_APPVERSION = "CACHE_GET_APPVERSION";
+
@Value("${version}")
private String version;
+ @Cacheable(CACHE_GET_APPVERSION)
@Override
public String getAppVersion() {
return version;
diff --git a/src/main/java/manon/app/stats/service/NoPerformanceRecorder.java b/src/main/java/manon/app/stats/service/NoPerformanceRecorder.java
index ca2da416..64f2dc94 100644
--- a/src/main/java/manon/app/stats/service/NoPerformanceRecorder.java
+++ b/src/main/java/manon/app/stats/service/NoPerformanceRecorder.java
@@ -3,10 +3,10 @@
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
-import static manon.app.config.SpringProfiles.NO_METRICS;
+import static manon.app.config.SpringProfiles.NOT_METRICS;
@Service
-@Profile(NO_METRICS)
+@Profile(NOT_METRICS)
public class NoPerformanceRecorder implements PerformanceRecorder {
@Override
diff --git a/src/main/java/manon/user/friendship/service/FriendshipServiceImpl.java b/src/main/java/manon/user/friendship/service/FriendshipServiceImpl.java
index 15484d23..6a03ae18 100644
--- a/src/main/java/manon/user/friendship/service/FriendshipServiceImpl.java
+++ b/src/main/java/manon/user/friendship/service/FriendshipServiceImpl.java
@@ -20,7 +20,7 @@ public class FriendshipServiceImpl implements FriendshipService {
private final UserService userService;
@Override
- public void keepEvents(String... ids) throws UserNotFoundException {
+ public void keepEvents(String... ids) {
for (String id : ids) {
userRepository.keepEvents(id, MAX_EVENTS);
}
@@ -54,19 +54,19 @@ public void acceptFriendshipRequest(String userIdFrom, String userIdTo)
}
@Override
- public void rejectFriendshipRequest(String userIdFrom, String userIdTo) throws UserNotFoundException {
+ public void rejectFriendshipRequest(String userIdFrom, String userIdTo) {
userRepository.rejectFriendshipRequest(userIdFrom, userIdTo);
keepEvents(userIdFrom, userIdTo);
}
@Override
- public void cancelFriendshipRequest(String userIdFrom, String userIdTo) throws UserNotFoundException {
+ public void cancelFriendshipRequest(String userIdFrom, String userIdTo) {
userRepository.cancelFriendshipRequest(userIdFrom, userIdTo);
keepEvents(userIdFrom, userIdTo);
}
@Override
- public void revokeFriendship(String userIdFrom, String userIdTo) throws UserNotFoundException {
+ public void revokeFriendship(String userIdFrom, String userIdTo) {
userRepository.revokeFriendship(userIdFrom, userIdTo);
keepEvents(userIdFrom, userIdTo);
}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 40fb18fe..93937624 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -15,3 +15,7 @@ spring:
password: woot
url: jdbc:mysql://127.0.0.1:3307/manon_dev?useUnicode=true&characterEncoding=utf8&autoReconnect=true
jpa.hibernate.ddl-auto: create-drop
+ redis:
+ database: 2
+ host: localhost
+ port: 6379
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index f314824e..292fad40 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -9,6 +9,10 @@ spring:
username: ${MANON_PROD_MONGODB_USERNAME}
password: ${MANON_PROD_MONGODB_PASSWORD}
authentication-database: ${MANON_PROD_MONGODB_AUTH_DB_NAME}
+ redis:
+ database: ${MANON_PROD_REDIS_DB_NUMBER}
+ host: ${MANON_PROD_REDIS_HOST}
+ port: ${MANON_PROD_REDIS_PORT}
manon:
admin:
diff --git a/src/test/java/manon/app/actuator/ActuatorTest.java b/src/test/java/manon/app/actuator/ActuatorTest.java
index 93801dbe..e22d9c1a 100644
--- a/src/test/java/manon/app/actuator/ActuatorTest.java
+++ b/src/test/java/manon/app/actuator/ActuatorTest.java
@@ -15,6 +15,7 @@
import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalToIgnoringWhiteSpace;
+import static org.hamcrest.Matchers.not;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
@@ -67,7 +68,8 @@ public void shouldGetFullHealthActuatorWhenAdmin() {
containsString("\"status\""),
containsString("\"diskSpace\""),
containsString("\"mongo\""),
- containsString("\"db\"")
+ containsString("\"db\""),
+ not(containsString("\"redis\"")) // tests use embedded cache, not Redis
);
}
diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml
index 0a1a78e4..771888c6 100644
--- a/src/test/resources/application-test.yml
+++ b/src/test/resources/application-test.yml
@@ -7,3 +7,5 @@ manon:
security.bcrypt.strength: 4
batch:
user-snapshot.chunk: 10
+
+management.health.redis.enabled: false # disable Redis health check since we prefer embedded cache provider