Skip to content

Instantly share code, notes, and snippets.

@pianovwork
Created November 20, 2018 18:25
Show Gist options
  • Save pianovwork/b360622dc76136064b0215136f402837 to your computer and use it in GitHub Desktop.
Save pianovwork/b360622dc76136064b0215136f402837 to your computer and use it in GitHub Desktop.
Cache based on session
@SpringBootApplication
@EnableCaching
@Import({
CacheCleanupOnSessionDestroyingListener.class
})
public class TestApp {
public static void main(String[] args) {
SpringApplication.run(TestApp.class, args);
}
@Bean
SessionBasedCacheManager cacheManager() {
return new SessionBasedCacheManager(
new ConcurrentMapCacheManager()
);
}
}
public class CacheCleanupOnSessionDestroyingListener implements HttpSessionListener {
private final SessionBasedCacheManager cacheManager;
public CacheCleanupOnSessionDestroyingListener(SessionBasedCacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println();
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
String id = se.getSession().getId();
cacheManager.getCacheNames().stream()
.filter(name -> name.startsWith(id))
.map(name -> cacheManager.getDelegate().getCache(name))
.forEach(Cache::clear);
}
}
public class SessionBasedCacheManager implements CacheManager {
@Autowired
private HttpServletRequest request;
private final CacheManager delegate;
public SessionBasedCacheManager(CacheManager delegate) {
this.delegate = delegate;
}
@Override
public Cache getCache(String name) {
if (request == null) {
return null;
}
return delegate.getCache(request.getSession().getId() + "_" + name);
}
@Override
public Collection<String> getCacheNames() {
return delegate.getCacheNames();
}
public CacheManager getDelegate() {
return delegate;
}
}
@RestController
public class TestController {
@Autowired
private HttpServletRequest request;
@Autowired
private MyService myService;
@Cacheable("cache_bucket")
@GetMapping("/test/cache")
public Object getFromCache() {
HashMap<Object, Object> map = new HashMap<>();
map.put("id", myService.doSomething());
map.put("session_id", request.getSession().getId());
return map;
}
@DeleteMapping("/test/cache")
public Object deleteSession() {
request.getSession().invalidate();
return Collections.emptyMap();
}
}
package test.cache;
import com.cigna.ng.provider.BaseMockWebTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Map;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@WebMvcTest(secure = false)
@ContextConfiguration(classes = {
TestControllerTest.Config.class,
})
@Import({
TestController.class,
CacheCleanupOnSessionDestroyingListener.class
})
public class TestControllerTest extends BaseMockWebTest {
@Autowired
MockMvc mockMvc;
@MockBean
MyService myService;
@Autowired
SessionBasedCacheManager cacheManager;
@Test
public void getFromCache() throws Exception {
MockHttpSession session = new MockHttpSession();
session.setMaxInactiveInterval(500);
mockMvc.perform(get("/test/cache").session(session))
.andExpect(status().isOk());
mockMvc.perform(get("/test/cache").session(session))
.andExpect(status().isOk());
Mockito.verify(myService, Mockito.times(1)).doSomething();
Assert.assertThat(getSizeOfFirstCache(), is(1));
mockMvc.perform(delete("/test/cache").session(session))
.andExpect(status().isOk());
// todo: find a way to make listener works, maybe the problem in MockHttpSession
// Assert.assertThat(getSizeOfFirstCache(), is(0));
}
private int getSizeOfFirstCache() {
Map map = (Map) cacheManager.getDelegate().getCache(
cacheManager.getCacheNames().iterator().next()
).getNativeCache();
return map.size();
}
@EnableCaching
public static class Config {
@Bean
SessionBasedCacheManager cacheManager() {
return new SessionBasedCacheManager(
new ConcurrentMapCacheManager()
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment