1

loggers replaced with lombok, additional logging, further general service refactoring

This commit is contained in:
Christoph
2020-04-07 01:32:40 +02:00
parent 952b32a86c
commit 9c6732d2d2
19 changed files with 139 additions and 75 deletions

View File

@ -5,7 +5,6 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.api.GroupRequestWrapper; import mops.gruppen2.domain.api.GroupRequestWrapper;
import mops.gruppen2.domain.event.Event;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.service.APIService; import mops.gruppen2.service.APIService;
import mops.gruppen2.service.EventStoreService; import mops.gruppen2.service.EventStoreService;
@ -39,10 +38,10 @@ public class APIController {
@GetMapping("/updateGroups/{lastEventId}") @GetMapping("/updateGroups/{lastEventId}")
@Secured("ROLE_api_user") @Secured("ROLE_api_user")
@ApiOperation("Gibt alle Gruppen zurück, in denen sich etwas geändert hat") @ApiOperation("Gibt alle Gruppen zurück, in denen sich etwas geändert hat")
public GroupRequestWrapper updateGroups(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long lastEventId) throws EventException { public GroupRequestWrapper updateGroups(@ApiParam("Letzter Status des Anfragestellers")
List<Event> events = eventStoreService.getNewEvents(lastEventId); @PathVariable Long lastEventId) throws EventException {
return APIService.wrap(eventStoreService.findMaxEventId(),
return APIService.wrap(eventStoreService.getMaxEventId(), ProjectionService.projectEventList(events)); projectionService.projectNewGroups(lastEventId));
} }
@GetMapping("/getGroupIdsOfUser/{userId}") @GetMapping("/getGroupIdsOfUser/{userId}")
@ -56,7 +55,8 @@ public class APIController {
@GetMapping("/getGroup/{groupId}") @GetMapping("/getGroup/{groupId}")
@Secured("ROLE_api_user") @Secured("ROLE_api_user")
@ApiOperation("Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück") @ApiOperation("Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück")
public Group getGroupById(@ApiParam("GruppenId der gefordeten Gruppe") @PathVariable String groupId) throws EventException { public Group getGroupById(@ApiParam("GruppenId der gefordeten Gruppe")
@PathVariable String groupId) throws EventException {
return projectionService.projectSingleGroup(UUID.fromString(groupId)); return projectionService.projectSingleGroup(UUID.fromString(groupId));
} }

View File

@ -3,6 +3,7 @@ package mops.gruppen2.controller;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import mops.gruppen2.service.ControllerService; import mops.gruppen2.service.ControllerService;
import mops.gruppen2.service.GroupService; import mops.gruppen2.service.GroupService;
import mops.gruppen2.service.IdService;
import mops.gruppen2.service.KeyCloakService; import mops.gruppen2.service.KeyCloakService;
import mops.gruppen2.service.ProjectionService; import mops.gruppen2.service.ProjectionService;
import mops.gruppen2.service.ValidationService; import mops.gruppen2.service.ValidationService;
@ -64,7 +65,7 @@ public class GroupCreationController {
@RequestParam(value = "file", required = false) MultipartFile file) { @RequestParam(value = "file", required = false) MultipartFile file) {
Account account = KeyCloakService.createAccountFromPrincipal(token); Account account = KeyCloakService.createAccountFromPrincipal(token);
UUID parentUUID = GroupService.getUUID(parent); UUID parentUUID = IdService.stringToUUID(parent);
validationService.checkFields(description, title, userMaximum, maxInfiniteUsers); validationService.checkFields(description, title, userMaximum, maxInfiniteUsers);
@ -105,7 +106,7 @@ public class GroupCreationController {
@RequestParam(value = "parent", required = false) String parent) { @RequestParam(value = "parent", required = false) String parent) {
Account account = KeyCloakService.createAccountFromPrincipal(token); Account account = KeyCloakService.createAccountFromPrincipal(token);
UUID parentUUID = GroupService.getUUID(parent); UUID parentUUID = IdService.stringToUUID(parent);
validationService.checkFields(description, title, userMaximum, maxInfiniteUsers); validationService.checkFields(description, title, userMaximum, maxInfiniteUsers);

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.api.GroupRequestWrapper; import mops.gruppen2.domain.api.GroupRequestWrapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -7,6 +8,7 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@Service @Service
@Log4j2
public class APIService { public class APIService {
// private APIService() {} // private APIService() {}

View File

@ -1,12 +1,11 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.event.CreateGroupEvent; import mops.gruppen2.domain.event.CreateGroupEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -16,17 +15,15 @@ import java.util.UUID;
@Service @Service
@Log4j2
public class ControllerService { public class ControllerService {
private static final Logger LOG = LoggerFactory.getLogger("controllerServiceLogger");
private final EventStoreService eventStoreService; private final EventStoreService eventStoreService;
private final ValidationService validationService;
private final InviteService inviteService; private final InviteService inviteService;
private final GroupService groupService; private final GroupService groupService;
public ControllerService(EventStoreService eventStoreService, ValidationService validationService, InviteService inviteService, GroupService groupService) { public ControllerService(EventStoreService eventStoreService, InviteService inviteService, GroupService groupService) {
this.eventStoreService = eventStoreService; this.eventStoreService = eventStoreService;
this.validationService = validationService;
this.inviteService = inviteService; this.inviteService = inviteService;
this.groupService = groupService; this.groupService = groupService;
} }

View File

@ -3,11 +3,10 @@ package mops.gruppen2.service;
import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.WrongFileException; import mops.gruppen2.domain.exception.WrongFileException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -18,10 +17,9 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@Log4j2
public final class CsvService { public final class CsvService {
private static final Logger LOG = LoggerFactory.getLogger(CsvService.class);
private CsvService() {} private CsvService() {}
static List<User> read(InputStream stream) throws IOException { static List<User> read(InputStream stream) throws IOException {
@ -43,7 +41,7 @@ public final class CsvService {
List<User> userList = read(file.getInputStream()); List<User> userList = read(file.getInputStream());
return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list
} catch (IOException ex) { } catch (IOException ex) {
LOG.warn("File konnte nicht gelesen werden"); log.error("File konnte nicht gelesen werden");
throw new WrongFileException(file.getOriginalFilename()); throw new WrongFileException(file.getOriginalFilename());
} }
} }

View File

@ -1,7 +1,11 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class EventBuilderService { @Log4j2
public final class EventBuilderService {
private EventBuilderService() {}
} }

View File

@ -1,14 +1,13 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.dto.EventDTO; import mops.gruppen2.domain.dto.EventDTO;
import mops.gruppen2.domain.event.AddUserEvent; import mops.gruppen2.domain.event.AddUserEvent;
import mops.gruppen2.domain.event.CreateGroupEvent; import mops.gruppen2.domain.event.CreateGroupEvent;
import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.Event;
import mops.gruppen2.domain.exception.BadPayloadException; import mops.gruppen2.domain.exception.BadPayloadException;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,18 +18,19 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
//TODO: Evtl aufsplitten in EventRepoService und EventService? @Log4j2
public class EventStoreService { public class EventStoreService {
private static final Logger LOG = LoggerFactory.getLogger(EventStoreService.class);
private final EventRepository eventStore; private final EventRepository eventStore;
public EventStoreService(EventRepository eventStore) { public EventStoreService(EventRepository eventStore) {
this.eventStore = eventStore; this.eventStore = eventStore;
} }
//########################################### SAVE ########################################### //########################################### SAVE ###########################################
/** /**
* Erzeugt ein DTO aus einem Event und speicher es. * Erzeugt ein DTO aus einem Event und speicher es.
* *
@ -38,12 +38,14 @@ public class EventStoreService {
*/ */
public void saveEvent(Event event) { public void saveEvent(Event event) {
eventStore.save(getDTOFromEvent(event)); eventStore.save(getDTOFromEvent(event));
log.trace("Ein Event wurde gespeichert!");
} }
public void saveAll(Event... events) { public void saveAll(Event... events) {
for (Event event : events) { for (Event event : events) {
eventStore.save(getDTOFromEvent(event)); eventStore.save(getDTOFromEvent(event));
} }
log.trace("{} Events wurden gespeichert!", events.length);
} }
/** /**
@ -57,11 +59,14 @@ public class EventStoreService {
for (Event event : eventlist) { for (Event event : eventlist) {
eventStore.save(getDTOFromEvent(event)); eventStore.save(getDTOFromEvent(event));
} }
log.trace("{} Events wurden gespeichert!", eventlist.size());
} }
} }
//########################################### DTOs ########################################### //########################################### DTOs ###########################################
static List<EventDTO> getDTOsFromEvents(List<Event> events) { static List<EventDTO> getDTOsFromEvents(List<Event> events) {
return events.stream() return events.stream()
.map(EventStoreService::getDTOFromEvent) .map(EventStoreService::getDTOFromEvent)
@ -84,7 +89,7 @@ public class EventStoreService {
getEventType(event), getEventType(event),
payload); payload);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
LOG.error("Event ({}) konnte nicht serialisiert werden!", e.getMessage()); log.error("Event ({}) konnte nicht serialisiert werden!", e.getMessage());
throw new BadPayloadException(EventStoreService.class.toString()); throw new BadPayloadException(EventStoreService.class.toString());
} }
} }
@ -106,26 +111,40 @@ public class EventStoreService {
try { try {
return JsonService.deserializeEvent(dto.getEvent_payload()); return JsonService.deserializeEvent(dto.getEvent_payload());
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
LOG.error("Payload\n {}\n konnte nicht deserialisiert werden!", e.getMessage()); log.error("Payload\n {}\n konnte nicht deserialisiert werden!", e.getMessage());
throw new BadPayloadException(EventStoreService.class.toString()); throw new BadPayloadException(EventStoreService.class.toString());
} }
} }
/**
* Gibt den Eventtyp als String wieder.
*
* @param event Event dessen Typ abgefragt werden soll
*
* @return Der Name des Typs des Events
*/
private static String getEventType(Event event) {
int lastDot = event.getClass().getName().lastIndexOf('.');
return event.getClass().getName().substring(lastDot + 1);
}
// ######################################## QUERIES ########################################## // ######################################## QUERIES ##########################################
public List<Event> getGroupEvents(UUID groupId) {
List<Event> findGroupEvents(UUID groupId) {
return getEventsFromDTOs(eventStore.findEventDTOsByGroup(Collections.singletonList(groupId.toString()))); return getEventsFromDTOs(eventStore.findEventDTOsByGroup(Collections.singletonList(groupId.toString())));
} }
/** /**
* Sucht in der DB alle Zeilen raus welche eine der Gruppen_ids hat. * Sucht alle Events, welche zu einer der übergebenen Gruppen gehören
* Wandelt die Zeilen in Events um und gibt davon eine Liste zurück.
* *
* @param groupIds Liste an IDs * @param groupIds Liste an IDs
* *
* @return Liste an Events * @return Liste an Events
*/ */
public List<Event> getGroupEvents(List<UUID> groupIds) { List<Event> findGroupEvents(List<UUID> groupIds) {
List<EventDTO> eventDTOS = new ArrayList<>(); List<EventDTO> eventDTOS = new ArrayList<>();
for (UUID groupId : groupIds) { for (UUID groupId : groupIds) {
@ -136,17 +155,18 @@ public class EventStoreService {
} }
/** /**
* Findet alle Events, welche ab dem neuen Status hinzugekommen sind. * Findet alle Events zu Gruppen, welche seit dem neuen Status verändert wurden.
* Sucht alle Events mit event_id > status.
* *
* @param status Die Id des zuletzt gespeicherten Events * @param status Die Id des zuletzt gespeicherten Events
* *
* @return Liste von neueren Events * @return Liste von neuen und alten Events
*/ */
public List<Event> getNewEvents(Long status) { List<Event> findChangedGroupEvents(Long status) {
List<String> changedGroupIds = eventStore.findGroupIdsWhereEventIdGreaterThanStatus(status); List<String> changedGroupIds = eventStore.findGroupIdsWhereEventIdGreaterThanStatus(status);
List<EventDTO> groupEventDTOS = eventStore.findEventDTOsByGroup(changedGroupIds); List<EventDTO> groupEventDTOS = eventStore.findEventDTOsByGroup(changedGroupIds);
log.trace("Seit Event {} haben sich {} Gruppen geändert!", status, changedGroupIds.size());
return getEventsFromDTOs(groupEventDTOS); return getEventsFromDTOs(groupEventDTOS);
} }
@ -166,7 +186,7 @@ public class EventStoreService {
} }
/** /**
* Liefert Gruppen-Ids von existierenden (ungelöschten) Gruppen. * Liefert Gruppen-Ids von existierenden (ungelöschten) Gruppen, in welchen der User teilnimmt.
* *
* @return GruppenIds (UUID) als Liste * @return GruppenIds (UUID) als Liste
*/ */
@ -184,15 +204,15 @@ public class EventStoreService {
/** /**
* Ermittelt die Id des letzten Events. * Ermittelt die Id zuletzt gespeicherten Events.
* *
* @return Letzte EventId * @return Letzte EventId
*/ */
public long getMaxEventId() { public long findMaxEventId() {
try { try {
return eventStore.findMaxEventId(); return eventStore.findMaxEventId();
} catch (NullPointerException e) { } catch (NullPointerException e) {
LOG.debug("Eine maxId von 0 wurde zurückgegeben, da keine Events vorhanden sind."); log.trace("Eine maxId von 0 wurde zurückgegeben, da keine Events vorhanden sind.");
return 0; return 0;
} }
} }
@ -210,27 +230,26 @@ public class EventStoreService {
IdService.uuidsToString(groupIds))); IdService.uuidsToString(groupIds)));
} }
/**
* Sucht zu jeder Gruppe das letzte Add- oder DeleteUserEvent heraus, welches den übergebenen User betrifft.
*
* @param userId User, zu welchem die Events gesucht werden
*
* @return Eine Liste von einem Add- oder DeleteUserEvent pro Gruppe
*/
List<Event> findLatestEventsFromGroupsByUser(String userId) { List<Event> findLatestEventsFromGroupsByUser(String userId) {
return getEventsFromDTOs(eventStore.findLatestEventDTOsPartitionedByGroupByUser(userId)); return getEventsFromDTOs(eventStore.findLatestEventDTOsPartitionedByGroupByUser(userId));
} }
/**
* Sucht zu jeder Gruppe das letzte Event des/der übergebenen Typen heraus.
*
* @param types Eventtyp, nach welchem gesucht wird
*
* @return Eine Liste von einem Event pro Gruppe
*/
List<Event> findLatestEventsFromGroupsByType(String... types) { List<Event> findLatestEventsFromGroupsByType(String... types) {
return getEventsFromDTOs(eventStore.findLatestEventDTOsPartitionedByGroupByType(Arrays.asList(types))); return getEventsFromDTOs(eventStore.findLatestEventDTOsPartitionedByGroupByType(Arrays.asList(types)));
} }
// ######################################### HELPERS #########################################
/**
* Gibt den Eventtyp als String wieder.
*
* @param event Event dessen Typ abgefragt werden soll
*
* @return Der Name des Typs des Events
*/
private static String getEventType(Event event) {
int lastDot = event.getClass().getName().lastIndexOf('.');
return event.getClass().getName().substring(lastDot + 1);
}
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
@ -14,8 +15,6 @@ import mops.gruppen2.domain.event.UpdateGroupTitleEvent;
import mops.gruppen2.domain.event.UpdateRoleEvent; import mops.gruppen2.domain.event.UpdateRoleEvent;
import mops.gruppen2.domain.event.UpdateUserMaxEvent; import mops.gruppen2.domain.event.UpdateUserMaxEvent;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -28,6 +27,7 @@ import static mops.gruppen2.domain.Role.ADMIN;
* Behandelt Aufgaben, welche sich auf eine Gruppe beziehen * Behandelt Aufgaben, welche sich auf eine Gruppe beziehen
*/ */
@Service @Service
@Log4j2
public class GroupService { public class GroupService {
private final EventStoreService eventStoreService; private final EventStoreService eventStoreService;
@ -35,8 +35,6 @@ public class GroupService {
private final InviteService inviteService; private final InviteService inviteService;
private final ProjectionService projectionService; private final ProjectionService projectionService;
private static final Logger LOG = LoggerFactory.getLogger(GroupService.class);
public GroupService(EventStoreService eventStoreService, ValidationService validationService, InviteService inviteService, ProjectionService projectionService) { public GroupService(EventStoreService eventStoreService, ValidationService validationService, InviteService inviteService, ProjectionService projectionService) {
this.eventStoreService = eventStoreService; this.eventStoreService = eventStoreService;
this.validationService = validationService; this.validationService = validationService;
@ -111,7 +109,7 @@ public class GroupService {
for (User user : newUsers) { for (User user : newUsers) {
Group group = projectionService.projectSingleGroup(groupId); Group group = projectionService.projectSingleGroup(groupId);
if (group.getMembers().contains(user)) { if (group.getMembers().contains(user)) {
LOG.info("Benutzer {} ist bereits in Gruppe", user.getId()); log.info("Benutzer {} ist bereits in Gruppe", user.getId());
} else { } else {
AddUserEvent addUserEvent = new AddUserEvent(groupId, user.getId(), user.getGivenname(), user.getFamilyname(), user.getEmail()); AddUserEvent addUserEvent = new AddUserEvent(groupId, user.getId(), user.getGivenname(), user.getFamilyname(), user.getEmail());
eventStoreService.saveEvent(addUserEvent); eventStoreService.saveEvent(addUserEvent);

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@ -7,6 +8,7 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@Log4j2
public final class IdService { public final class IdService {
private IdService() {} private IdService() {}

View File

@ -1,19 +1,18 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.dto.InviteLinkDTO; import mops.gruppen2.domain.dto.InviteLinkDTO;
import mops.gruppen2.domain.exception.InvalidInviteException; import mops.gruppen2.domain.exception.InvalidInviteException;
import mops.gruppen2.domain.exception.NoInviteExistException; import mops.gruppen2.domain.exception.NoInviteExistException;
import mops.gruppen2.repository.InviteRepository; import mops.gruppen2.repository.InviteRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.UUID; import java.util.UUID;
@Service @Service
@Log4j2
public class InviteService { public class InviteService {
private static final Logger LOG = LoggerFactory.getLogger(InviteService.class);
private final InviteRepository inviteRepository; private final InviteRepository inviteRepository;
public InviteService(InviteRepository inviteRepository) { public InviteService(InviteRepository inviteRepository) {
@ -32,7 +31,7 @@ public class InviteService {
try { try {
return UUID.fromString(inviteRepository.findGroupIdByLink(link)); return UUID.fromString(inviteRepository.findGroupIdByLink(link));
} catch (Exception e) { } catch (Exception e) {
LOG.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link); log.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link);
throw new InvalidInviteException(link); throw new InvalidInviteException(link);
} }
} }
@ -41,7 +40,7 @@ public class InviteService {
try { try {
return inviteRepository.findLinkByGroupId(groupId.toString()); return inviteRepository.findLinkByGroupId(groupId.toString());
} catch (Exception e) { } catch (Exception e) {
LOG.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", groupId); log.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", groupId);
throw new NoInviteExistException(groupId.toString()); throw new NoInviteExistException(groupId.toString());
} }
} }

View File

@ -2,6 +2,7 @@ package mops.gruppen2.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.Event;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -9,6 +10,7 @@ import org.springframework.stereotype.Service;
* Übersetzt JSON-Event-Payloads zu Java-Event-Repräsentationen und zurück. * Übersetzt JSON-Event-Payloads zu Java-Event-Repräsentationen und zurück.
*/ */
@Service @Service
@Log4j2
public final class JsonService { public final class JsonService {
private JsonService() {} private JsonService() {}

View File

@ -1,11 +1,13 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@Log4j2
public final class KeyCloakService { public final class KeyCloakService {
private KeyCloakService() {} private KeyCloakService() {}

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
@ -21,6 +22,7 @@ import java.util.stream.Collectors;
* Benötigt ausschließlich den EventStoreService. * Benötigt ausschließlich den EventStoreService.
*/ */
@Service @Service
@Log4j2
public class ProjectionService { public class ProjectionService {
private final EventStoreService eventStoreService; private final EventStoreService eventStoreService;
@ -29,6 +31,9 @@ public class ProjectionService {
this.eventStoreService = eventStoreService; this.eventStoreService = eventStoreService;
} }
// ################################## STATISCHE PROJEKTIONEN #################################
/** /**
* Konstruiert Gruppen aus einer Liste von Events. * Konstruiert Gruppen aus einer Liste von Events.
* *
@ -38,10 +43,11 @@ public class ProjectionService {
* *
* @throws EventException Projektionsfehler * @throws EventException Projektionsfehler
*/ */
public static List<Group> projectEventList(List<Event> events) throws EventException { static List<Group> projectEventList(List<Event> events) throws EventException {
Map<UUID, Group> groupMap = new HashMap<>(); Map<UUID, Group> groupMap = new HashMap<>();
events.forEach(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId()))); events.forEach(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId())));
log.trace("{} Events wurden projiziert!", events.size());
return new ArrayList<>(groupMap.values()); return new ArrayList<>(groupMap.values());
} }
@ -63,6 +69,24 @@ public class ProjectionService {
return groups.get(groupId); return groups.get(groupId);
} }
// ############################### PROJEKTIONEN MIT DATENBANK ################################
/**
* Projiziert Gruppen, welche sich seit einer übergebenen eventId geändert haben.
* Die Gruppen werden dabei vollständig konstruiert.
*
* @param status Letzte bekannte eventId
*
* @return Liste an Gruppen
*/
public List<Group> projectNewGroups(long status) {
List<Event> events = eventStoreService.findChangedGroupEvents(status);
return projectEventList(events);
}
/** /**
* Projiziert öffentliche Gruppen. * Projiziert öffentliche Gruppen.
* Die Gruppen enthalten Metainformationen: Titel, Beschreibung und MaxUserAnzahl. * Die Gruppen enthalten Metainformationen: Titel, Beschreibung und MaxUserAnzahl.
@ -141,13 +165,20 @@ public class ProjectionService {
*/ */
public Group projectSingleGroup(UUID groupId) throws GroupNotFoundException { public Group projectSingleGroup(UUID groupId) throws GroupNotFoundException {
try { try {
List<Event> events = eventStoreService.getGroupEvents(groupId); List<Event> events = eventStoreService.findGroupEvents(groupId);
return projectEventList(events).get(0); return projectEventList(events).get(0);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
log.error("Gruppe {} wurde nicht gefunden!", groupId.toString());
throw new GroupNotFoundException(ProjectionService.class.toString()); throw new GroupNotFoundException(ProjectionService.class.toString());
} }
} }
/**
* Entfernt alle Gruppen, in welchen ein User teilnimmt, aus einer Gruppenliste.
*
* @param groups Gruppenliste, aus der entfernt wird
* @param userId User, welcher teilnimmt
*/
void removeUserGroups(List<Group> groups, String userId) { void removeUserGroups(List<Group> groups, String userId) {
List<UUID> userGroups = eventStoreService.findExistingUserGroups(userId); List<UUID> userGroups = eventStoreService.findExistingUserGroups(userId);

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
@ -10,6 +11,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@Log4j2
public class SearchService { public class SearchService {
private final ProjectionService projectionService; private final ProjectionService projectionService;
@ -58,6 +60,8 @@ public class SearchService {
return groups; return groups;
} }
log.trace("Es wurde gesucht nach: {}", search);
return groups.stream() return groups.stream()
.filter(group -> groupMetaContains(group, search)) .filter(group -> groupMetaContains(group, search))
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.Role; import mops.gruppen2.domain.Role;
@ -21,6 +22,7 @@ import java.util.UUID;
import static mops.gruppen2.domain.Role.ADMIN; import static mops.gruppen2.domain.Role.ADMIN;
@Service @Service
@Log4j2
public class ValidationService { public class ValidationService {
private final SearchService searchService; private final SearchService searchService;

View File

@ -21,3 +21,4 @@ keycloak.confidential-port=443
server.error.include-stacktrace=always server.error.include-stacktrace=always
management.endpoints.web.exposure.include=info,health management.endpoints.web.exposure.include=info,health
spring.cache.type=NONE spring.cache.type=NONE
logging.level.mops.gruppen2=trace

View File

@ -1,6 +1,7 @@
package mops.gruppen2.controller; package mops.gruppen2.controller;
import mops.gruppen2.Gruppen2Application; import mops.gruppen2.Gruppen2Application;
import mops.gruppen2.domain.exception.GroupNotFoundException;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
import mops.gruppen2.service.EventStoreService; import mops.gruppen2.service.EventStoreService;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -23,6 +24,7 @@ import static mops.gruppen2.TestBuilder.deleteUserEvent;
import static mops.gruppen2.TestBuilder.updateGroupTitleEvent; import static mops.gruppen2.TestBuilder.updateGroupTitleEvent;
import static mops.gruppen2.TestBuilder.uuidMock; import static mops.gruppen2.TestBuilder.uuidMock;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Gruppen2Application.class) @SpringBootTest(classes = Gruppen2Application.class)
@ -146,7 +148,7 @@ class APIControllerTest {
@Test @Test
@WithMockUser(username = "api_user", roles = "api_user") @WithMockUser(username = "api_user", roles = "api_user")
void getGroupFromId_noGroup() { void getGroupFromId_noGroup() {
assertThat(apiController.getGroupById(uuidMock(0).toString())).isEqualTo(null); assertThrows(GroupNotFoundException.class, () -> apiController.getGroupById(uuidMock(0).toString()));
} }
@Test @Test

View File

@ -68,7 +68,7 @@ class EventStoreServiceTest {
void getDTO() { void getDTO() {
Event event = createPublicGroupEvent(); Event event = createPublicGroupEvent();
EventDTO dto = eventStoreService.getDTOFromEvent(event); EventDTO dto = EventStoreService.getDTOFromEvent(event);
assertThat(dto.getGroup_id()).isEqualTo(event.getGroupId().toString()); assertThat(dto.getGroup_id()).isEqualTo(event.getGroupId().toString());
assertThat(dto.getUser_id()).isEqualTo(event.getUserId()); assertThat(dto.getUser_id()).isEqualTo(event.getUserId());
@ -81,8 +81,8 @@ class EventStoreServiceTest {
eventStoreService.saveAll(addUserEvents(10, uuidMock(0)), eventStoreService.saveAll(addUserEvents(10, uuidMock(0)),
addUserEvents(5, uuidMock(1))); addUserEvents(5, uuidMock(1)));
assertThat(eventStoreService.getEventsOfGroup(uuidMock(0))).hasSize(10); assertThat(eventStoreService.findGroupEvents(uuidMock(0))).hasSize(10);
assertThat(eventStoreService.getEventsOfGroup(uuidMock(1))).hasSize(5); assertThat(eventStoreService.findGroupEvents(uuidMock(1))).hasSize(5);
} }
@Test @Test
@ -93,7 +93,7 @@ class EventStoreServiceTest {
addUserEvent(uuidMock(3), "A"), addUserEvent(uuidMock(3), "A"),
addUserEvent(uuidMock(3), "B")); addUserEvent(uuidMock(3), "B"));
assertThat(eventStoreService.findGroupIdsByUser("A")).hasSize(4); assertThat(eventStoreService.findExistingUserGroups("A")).hasSize(4);
assertThat(eventStoreService.findGroupIdsByUser("B")).hasSize(1); assertThat(eventStoreService.findExistingUserGroups("B")).hasSize(1);
} }
} }

View File

@ -107,9 +107,9 @@ class GroupServiceTest {
List<UUID> groupIds = Arrays.asList(uuidMock(0), uuidMock(1)); List<UUID> groupIds = Arrays.asList(uuidMock(0), uuidMock(1));
assertThat(eventStoreService.getGroupEvents(groupIds)).hasSize(2); assertThat(eventStoreService.findGroupEvents(groupIds)).hasSize(2);
assertThat(eventStoreService.getGroupEvents(groupIds).get(0).getGroupId()).isEqualTo(uuidMock(0)); assertThat(eventStoreService.findGroupEvents(groupIds).get(0).getGroupId()).isEqualTo(uuidMock(0));
assertThat(eventStoreService.getGroupEvents(groupIds).get(1).getGroupId()).isEqualTo(uuidMock(1)); assertThat(eventStoreService.findGroupEvents(groupIds).get(1).getGroupId()).isEqualTo(uuidMock(1));
} }
//TODO: ProjectionServiceTest //TODO: ProjectionServiceTest