diff --git a/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java b/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java index 194822867c9ed71650d7d63f0e50de47bfa4b4c0..003bb2d0d297348ab20d07dc1b7004da3db9b1bb 100644 --- a/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java +++ b/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java @@ -24,6 +24,7 @@ import de.thm.arsnova.event.AfterCreationEvent; import de.thm.arsnova.event.AfterDeletionEvent; import de.thm.arsnova.event.AfterFullUpdateEvent; import de.thm.arsnova.event.AfterPatchEvent; +import de.thm.arsnova.event.AfterUpdateEvent; import de.thm.arsnova.event.BeforeCreationEvent; import de.thm.arsnova.event.BeforeDeletionEvent; import de.thm.arsnova.event.BeforeFullUpdateEvent; @@ -31,10 +32,16 @@ import de.thm.arsnova.event.BeforePatchEvent; import de.thm.arsnova.model.Entity; import de.thm.arsnova.model.serialization.View; import de.thm.arsnova.persistence.CrudRepository; + +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.context.event.EventListener; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreFilter; +import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Date; @@ -63,17 +70,16 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService @Override @PreAuthorize("hasPermission(#id, #this.this.getTypeName(), 'read')") public T get(final String id) { - return repository.findOne(id); + return get(id, false); } @Override + @Cacheable(cacheNames = "entity", key = "#root.target.getTypeName() + '-' + #id", condition = "#internal == false") public T get(final String id, final boolean internal) { T entity; + entity = repository.findOne(id); if (internal) { - entity = repository.findOne(id); entity.setInternal(true); - } else { - entity = get(id); } modifyRetrieved(entity); @@ -260,4 +266,25 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService public void setApplicationEventPublisher(final ApplicationEventPublisher applicationEventPublisher) { this.eventPublisher = applicationEventPublisher; } + + @Component + public static class EntityCacheHandler { + @CachePut(cacheNames = "entity", key = "#event.entity.class.simpleName.toLowerCase() + '-' + #event.entity.id") + @EventListener + public Entity handleCreate(AfterCreationEvent event) { + return event.getEntity(); + } + + @CachePut(cacheNames = "entity", key = "#event.entity.class.simpleName.toLowerCase() + '-' + #event.entity.id") + @EventListener + public Entity handleUpdate(AfterUpdateEvent event) { + return event.getEntity(); + } + + @CacheEvict(cacheNames = "entity", key = "#event.entity.class.simpleName.toLowerCase() + '-' + #event.entity.id") + @EventListener + public void handleDelete(AfterDeletionEvent event) { + + } + } } diff --git a/src/test/java/de/thm/arsnova/service/DefaultEntityServiceImplTest.java b/src/test/java/de/thm/arsnova/service/DefaultEntityServiceImplTest.java index eed130c37c8516cc027fb9b82eddbbc9b42f1044..ac97ac25c1b6ccdd3c614543b4938b0ad65ee71c 100644 --- a/src/test/java/de/thm/arsnova/service/DefaultEntityServiceImplTest.java +++ b/src/test/java/de/thm/arsnova/service/DefaultEntityServiceImplTest.java @@ -12,6 +12,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.cache.CacheManager; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.test.context.ActiveProfiles; @@ -24,8 +25,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.Matchers.anyListOf; import static org.mockito.Mockito.any; @@ -44,6 +46,9 @@ public class DefaultEntityServiceImplTest { @Autowired private ApplicationEventPublisher eventPublisher; + @Autowired + private CacheManager cacheManager; + @Autowired private RoomRepository roomRepository; @@ -130,4 +135,40 @@ public class DefaultEntityServiceImplTest { assertEquals(patchedClosed, room2.isClosed()); assertEquals(originalOwnerId2, room2.getOwnerId()); } + + @Test + @WithMockUser("TestUser") + public void testCaching() { + final ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper(); + final DefaultEntityServiceImpl<Room> entityService = new DefaultEntityServiceImpl<>(Room.class, roomRepository, objectMapper); + entityService.setApplicationEventPublisher(eventPublisher); + + final Room room1 = new Room(); + room1.setId("a34876427c634a9b9cb56789d73607f0"); + room1.setOwnerId("TestUser"); + final Room room2 = new Room(); + room2.setId("4638748d89884ff7936d7fe994a4090c"); + room2.setOwnerId("TestUser"); + final Room room3 = new Room(); + room3.setId("c9651db0a67b49789a354e90e0401032"); + room3.setOwnerId("TestUser"); + final Room room4 = new Room(); + room4.setId("66c1673056b2410b87335b9f317da5aa"); + room4.setOwnerId("TestUser"); + + when(roomRepository.findById(any(String.class))).thenReturn(Optional.of(room1)); + when(roomRepository.findOne(any(String.class))).thenReturn(room1); + assertSame(room1, entityService.get(room1.getId())); + /* room1 should now be cached for room1.id */ + assertSame(room1, cacheManager.getCache("entity").get("room-" + room1.getId()).get()); + when(roomRepository.findById(any(String.class))).thenReturn(Optional.of(room2)); + when(roomRepository.findOne(any(String.class))).thenReturn(room2); + assertSame(room1, entityService.get(room1.getId())); + assertSame("Cache should not be used if internal == true.", room2, entityService.get(room1.getId(), true)); + + entityService.delete(room1); + /* room1 should no longer be cached for room1.id */ + assertSame("Entity should not be cached.", null, cacheManager.getCache("entity").get("room-" + room1.getId())); + assertSame(room2, entityService.get(room1.getId())); + } }