From d5e33381a23cfc2b9fb6dd004bb8b7171e216dd8 Mon Sep 17 00:00:00 2001 From: Mikolaj Widla Date: Fri, 19 May 2023 13:10:45 +0200 Subject: [PATCH] Refactor of History module (#184) Co-authored-by: widlam Co-authored-by: Adam Bem Reviewed-on: https://gitea.release11.com/R11/release11-tools/pulls/184 Reviewed-by: Adam Bem Co-authored-by: Mikolaj Widla Co-committed-by: Mikolaj Widla --- Backend/mocked-services/pom.xml | 25 +- .../com/r11/tools/config/RedisConfig.java | 68 ----- .../configuration/RetentionConfiguration.java | 64 +++++ .../RetentionConfigurationProperties.java | 31 +++ .../r11/tools/configuration/WebConfig.java | 28 +++ .../r11/tools/controller/EventController.java | 56 ----- .../r11/tools/controller/MockController.java | 23 +- .../tools/controller/MvcExceptionHandler.java | 2 + .../controller/RequestHistoryController.java | 71 ++++++ .../IncomingMockRequestInterceptor.java | 79 ++++++ .../tools/mappers/MockedMessageMapper.java | 1 + .../tools/mappers/RequestHistoryMapper.java | 24 ++ .../main/java/com/r11/tools/model/Event.java | 36 --- ...questDto.java => HistoryRequestModel.java} | 12 +- .../com/r11/tools/model/MockedMessage.java | 2 + .../com/r11/tools/model/RequestHistory.java | 45 ++++ .../r11/tools/model/RequestHistoryDTO.java | 33 +++ .../r11/tools/repository/EventRepository.java | 20 -- .../tools/repository/EventRepositoryImpl.java | 99 -------- .../repository/RequestHistoryRepository.java | 20 ++ .../com/r11/tools/service/EtrackService.java | 20 -- .../r11/tools/service/EtrackServiceImpl.java | 44 ---- .../r11/tools/service/KlausServiceImpl.java | 3 +- .../tools/service/RequestHistoryService.java | 23 ++ .../service/RequestHistoryServiceImpl.java | 58 +++++ .../com/r11/tools/utilis/BusinessKey.java | 24 -- .../com/r11/tools/utilis/RedisAppender.java | 235 ------------------ .../com/r11/tools/utilis/TrackingClient.java | 24 -- .../src/main/resources/application.properties | 9 + .../src/main/resources/data-access.properties | 2 - .../src/main/resources/logback.xml | 18 -- Frontend/assets/css/tools/mock/common.css | 2 + Frontend/assets/css/tools/mock/r11addons.css | 25 +- Frontend/assets/css/tools/mock/r11popup.css | 83 +++++++ Frontend/assets/css/tools/mock/r11tables.css | 25 ++ .../assets/scripts/tools/mock/datatransfer.js | 2 +- .../scripts/tools/mock/historyloader.js | 27 +- Frontend/assets/scripts/tools/mock/popup.js | 34 +++ .../assets/scripts/tools/mock/uianimation.js | 110 +++++++- Frontend/tools/mock.html | 41 ++- 40 files changed, 855 insertions(+), 693 deletions(-) delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/config/RedisConfig.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfiguration.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfigurationProperties.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/configuration/WebConfig.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/controller/EventController.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/controller/RequestHistoryController.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/interceptor/IncomingMockRequestInterceptor.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/mappers/RequestHistoryMapper.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/model/Event.java rename Backend/mocked-services/src/main/java/com/r11/tools/model/{EventRequestDto.java => HistoryRequestModel.java} (79%) create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistory.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistoryDTO.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepository.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepositoryImpl.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/repository/RequestHistoryRepository.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackService.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackServiceImpl.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryService.java create mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryServiceImpl.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/utilis/BusinessKey.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/utilis/RedisAppender.java delete mode 100644 Backend/mocked-services/src/main/java/com/r11/tools/utilis/TrackingClient.java delete mode 100644 Backend/mocked-services/src/main/resources/data-access.properties create mode 100644 Frontend/assets/css/tools/mock/r11popup.css create mode 100644 Frontend/assets/scripts/tools/mock/popup.js diff --git a/Backend/mocked-services/pom.xml b/Backend/mocked-services/pom.xml index 0a6ceb7..96e6d0e 100644 --- a/Backend/mocked-services/pom.xml +++ b/Backend/mocked-services/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent - 2.3.1.RELEASE + 2.7.11 @@ -18,9 +18,10 @@ 3.3.0 1.1.6 3.16.1 - 1.3.1.Final + 1.5.5.Final Release11 ${project.artifactId} + 1.18.26 @@ -57,21 +58,6 @@ org.springframework.boot spring-boot-starter-data-redis - - com.cwbase - logback-redis-appender - ${logback-redis-appender.version} - - - redis.clients - jedis - ${jedis.version} - - - org.codehaus.jettison - jettison - 1.4.1 - @@ -101,6 +87,11 @@ lombok ${lombok.version} + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + -Amapstruct.defaultComponentModel=spring diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/config/RedisConfig.java b/Backend/mocked-services/src/main/java/com/r11/tools/config/RedisConfig.java deleted file mode 100644 index c3438d2..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/config/RedisConfig.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.r11.tools.config; - -import java.util.Objects; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.data.redis.connection.RedisStandaloneConfiguration; -import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; -import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; -import redis.clients.jedis.JedisPool; - -/** - * Class containing configuration for Redis db client - * @author Rafał Żukowicz - */ -@Configuration -@EnableRedisRepositories -@PropertySource("classpath:data-access.properties") -public class RedisConfig { - - @Autowired - private Environment environment; - - /** - * Bean of JedisPool - the Redis client. It stores requests in "the pool" and then fires them at Redis. - * It's considered super lightweight and fast client variant - * @return lightweight client of the Redis - the JedisPool - */ - @Bean - JedisPool jedisPool(){ - final JedisPool pool = new JedisPool(environment.getProperty("redis.host"), - Integer.parseInt(environment.getProperty("redis.port"))); - return pool; - } - - /** - * Bean of a factory for connenction object. - * It's initialized with Redis db url property and is fed to other methods. - * @return the factory for RedisTemplates - */ - @Bean - JedisConnectionFactory jedisConnectionFactory() { - RedisStandaloneConfiguration redisStandaloneConfiguration = - new RedisStandaloneConfiguration(Objects.requireNonNull(environment.getProperty("redis.host")), - Integer.parseInt(Objects.requireNonNull(environment.getProperty("redis.port")))); - return new JedisConnectionFactory(redisStandaloneConfiguration); - } - - /** - * RedisTemplate is the tool to store and retrieve given type (object) of hash from the database. - * It's like you could store your Java object by just naming it inside database. You might thing about it - * as of DAO. - * @return RedisTemplate the redis dao. - */ - @Bean - public RedisTemplate redisTemplate() { - RedisTemplate redisTemplate = new RedisTemplate<>(); - redisTemplate.setConnectionFactory(jedisConnectionFactory()); - redisTemplate.setExposeConnection(true); - redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); - return redisTemplate; - } - -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfiguration.java b/Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfiguration.java new file mode 100644 index 0000000..3923df0 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfiguration.java @@ -0,0 +1,64 @@ +package com.r11.tools.configuration; + +import com.r11.tools.repository.MockedResponseRepository; +import com.r11.tools.repository.RequestHistoryRepository; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import java.time.LocalDateTime; + +/** + * Based on configuration deletes all outdated messages and history records from database. + * + * @author Mikołaj Widła + */ + +@EnableScheduling +@EnableAsync +@Configuration +public class RetentionConfiguration { + + private final MockedResponseRepository responseRepository; + private final RequestHistoryRepository historyRepository; + private final RetentionConfigurationProperties retentionProperties; + private final Logger log = LogManager.getRootLogger(); + + + public RetentionConfiguration(MockedResponseRepository responseRepository, + RequestHistoryRepository historyRepository, + RetentionConfigurationProperties retentionProperties){ + this.historyRepository = historyRepository; + this.responseRepository = responseRepository; + this.retentionProperties = retentionProperties; + } + @Scheduled(fixedDelayString = "#{${retention.retention-cooldown} * 60000 }") + @Async + public void deleteMessagesAndHistoryRecords(){ + log.info("OUTDATED MESSAGES AND HISTORY RECORDS DELETED!"); + responseRepository + .findAll() + .iterator() + .forEachRemaining( mockedMessage -> { + if (mockedMessage.getCreatedAt().plusMinutes(retentionProperties.getMinutesToDeleteMessage()).isBefore(LocalDateTime.now())){ + responseRepository.delete(mockedMessage); + } + } ); + + historyRepository + .findAll() + .iterator() + .forEachRemaining( + historyRecord -> { + if (historyRecord.getDateTimeStamp().plusMinutes(retentionProperties.getMinutesToDeleteHistoryRecord()).isBefore(LocalDateTime.now())){ + historyRepository.delete(historyRecord); + } + } + ); + } + +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfigurationProperties.java b/Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfigurationProperties.java new file mode 100644 index 0000000..00aac59 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/configuration/RetentionConfigurationProperties.java @@ -0,0 +1,31 @@ +package com.r11.tools.configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import javax.validation.constraints.Positive; + +/** + * Store all properties needed to change a retention in {@link RetentionConfiguration} + * + * @author Mikołaj Widła + */ + +@Configuration +@ConfigurationProperties(prefix = "retention") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class RetentionConfigurationProperties { + @Positive + private Integer minutesToDeleteMessage; + @Positive + private Integer minutesToDeleteHistoryRecord; + @Positive + private Integer retentionCooldown; +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/configuration/WebConfig.java b/Backend/mocked-services/src/main/java/com/r11/tools/configuration/WebConfig.java new file mode 100644 index 0000000..52cdc81 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/configuration/WebConfig.java @@ -0,0 +1,28 @@ +package com.r11.tools.configuration; + +import com.r11.tools.interceptor.IncomingMockRequestInterceptor; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * Configuration for {@link IncomingMockRequestInterceptor} + * + * @author Mikołaj Widła + */ + +@Configuration +@AllArgsConstructor +public class WebConfig implements WebMvcConfigurer{ + + private final IncomingMockRequestInterceptor requestInterceptor; + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor( requestInterceptor ) + .addPathPatterns("/api/mock/r/**"); + } + +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/controller/EventController.java b/Backend/mocked-services/src/main/java/com/r11/tools/controller/EventController.java deleted file mode 100644 index 81ff153..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/controller/EventController.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.r11.tools.controller; - -import com.r11.tools.model.EventRequestDto; -import com.r11.tools.service.EtrackService; -import lombok.AllArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; -import java.util.UUID; - -/** - * It's the REST api for {@link com.r11.tools.model.Event} - * @author Gabriel Modzelewski - */ -@RestController -@RequestMapping(path = "/api/event") -@AllArgsConstructor -public class EventController { - private final EtrackService service; - - /** - * Returns the list of Events in given time bracket. - * The list of objects is received via {@link EventRequestDto}, which contains time brackets, - * as well as the key - uuid. - * @param event EventRequestDto object that contains data needed to query the database - * @return list of {@link com.r11.tools.model.Event} - */ - @PostMapping - public ResponseEntity filterHistory(@RequestBody EventRequestDto event){ - return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(event), HttpStatus.OK); - } - - /** - * Returns the list of Events of last 24h from given date. - * @param uuid unique id of message list - * @param messageId unique id of message in message list - * @return list of {@link com.r11.tools.model.Event} - */ - @GetMapping(path = "/{uuid}/{messageId}") - public ResponseEntity getLastDay(@PathVariable UUID uuid, - @PathVariable Integer messageId){ - LocalDateTime requestTime = LocalDateTime.now(); - LocalDateTime dayBeforeRequest = requestTime.minusDays(1L); - EventRequestDto eventRequestDto = EventRequestDto.builder() - .clientUUID(uuid) - .mockedResponseId(messageId) - .localDateTimeFrom(dayBeforeRequest) - .localDateTimeTo(requestTime) - .build(); - return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(eventRequestDto), HttpStatus.OK); - } - - -} - diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/controller/MockController.java b/Backend/mocked-services/src/main/java/com/r11/tools/controller/MockController.java index 8ec6473..61f00fe 100644 --- a/Backend/mocked-services/src/main/java/com/r11/tools/controller/MockController.java +++ b/Backend/mocked-services/src/main/java/com/r11/tools/controller/MockController.java @@ -3,13 +3,14 @@ package com.r11.tools.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.r11.tools.model.MockedMessageDto; import com.r11.tools.service.KlausService; -import com.r11.tools.utilis.BusinessKey; -import com.r11.tools.utilis.TrackingClient; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.springframework.http.*; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.time.LocalDateTime; @@ -18,17 +19,19 @@ import java.util.*; /** * Returns the homepage and provides the api for javascript async requests. * @author Gabriel Modzelewski + * @author Mikołaj Widła */ @RestController @RequestMapping(path = "/api/mock") @AllArgsConstructor +@CrossOrigin(origins = "*") public class MockController { private final KlausService klausService; private final Logger log = LogManager.getRootLogger(); @ExceptionHandler(Exception.class) public void errorHandler(Exception ex){ - log.error(ex.getStackTrace()); + log.error(Arrays.toString(ex.getStackTrace())); } /** @@ -175,22 +178,14 @@ public class MockController { /** * It's one of the most important features - the bread and butter of the Mocked Service. It's link that allows * to receive mocked response from the server and use it to mock! - * @param requestEntity Logs the data of request * @param clientUUID the key-uuid of given set of messages * @param mockedResponseId unique id of given message * @return */ - @GetMapping(value = "/r/{clientUUID}/{mockedResponseId}") - public ResponseEntity getMockedResponse(RequestEntity requestEntity, + @RequestMapping(value = "/r/{clientUUID}/{mockedResponseId}") + public ResponseEntity getMockedResponse( @PathVariable UUID clientUUID, @PathVariable int mockedResponseId) { - TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getMockedResponse - request", - BusinessKey.CLIENT_UUID, String.valueOf(clientUUID), - BusinessKey.MESSAGE_ID, String.valueOf(mockedResponseId))); - // log.info(requestEntity.toString().replaceAll("\"", "\\\\\"").substring(1).replaceAll("\n","")); - TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getMockedResponse - response", - BusinessKey.CLIENT_UUID, String.valueOf(clientUUID), - BusinessKey.MESSAGE_ID, String.valueOf(mockedResponseId))); MockedMessageDto mockedMessageDto = klausService.getMockedResponse(clientUUID, mockedResponseId); HttpHeaders httpHeaders = new HttpHeaders(); if (mockedMessageDto.getHttpHeaders() != null) mockedMessageDto.getHttpHeaders().forEach(httpHeaders::set); diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/controller/MvcExceptionHandler.java b/Backend/mocked-services/src/main/java/com/r11/tools/controller/MvcExceptionHandler.java index 2c9f582..1879df5 100644 --- a/Backend/mocked-services/src/main/java/com/r11/tools/controller/MvcExceptionHandler.java +++ b/Backend/mocked-services/src/main/java/com/r11/tools/controller/MvcExceptionHandler.java @@ -7,6 +7,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler; * @author Rafał Żukowicz */ @ControllerAdvice +@CrossOrigin(origins = "*") public class MvcExceptionHandler { /** diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/controller/RequestHistoryController.java b/Backend/mocked-services/src/main/java/com/r11/tools/controller/RequestHistoryController.java new file mode 100644 index 0000000..de220c7 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/controller/RequestHistoryController.java @@ -0,0 +1,71 @@ +package com.r11.tools.controller; + +import com.r11.tools.mappers.RequestHistoryMapper; +import com.r11.tools.model.HistoryRequestModel; +import com.r11.tools.model.RequestHistory; +import com.r11.tools.model.RequestHistoryDTO; +import com.r11.tools.service.RequestHistoryService; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * It's the REST api for {@link RequestHistory} + * @author Gabriel Modzelewski + * @author Mikołaj Widła + */ +@RestController +@RequestMapping(path = "/api/event") +@AllArgsConstructor +@CrossOrigin(origins = "*") +public class RequestHistoryController { + private final RequestHistoryService service; + private final RequestHistoryMapper mapper; + + /** + * Returns the list of Events in given time bracket. + * The list of objects is received via {@link RequestHistoryDTO}, which contains time brackets, + * as well as the key - uuid. + * @param historyRequestModel EventRequestDto object that contains data needed to query the database + * @return list of {@link RequestHistory} + */ + @PostMapping + public ResponseEntity> filterHistory(@RequestBody HistoryRequestModel historyRequestModel){ + return ResponseEntity.ok( + service.getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(historyRequestModel) + .stream() + .map(mapper::requestHistoryToRequestHistoryDTO) + .collect(Collectors.toList()) + ); + } + + /** + * Returns the list of Events of last 24h from given date. + * @param uuid unique id of message list + * @param messageId unique id of message in message list + * @return list of {@link RequestHistory} + */ + @GetMapping(path = "/{uuid}/{messageId}") + public ResponseEntity> getLastDay(@PathVariable UUID uuid, + @PathVariable Integer messageId){ + LocalDateTime requestTime = LocalDateTime.now(); + LocalDateTime dayBeforeRequest = requestTime.minusDays(1L); + List requestHistory = service.getHistoryRecordsBetweenDatesAndByUUIDAndMessageId( + HistoryRequestModel.builder() + .localDateTimeFrom(dayBeforeRequest) + .localDateTimeTo(requestTime) + .clientUUID(uuid) + .mockedResponseId(messageId) + .build() + ).stream() + .map(mapper::requestHistoryToRequestHistoryDTO) + .collect(Collectors.toList()); + return ResponseEntity.ok(requestHistory); + } +} + diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/interceptor/IncomingMockRequestInterceptor.java b/Backend/mocked-services/src/main/java/com/r11/tools/interceptor/IncomingMockRequestInterceptor.java new file mode 100644 index 0000000..70faec3 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/interceptor/IncomingMockRequestInterceptor.java @@ -0,0 +1,79 @@ +package com.r11.tools.interceptor; + +import com.r11.tools.model.RequestHistoryDTO; +import com.r11.tools.service.RequestHistoryService; +import lombok.AllArgsConstructor; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.util.ContentCachingRequestWrapper; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.Charset; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * Interceptor that gets needed data from HttpRequest, and saves it to history + * @author Mikołaj Widła + */ + +@Component +@AllArgsConstructor +public class IncomingMockRequestInterceptor implements HandlerInterceptor { + + private final RequestHistoryService historyService; + + @Override + public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse response, Object handler){ + Map headers = getHeadersFromHttpRequest(httpRequest); + Map pathVariable = getPathVariablesFromHttpRequest(httpRequest); + String requestBody = getRequestBodyFromHttpRequest(httpRequest); + + RequestHistoryDTO historyDTO = RequestHistoryDTO.builder() + .httpMethod(HttpMethod.valueOf(httpRequest.getMethod())) + .headers( headers ) + .messageID(Integer.valueOf(pathVariable.get("mockedResponseId"))) + .clientUUID(UUID.fromString(pathVariable.get("clientUUID"))) + .dateTimeStamp(LocalDateTime.now()) + .requestBody(requestBody) + .build(); + historyService.saveRequest(historyDTO); + return true; + } + + private Map getHeadersFromHttpRequest( HttpServletRequest httpRequest ){ + Set headersName = StreamSupport.stream( + Spliterators.spliteratorUnknownSize( + httpRequest.getHeaderNames().asIterator(), + Spliterator.ORDERED + ), false + ).collect(Collectors.toSet()); + + return headersName.stream() + .collect(Collectors.toMap( + value -> value, + httpRequest::getHeader + )); + } + + private Map getPathVariablesFromHttpRequest( HttpServletRequest httpRequest ){ + return (Map) httpRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + } + + private String getRequestBodyFromHttpRequest( HttpServletRequest httpRequest ){ + HttpServletRequest wrappedRequest = new ContentCachingRequestWrapper(httpRequest); + try { + return StreamUtils.copyToString(wrappedRequest.getInputStream(), Charset.defaultCharset()); + } catch (IOException e) { + return ""; + } + } + +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/mappers/MockedMessageMapper.java b/Backend/mocked-services/src/main/java/com/r11/tools/mappers/MockedMessageMapper.java index 882ab09..0ba9a76 100644 --- a/Backend/mocked-services/src/main/java/com/r11/tools/mappers/MockedMessageMapper.java +++ b/Backend/mocked-services/src/main/java/com/r11/tools/mappers/MockedMessageMapper.java @@ -12,6 +12,7 @@ import org.mapstruct.*; public interface MockedMessageMapper { @Mapping( target = "compositePrimaryKey", expression = "java(mockedMessageDto.getClientUUID() + \"_\"" + " + mockedMessageDto.getMockedResponseId())") + @Mapping( target = "createdAt" , expression = "java(java.time.LocalDateTime.now())") MockedMessage mockedMessageDtoToMockedMessage(MockedMessageDto mockedMessageDto); MockedMessageDto mockedMessageToMockedMessageDto(MockedMessage mockedMessage); } diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/mappers/RequestHistoryMapper.java b/Backend/mocked-services/src/main/java/com/r11/tools/mappers/RequestHistoryMapper.java new file mode 100644 index 0000000..a4bb5ed --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/mappers/RequestHistoryMapper.java @@ -0,0 +1,24 @@ +package com.r11.tools.mappers; + +import com.r11.tools.model.RequestHistory; +import com.r11.tools.model.RequestHistoryDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +/** +* Map between DTO and Entity +* +* @author Mikołaj Widła +* + */ + +@Mapper +public interface RequestHistoryMapper { + + @Mapping(target = "id", expression = "java(null)") + @Mapping(target = "clientUUID", expression = "java(requestHistoryDTO.getClientUUID().toString())") + RequestHistory requestHistoryDTOToRequestHistory(RequestHistoryDTO requestHistoryDTO); + @Mapping(target = "clientUUID", expression = "java(java.util.UUID.fromString(requestHistory.getClientUUID()))") + RequestHistoryDTO requestHistoryToRequestHistoryDTO(RequestHistory requestHistory); + +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/model/Event.java b/Backend/mocked-services/src/main/java/com/r11/tools/model/Event.java deleted file mode 100644 index 4bd0b4e..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/model/Event.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.r11.tools.model; - -import java.time.LocalDateTime; -import lombok.*; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.lang.Nullable; - -/** - * Pojo class for Event entity - * @author Rafał Żukowicz - */ -@Data -@Builder -@ToString -@NoArgsConstructor -@AllArgsConstructor -public class Event implements Comparable{ - - @DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss") - private LocalDateTime dateTimeStamp; - @Nullable - private String interfaceName; - @Nullable - private String clientUUID; - @Nullable - private Integer messageId; - private String thread; - private String level; - @Nullable - private String message; - - @Override - public int compareTo(Event o) { - return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1; - } -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/model/EventRequestDto.java b/Backend/mocked-services/src/main/java/com/r11/tools/model/HistoryRequestModel.java similarity index 79% rename from Backend/mocked-services/src/main/java/com/r11/tools/model/EventRequestDto.java rename to Backend/mocked-services/src/main/java/com/r11/tools/model/HistoryRequestModel.java index ecfc03f..54aa79f 100644 --- a/Backend/mocked-services/src/main/java/com/r11/tools/model/EventRequestDto.java +++ b/Backend/mocked-services/src/main/java/com/r11/tools/model/HistoryRequestModel.java @@ -1,22 +1,24 @@ package com.r11.tools.model; -import java.time.LocalDateTime; -import java.util.UUID; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import java.util.UUID; + /** - * Pojo for history query request. Contains information necessary to obtain {@link Event} list - * @author Rafał Żukowicz + * Represents all data needed to get HistoryRecord from database + * @author Mikołaj Widła */ + @Data @Builder @NoArgsConstructor @AllArgsConstructor -public class EventRequestDto { +public class HistoryRequestModel { private UUID clientUUID; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/model/MockedMessage.java b/Backend/mocked-services/src/main/java/com/r11/tools/model/MockedMessage.java index 29989d4..abdf15a 100644 --- a/Backend/mocked-services/src/main/java/com/r11/tools/model/MockedMessage.java +++ b/Backend/mocked-services/src/main/java/com/r11/tools/model/MockedMessage.java @@ -2,6 +2,7 @@ package com.r11.tools.model; import com.r11.tools.model.constraints.HttpCode; import java.io.Serializable; +import java.time.LocalDateTime; import java.util.Map; import java.util.UUID; import javax.validation.constraints.Positive; @@ -34,6 +35,7 @@ public class MockedMessage implements Serializable { private Map httpHeaders; @HttpCode private Integer httpStatus; + private LocalDateTime createdAt; } diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistory.java b/Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistory.java new file mode 100644 index 0000000..385d5e2 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistory.java @@ -0,0 +1,45 @@ +package com.r11.tools.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.redis.core.RedisHash; +import org.springframework.data.redis.core.index.Indexed; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.HttpMethod; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Map; + +/** + * Pojo class for Event entity + * @author Rafał Żukowicz + * @author Mikołaj Widła + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@RedisHash("mockHistory") +public class RequestHistory implements Comparable, Serializable { + + @Id + private String id; + @DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss") + private LocalDateTime dateTimeStamp; + @Indexed + private String clientUUID; + @Indexed + private Integer messageID; + private Map headers; + private HttpMethod httpMethod; + private String requestBody; + + @Override + public int compareTo(RequestHistory o) { + return this.getDateTimeStamp().compareTo(o.getDateTimeStamp()) * -1; + } +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistoryDTO.java b/Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistoryDTO.java new file mode 100644 index 0000000..1df697c --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/model/RequestHistoryDTO.java @@ -0,0 +1,33 @@ +package com.r11.tools.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.HttpMethod; + +import java.time.LocalDateTime; +import java.util.Map; +import java.util.UUID; + +/** + * Pojo for history query request. Contains information necessary to obtain {@link RequestHistory} list + * @author Rafał Żukowicz + * @author Mikołaj Widła + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RequestHistoryDTO { + + private UUID clientUUID; + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + private LocalDateTime dateTimeStamp; + private Integer messageID; + private Map headers; + private HttpMethod httpMethod; + private String requestBody; + +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepository.java b/Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepository.java deleted file mode 100644 index c634732..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.r11.tools.repository; - -import com.r11.tools.model.Event; -import com.r11.tools.utilis.BusinessKey; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -/** - * Event entity dao interface - * @author Rafał Żukowicz - */ -@Repository -@Transactional -public interface EventRepository { - List findEvents(LocalDateTime localDateTimeFrom, LocalDateTime localDateTimeTo, - Map businessKeys); -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepositoryImpl.java b/Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepositoryImpl.java deleted file mode 100644 index 3de0e2a..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/repository/EventRepositoryImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.r11.tools.repository; - -import static com.r11.tools.utilis.RedisAppender.LOG_PREFIX; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.r11.tools.model.Event; -import com.r11.tools.utilis.BusinessKey; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Repository; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; - -/** - * Builds Event list based on logs created via {@link com.r11.tools.utilis.TrackingClient} and {@link com.r11.tools.utilis.RedisAppender} - * @author Rafał Żukowicz - */ -@Repository -@AllArgsConstructor -public class EventRepositoryImpl implements EventRepository { - private final JedisPool jedisPool; - private final ObjectMapper objectMapper; - - /** - * Creates list of {@link Event} based on {@link com.r11.tools.model.EventRequestDto} data via searching logs - * @param localDateTimeFrom date from which logs are retrieved - * @param localDateTimeTo date to which logs are retrieved - * @param businessKeys set keys for redis values - * @return - */ - @Override - public List findEvents(LocalDateTime localDateTimeFrom, LocalDateTime localDateTimeTo, - Map businessKeys) { - List eventStrings = findEventsBetweenDates(localDateTimeFrom.toLocalDate(), localDateTimeTo.toLocalDate()); - if (businessKeys.size() > 0) { - eventStrings = businessKeysFilter(eventStrings, businessKeys); - } - List events = parseEvents(eventStrings); - if (localDateTimeFrom.toLocalTime() != LocalTime.MIN) { - events = events.stream().filter(event -> event.getDateTimeStamp().compareTo(localDateTimeFrom) >= 0) - .collect(Collectors.toList()); - } - return events.stream().filter(event -> event.getDateTimeStamp().compareTo(localDateTimeTo) <= 0) - .collect(Collectors.toList()); - } - - /** - * Returns logs between given dates - * @param localDateFrom date from which logs are retrieved - * @param localDateTo date to which logs are retrieved - * @return - */ - private List findEventsBetweenDates(LocalDate localDateFrom, LocalDate localDateTo) { - try (Jedis jedis = jedisPool.getResource()) { - return localDateFrom.datesUntil(localDateTo.plusDays(1)).map(day -> LOG_PREFIX + day.toString()) - .map(key -> jedis.lrange(key, 0, -1)).flatMap(Collection::stream).collect(Collectors.toList()); - } - } - - /** - * Filters keys so only the ones queried are retirned - * @param events list of logs - * @param businessKeys set keys for redis values - * @return filtered list of logs - */ - private List businessKeysFilter(List events, Map businessKeys) { - for (Map.Entry entry : businessKeys.entrySet()) { - String stringPattern = entry.getKey().getReasonPhrase()+ "\"" + ":" + "\"" + entry.getValue() + "\""; - events = events.stream().filter(s -> s.contains(stringPattern)).collect(Collectors.toList()); - } - return events; - } - - /** - * Parses list of logs into list of {@link Event} - * @param eventStrings list of logs - * @return list of {@link Event} - */ - private List parseEvents(List eventStrings) { - List events = new ArrayList<>(); - for (String eventString : eventStrings) { - eventString = eventString.replaceAll("\\R", ""); - try { - events.add(objectMapper.readValue(eventString, Event.class)); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - } - return events; - } -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/repository/RequestHistoryRepository.java b/Backend/mocked-services/src/main/java/com/r11/tools/repository/RequestHistoryRepository.java new file mode 100644 index 0000000..2df27d5 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/repository/RequestHistoryRepository.java @@ -0,0 +1,20 @@ +package com.r11.tools.repository; + +import com.r11.tools.model.RequestHistory; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * History Record entity dao interface + * @author Rafał Żukowicz + */ +@Repository +@Transactional +public interface RequestHistoryRepository extends CrudRepository { + List findAllByClientUUIDAndMessageID( + String clientUUID, + Integer messageID); +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackService.java b/Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackService.java deleted file mode 100644 index 98c6658..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.r11.tools.service; - -import com.r11.tools.model.Event; -import com.r11.tools.model.EventRequestDto; -import java.util.List; -import org.springframework.stereotype.Service; - -/** - * Spring service interface for {@link com.r11.tools.controller.EventController} - * @author Rafał Żukowicz - */ -@Service -public interface EtrackService { - /** - * Searches for {@link Event} objects between date brackets - * @param eventsDto object containing required data for request - * @return list of {@link Event} - */ - List getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto); -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackServiceImpl.java b/Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackServiceImpl.java deleted file mode 100644 index ea49c17..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/service/EtrackServiceImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.r11.tools.service; - -import com.r11.tools.model.Event; -import com.r11.tools.model.EventRequestDto; -import com.r11.tools.repository.EventRepository; -import com.r11.tools.utilis.BusinessKey; -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Spring Service for {@link com.r11.tools.controller.EventController}. Contains logic required for quering - * the database for {@link Event} objects - * @author Rafał Żukowicz - */ -@Service -@AllArgsConstructor -public class EtrackServiceImpl implements EtrackService { - - private final EventRepository eventRepository; - - /** - * Adds {@link BusinessKey} to {@link EventRequestDto} - * in order to create query via{@link com.r11.tools.repository.EventRepositoryImpl} - * @param eventsDto object containing required data for request - * @return list of {@link Event} - */ - @Override - public List getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto) { - Map businessKeys = new HashMap<>(); - businessKeys.put(BusinessKey.CLIENT_UUID, eventsDto.getClientUUID().toString()); - if (eventsDto.getMockedResponseId() != null){ - businessKeys.put(BusinessKey.MESSAGE_ID, String.valueOf(eventsDto.getMockedResponseId())); - } - List events = eventRepository.findEvents(eventsDto.getLocalDateTimeFrom(), eventsDto.getLocalDateTimeTo(), - businessKeys); - Collections.sort(events); - return events; - } -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/service/KlausServiceImpl.java b/Backend/mocked-services/src/main/java/com/r11/tools/service/KlausServiceImpl.java index 2190048..ce16bb2 100644 --- a/Backend/mocked-services/src/main/java/com/r11/tools/service/KlausServiceImpl.java +++ b/Backend/mocked-services/src/main/java/com/r11/tools/service/KlausServiceImpl.java @@ -1,6 +1,5 @@ package com.r11.tools.service; -import com.fasterxml.jackson.databind.ObjectMapper; import com.r11.tools.mappers.MockedMessageMapper; import com.r11.tools.model.MockedMessage; import com.r11.tools.model.MockedMessageDto; @@ -13,6 +12,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; + import java.util.List; import java.util.Optional; import java.util.UUID; @@ -30,7 +30,6 @@ public class KlausServiceImpl implements KlausService { private final MockedMessageMapper mockedMessageMapper; private final Logger log = LogManager.getRootLogger(); private final MockedResponseRepository mockedResponseRepository; - private final ObjectMapper objectMapper; /** * Removes message of given id in given key-uuid set diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryService.java b/Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryService.java new file mode 100644 index 0000000..1f8042a --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryService.java @@ -0,0 +1,23 @@ +package com.r11.tools.service; + +import com.r11.tools.controller.RequestHistoryController; +import com.r11.tools.model.HistoryRequestModel; +import com.r11.tools.model.RequestHistory; +import com.r11.tools.model.RequestHistoryDTO; +import java.util.List; +import org.springframework.stereotype.Service; + +/** + * Spring service interface for {@link RequestHistoryController} + * @author Rafał Żukowicz + */ +@Service +public interface RequestHistoryService { + /** + * Searches for {@link RequestHistory} objects between date brackets + * @param historyRequestModel object containing required data for request + * @return list of {@link RequestHistory} + */ + List getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(HistoryRequestModel historyRequestModel); + void saveRequest(RequestHistoryDTO requestDTO); +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryServiceImpl.java b/Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryServiceImpl.java new file mode 100644 index 0000000..ffe3ed5 --- /dev/null +++ b/Backend/mocked-services/src/main/java/com/r11/tools/service/RequestHistoryServiceImpl.java @@ -0,0 +1,58 @@ +package com.r11.tools.service; + +import com.r11.tools.controller.RequestHistoryController; +import com.r11.tools.mappers.RequestHistoryMapper; +import com.r11.tools.model.HistoryRequestModel; +import com.r11.tools.model.RequestHistory; +import com.r11.tools.model.RequestHistoryDTO; +import com.r11.tools.repository.RequestHistoryRepository; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Spring Service for {@link RequestHistoryController}. Contains logic required for quering + * the database for {@link RequestHistory} objects + * @author Rafał Żukowicz + * @author Mikołaj Widła + */ +@Service +@AllArgsConstructor +public class RequestHistoryServiceImpl implements RequestHistoryService { + + private final RequestHistoryRepository repository; + private final RequestHistoryMapper requestMapper; + + /** + * in order to create query via{@link com.r11.tools.repository.RequestHistoryRepository} + * @param historyRequestModel object containing required data for request + * @return list of {@link RequestHistory} + */ + @Override + public List getHistoryRecordsBetweenDatesAndByUUIDAndMessageId(HistoryRequestModel historyRequestModel) { + List history = repository.findAllByClientUUIDAndMessageID( + historyRequestModel.getClientUUID().toString(), + historyRequestModel.getMockedResponseId() + ); + Collections.sort(history); + + return history.stream() + .filter( historyRecord -> historyRecord + .getDateTimeStamp() + .isAfter(historyRequestModel.getLocalDateTimeFrom()) + ).filter( + historyRecord-> historyRecord + .getDateTimeStamp() + .isBefore(historyRequestModel.getLocalDateTimeTo()) + ) + .collect(Collectors.toList()); + } + + @Override + public void saveRequest(RequestHistoryDTO requestDTO) { + repository.save(requestMapper.requestHistoryDTOToRequestHistory(requestDTO)); + } +} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/utilis/BusinessKey.java b/Backend/mocked-services/src/main/java/com/r11/tools/utilis/BusinessKey.java deleted file mode 100644 index fc90cdd..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/utilis/BusinessKey.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.r11.tools.utilis; - -import lombok.AllArgsConstructor; - -/** - * Enum of keys for redis database. - * @author Rafał Żukowicz - */ -@AllArgsConstructor -public enum BusinessKey { - INTERFACE_NAME("interfaceName"), - CLIENT_UUID("clientUUID"), - MESSAGE_ID("messageId"); - - private final String phrase; - - /** - * Returns string value of given enum variant - * @return string value of enum - */ - public String getReasonPhrase() { - return this.phrase; - } -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/utilis/RedisAppender.java b/Backend/mocked-services/src/main/java/com/r11/tools/utilis/RedisAppender.java deleted file mode 100644 index 0626848..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/utilis/RedisAppender.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.r11.tools.utilis; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.UnsynchronizedAppenderBase; -import com.cwbase.logback.AdditionalField; -import com.cwbase.logback.JSONEventLayout; -import java.time.LocalDate; -import java.util.Arrays; -import java.util.Iterator; -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.Protocol; - -/** - * Class is used to insert logs directly to Redis. {@link com.release11.klaus.repository.EventRepositoryImpl} is using those logs. - * @author Rafał Żukowicz - * @author Gabriel Modzelewski - */ -public class RedisAppender extends UnsynchronizedAppenderBase { - - JedisPool pool; - JSONEventLayout jsonlayout; - Layout layout; - String host = "localhost"; - int port = Protocol.DEFAULT_PORT; - String key = null; - int timeout = Protocol.DEFAULT_TIMEOUT; - String password = null; - int database = Protocol.DEFAULT_DATABASE; - - public static final String LOG_PREFIX = "logstash_"; - - - public RedisAppender() { - jsonlayout = new JSONEventLayout(); - } - - /** - * Appends JedisPool by another log - * @param event object containing log info - */ - @Override - protected void append(ILoggingEvent event) { - Jedis client = pool.getResource(); - try { - String json = layout == null ? jsonlayout.doLayout(event) : layout.doLayout(event); - key = LOG_PREFIX + LocalDate.now(); - client.rpush(key, json); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (client != null) { - client.close(); - } - } - } - - @Deprecated - public String getSource() { - return jsonlayout.getSource(); - } - - @Deprecated - public void setSource(String source) { - jsonlayout.setSource(source); - } - - @Deprecated - public String getSourceHost() { - return jsonlayout.getSourceHost(); - } - - @Deprecated - public void setSourceHost(String sourceHost) { - jsonlayout.setSourceHost(sourceHost); - } - - @Deprecated - public String getSourcePath() { - return jsonlayout.getSourcePath(); - } - - @Deprecated - public void setSourcePath(String sourcePath) { - jsonlayout.setSourcePath(sourcePath); - } - - @Deprecated - public String getTags() { - if (jsonlayout.getTags() != null) { - Iterator i = jsonlayout.getTags().iterator(); - StringBuilder sb = new StringBuilder(); - while (i.hasNext()) { - sb.append(i.next()); - if (i.hasNext()) { - sb.append(','); - } - } - return sb.toString(); - } - return null; - } - - @Deprecated - public void setTags(String tags) { - if (tags != null) { - String[] atags = tags.split(","); - jsonlayout.setTags(Arrays.asList(atags)); - } - } - - @Deprecated - public String getType() { - return jsonlayout.getType(); - } - - @Deprecated - public void setType(String type) { - jsonlayout.setType(type); - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public int getTimeout() { - return timeout; - } - - public void setTimeout(int timeout) { - this.timeout = timeout; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public int getDatabase() { - return database; - } - - public void setDatabase(int database) { - this.database = database; - } - - @Deprecated - public void setMdc(boolean flag) { - jsonlayout.setProperties(flag); - } - - @Deprecated - public boolean getMdc() { - return jsonlayout.getProperties(); - } - - @Deprecated - public void setLocation(boolean flag) { - jsonlayout.setLocationInfo(flag); - } - - @Deprecated - public boolean getLocation() { - return jsonlayout.getLocationInfo(); - } - - @Deprecated - public void setCallerStackIndex(int index) { - jsonlayout.setCallerStackIdx(index); - } - - @Deprecated - public int getCallerStackIndex() { - return jsonlayout.getCallerStackIdx(); - } - - @Deprecated - public void addAdditionalField(AdditionalField p) { - jsonlayout.addAdditionalField(p); - } - - public Layout getLayout() { - return layout; - } - - public void setLayout(Layout layout) { - this.layout = layout; - } - - /** - * Starts new instance of JedisPool - */ - @Override - public void start() { - super.start(); - GenericObjectPoolConfig config = new GenericObjectPoolConfig(); - config.setTestOnBorrow(true); - pool = new JedisPool(config, host, port, timeout, password, database); - } - - /** - * Stops and destroys JedisPool object - */ - @Override - public void stop() { - super.stop(); - pool.destroy(); - } - -} diff --git a/Backend/mocked-services/src/main/java/com/r11/tools/utilis/TrackingClient.java b/Backend/mocked-services/src/main/java/com/r11/tools/utilis/TrackingClient.java deleted file mode 100644 index 3f49400..0000000 --- a/Backend/mocked-services/src/main/java/com/r11/tools/utilis/TrackingClient.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.r11.tools.utilis; - -import java.util.Map; -import org.slf4j.MDC; - -/** - * This static class has one purpose and one purpose only. It logs data about incomming requests. - * The data from logs is received via {@link com.release11.klaus.repository.EventRepositoryImpl} - * @author Rafał Żukowski - */ -public final class TrackingClient { - - /** - * Logs data inside the given map - * @param businessKeysMap map containing all the information about incomming request - */ - public static void setBusinessKeys(Map businessKeysMap){ - for (Map.Entry entry : businessKeysMap.entrySet()) { - MDC.put(entry.getKey().getReasonPhrase(), entry.getValue()); - } - } - - -} diff --git a/Backend/mocked-services/src/main/resources/application.properties b/Backend/mocked-services/src/main/resources/application.properties index bd52dd8..cc5394a 100644 --- a/Backend/mocked-services/src/main/resources/application.properties +++ b/Backend/mocked-services/src/main/resources/application.properties @@ -5,3 +5,12 @@ spring.mvc.view.suffix=.html logging.level.root=INFO logging.level.org.springframework.web=INFO logging.level.com.release11=INFO + +#database: +spring.redis.host=redis +spring.redis.port=6379 + +#retention +retention.minutes-to-delete-message=120 +retention.minutes-to-delete-history-record=1440 +retention.retention-cooldown=1440 diff --git a/Backend/mocked-services/src/main/resources/data-access.properties b/Backend/mocked-services/src/main/resources/data-access.properties deleted file mode 100644 index 27196b6..0000000 --- a/Backend/mocked-services/src/main/resources/data-access.properties +++ /dev/null @@ -1,2 +0,0 @@ -redis.host = redis -redis.port = 6379 \ No newline at end of file diff --git a/Backend/mocked-services/src/main/resources/logback.xml b/Backend/mocked-services/src/main/resources/logback.xml index 16733a7..1827e28 100644 --- a/Backend/mocked-services/src/main/resources/logback.xml +++ b/Backend/mocked-services/src/main/resources/logback.xml @@ -2,25 +2,8 @@ - - - redis - 6379 - logstash - - - - {"dateTimeStamp" : "%d{yyyy-MM-dd}T%d{HH:mm:ss}", "eventId":"%X{eventId}", "interfaceName":"%X{interfaceName}", "clientUUID":"%X{clientUUID}", "messageId":"%X{messageId}", "thread":"%t","level":"%-5level", "message":"%msg"}%n - - - - - - - ${HOME_LOG} - logs/mockServices.%d{yyyy-MM-dd}.%i.log 10MB @@ -34,7 +17,6 @@ - diff --git a/Frontend/assets/css/tools/mock/common.css b/Frontend/assets/css/tools/mock/common.css index 350f678..f814529 100644 --- a/Frontend/assets/css/tools/mock/common.css +++ b/Frontend/assets/css/tools/mock/common.css @@ -6,6 +6,8 @@ @import url('r11tooltip.css'); @import url('r11modal.css'); @import url('r11flexbox.css'); +@import url('r11popup.css'); +@import url('../../highlight.css'); @font-face { font-family: 'Material Icons'; diff --git a/Frontend/assets/css/tools/mock/r11addons.css b/Frontend/assets/css/tools/mock/r11addons.css index 94db8ae..2d2e72e 100644 --- a/Frontend/assets/css/tools/mock/r11addons.css +++ b/Frontend/assets/css/tools/mock/r11addons.css @@ -69,4 +69,27 @@ .content p { margin: 0; padding: 0; -} \ No newline at end of file +} + +.refresh-button{ + float: right; + border: none; + background-color: unset; + font-size: xx-large; +} + +.refresh-button:hover{ + animation-name: rotation; + animation-duration: 0.8s; + animation-iteration-count: infinite; + animation-timing-function: linear; +} + +@keyframes rotation{ + from{ + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } \ No newline at end of file diff --git a/Frontend/assets/css/tools/mock/r11popup.css b/Frontend/assets/css/tools/mock/r11popup.css new file mode 100644 index 0000000..296349a --- /dev/null +++ b/Frontend/assets/css/tools/mock/r11popup.css @@ -0,0 +1,83 @@ +.popup-flex:not(.hiddable-container){ + animation: blur 0.5s ease-in-out ; + animation-fill-mode: forwards; +} +.popup-flex{ + display: flex; + align-items: center; + width: 100%; + height: 100%; + z-index: 50; + flex-direction: column; + gap: 2%; + position: fixed; + justify-content: center; +} + +.popup-body{ + min-width: 33%; + max-width: 60%; + max-height: 70%; + background-color: white; + box-shadow: 10px 10px 5px lightblue; + min-height: 45%; + border-radius: 1em; + text-align: center; + padding: 10px 15px 15px 15px; + color: black; + border: 1px #2A93B0 solid; + display: flex; + flex-direction: column; + position: fixed; +} + +.popup-button-close-container{ + text-align: right; + margin-right: 2%; + margin-top: 1%; + font-size: xx-large; + font-weight: bold; + position: sticky; + top:0 +} + +.hiddable-popup-option{ + flex-grow: 1; + overflow: auto; + padding: 1.5%; +} + +.popup-button-close{ + background: padding-box; + border: 0; +} + +.popup-button-close:hover{ + color: #2A93B0; +} + +.hiddable-container{ + display:none; +} + +.hidden-popup-type{ + display: none; +} + +#history-request-body{ + text-align: justify; +} + +@keyframes blur { + 0% { + backdrop-filter: blur(0px); + } + + 50% { + backdrop-filter: blur(5px); + } + + 100% { + backdrop-filter: blur(10px); + } + } diff --git a/Frontend/assets/css/tools/mock/r11tables.css b/Frontend/assets/css/tools/mock/r11tables.css index 0a680ab..c78730b 100644 --- a/Frontend/assets/css/tools/mock/r11tables.css +++ b/Frontend/assets/css/tools/mock/r11tables.css @@ -68,4 +68,29 @@ background-color: #3bc4f1; text-align: left; color: white; +} + +.table-default td{ + text-align: center; +} + +#header-table tr td { + border: 1px black solid; + padding: 1.5%; + +} + +#header-table{ + border-collapse: collapse; + width: 100%; + height: 100%; +} + +.history-header-name{ + min-width: 10vw; +} + +#historyTable, td{ + padding: 1%; + overflow-x: scroll; } \ No newline at end of file diff --git a/Frontend/assets/scripts/tools/mock/datatransfer.js b/Frontend/assets/scripts/tools/mock/datatransfer.js index 922d5eb..34945a2 100644 --- a/Frontend/assets/scripts/tools/mock/datatransfer.js +++ b/Frontend/assets/scripts/tools/mock/datatransfer.js @@ -470,7 +470,7 @@ function selectMessage(id){ $('.tile[tileid="'+id+'"]').addClass("active"); initializeHistory(); - refreshHeaderTable(innerHTML); + refreshHeaderTable(document.innerHTML); } diff --git a/Frontend/assets/scripts/tools/mock/historyloader.js b/Frontend/assets/scripts/tools/mock/historyloader.js index 8c1912a..4c54671 100644 --- a/Frontend/assets/scripts/tools/mock/historyloader.js +++ b/Frontend/assets/scripts/tools/mock/historyloader.js @@ -46,13 +46,36 @@ function historyToHtml(){ for(let i=0; i' + - '' + historyJson[i].dateTimeStamp + '' + - '' + historyJson[i].interfaceName + '' + + '' + parseTimeStamp(historyJson[i].dateTimeStamp) + '' + + '' + historyJson[i].httpMethod + '' + + '' + parseRequestBody(historyJson[i].requestBody, i) + '' + + ' ' + ''; } return innerHTML; } +function parseRequestBody(requestBody,i){ + return requestBody.length == 0 ? + "No request body" : + '' +} + +function parseTimeStamp(timeStamp){ + return timeStamp.substring(0,19).replace('T',' '); +} + +function parseHeaders(pos){ + parsedJson = new Map(); + headers = historyJson[pos].headers + Object.keys( headers ).forEach( + (jsonKey) => { + parsedJson.set( jsonKey , headers[jsonKey] ); + } + ) + return parsedJson; +} + function displayHistory(){ $('#historyTable tbody').html(historyToHtml()); } diff --git a/Frontend/assets/scripts/tools/mock/popup.js b/Frontend/assets/scripts/tools/mock/popup.js new file mode 100644 index 0000000..0d2b91f --- /dev/null +++ b/Frontend/assets/scripts/tools/mock/popup.js @@ -0,0 +1,34 @@ + +function switchPopups (neededPopupOption) { + $('.hiddable-popup-option').addClass('hidden-popup-type'); + $('#'+neededPopupOption).removeClass('hidden-popup-type'); + } + +function showPopup(){ + $('.popup-flex').removeClass('hiddable-container'); +} + +function hidePopup(){ + $('.popup-flex').addClass('hiddable-container'); + $('.hiddable-popup-option').addClass('hidden-popup-type'); +} + +/* +* Event listener that's close the popup when user clicks out of a popup. +*/ + +window.addEventListener( + 'click' , + (clickedElement) => { + if(!document.getElementById('popup-body').contains(clickedElement.target) && clickedElement.target.className == 'popup-flex' ) { + hidePopup(); + } + } +); + +$('.popup-button-close').click( + () => { + hidePopup(); + $('.hiddable-popup-option').addClass('hidden-popup-type') + } +); \ No newline at end of file diff --git a/Frontend/assets/scripts/tools/mock/uianimation.js b/Frontend/assets/scripts/tools/mock/uianimation.js index 46dfb20..7340b83 100644 --- a/Frontend/assets/scripts/tools/mock/uianimation.js +++ b/Frontend/assets/scripts/tools/mock/uianimation.js @@ -35,7 +35,6 @@ $('#historyTab').click(showHistory); $('#btn-history-filter').click(historyFilterSwitch); - const tabitem = $('.tabitem'); function showHistory(){ $('#headersTab').click(showHeaders); @@ -52,8 +51,6 @@ function initializeHistory(){ getLast24hHistoryData(); } - - function showHeaders(){ $('#historyTab').click(showHistory); tabitem.removeClass('active'); @@ -63,6 +60,109 @@ function showHeaders(){ $('#headersTab').off('click'); } +function showHeadersHistory(element){ + historyTable = ''; + headers = parseHeaders(element.id) + headers.forEach( + (value,key) => { + historyTable += + '' + + ''+ key + '' + + ''+ value + '' + + '' + } + ); + document.getElementById('header-history-table-body').innerHTML = historyTable; + switchPopups('history-headers-table'); + showPopup(); +} + +async function formatJSON(json) { + const address = window.location.protocol + "//" + window.location.hostname + ":" + 8081 + "/json/formatting"; + + var init = { + body: json, + method: "POST" + }; + var request = new Request(address, init); + + var result = await fetch(request).then(response => { + return response.text().then(function (text) { + var json = JSON.parse(text); + json.status = response.status; + return json; + }); + + }); + return result; +} + +async function formatXML(xml) { + const address = window.location.protocol + "//" + window.location.hostname + ":" + 8082 + "/prettify"; + var data = { + data: xml, + process: "", + processor: "libxml", + version: "1.0" + } + + var init = { + body: JSON.stringify(data), + method: "POST" + }; + var request = new Request(address, init); + + var result = await fetch(request).then(response => { + return response.text().then(function (text) { + return JSON.parse(text); + }); + + }); + return result; +} + +function showRequestBody(element){ + var historyRequestBody = historyJson[element.id].requestBody; + const popupContent = document.getElementById('code-highlight-content') + + document.getElementById('code-highlight-content').innerText = "Loading..."; + switch(historyJson[element.id].headers["content-type"]){ + case "application/json":{ + formatJSON(historyRequestBody).then(function(result) { + + if (result.status == "200") { + popupContent.innerText = result.data; + highlightSyntax('code-highlight-content'); + } + else { + popupContent.innerText = historyRequestBody; + } + }); + break; + } + case "application/xml":{ + formatXML(historyRequestBody).then(function(result) { + if (result.status == "OK") { + popupContent.innerText = result.result; + highlightSyntax('code-highlight-content'); + } + else { + popupContent.innerText = historyRequestBody; + } + + }); + + break; + } + default:{ + popupContent.innerText = historyRequestBody; + highlightSyntax('code-highlight-content'); + } + } + switchPopups('history-request-body'); + showPopup(); +} + function focusInTip(element){ showTip(element); focusedField = true; @@ -73,6 +173,10 @@ function focusOutTip(element){ hidTip(element); } +function refreshHistoryRecords(){ + getLast24hHistoryData(); +} + function hidTip(element){ if(focusedField) return; $('#'+element).removeClass('active'); diff --git a/Frontend/tools/mock.html b/Frontend/tools/mock.html index 6039601..837c834 100644 --- a/Frontend/tools/mock.html +++ b/Frontend/tools/mock.html @@ -9,6 +9,34 @@ +
@@ -127,7 +155,10 @@
- + +
@@ -149,7 +180,9 @@ Timestamp - Type + Method + Request Body + Headers @@ -299,5 +332,9 @@ + + + +