Merge branch 'modzeleg' into developer

This commit is contained in:
2021-03-22 16:45:43 +01:00
24 changed files with 217 additions and 48 deletions

View File

@@ -4,8 +4,11 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* It's generic Spring context starter. Move along...
*
* @author Rafał Żukowicz
*/
@SpringBootApplication
public class KlausApplication {
@@ -14,5 +17,3 @@ public class KlausApplication {
}
}
//TODO JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, redisPassword)
//TODO JedisPool optimalization https://partners-intl.aliyun.com/help/doc-detail/98726.htm

View File

@@ -15,11 +15,8 @@ import redis.clients.jedis.JedisPool;
import java.util.Objects;
/**
* RedisConfig is a class that reads properties from Environment singleton instance and builds beans based on them.
* JedisPool ?- an instance of the JedisPool class that contains info about host and port of Reddis
* JedisConnectionFactory - ConnectionFactory created based on host and port provided by Environment
* RedisTemplate - Creates map-like object which contains ConnectionFactory and sets parameters. Uses Jackson
* deserialiazer
* Class containing configuration for Redis db client
* @author Rafał Żukowicz
*/
@Configuration
@EnableRedisRepositories
@@ -29,15 +26,23 @@ 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(){
//TODO JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, redisPassword)
//TODO JedisPool optimalization https://partners-intl.aliyun.com/help/doc-detail/98726.htm
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 =
@@ -46,6 +51,12 @@ public class RedisConfig {
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<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

View File

@@ -1,30 +1,16 @@
package com.release11.klaus.controller;
import com.release11.klaus.model.Event;
import com.release11.klaus.model.EventRequestDto;
import com.release11.klaus.service.EtrackService;
import com.release11.klaus.service.KlausService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
/**
* Class responds to request asking about history of messages.
* It's the REST api for {@link com.release11.klaus.model.Event}
* @author Gabriel Modzelewski
*/
@Slf4j
@RestController
@@ -33,6 +19,13 @@ import java.util.UUID;
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 Event's
*/
@PostMapping
public ResponseEntity getHistory(@RequestBody EventRequestDto event){
return new ResponseEntity(service.getEventsByDateTimeAndBusinessKeys(event), HttpStatus.OK);

View File

@@ -11,7 +11,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -21,8 +20,12 @@ import java.util.UUID;
/**
* A class responds to generated message uri's requests.
* It deletes or fetches the requested message
* This controller is responsible for returning the data of given mocked message. The content is made of usual
* http parameters like: body, status, headers etc.
* Basicly the api is responsible for what a client is looking for - a mocked server response.
* Important note: {@link TrackingClient} use is to create logs - the history.
* @author Gabriel Modzelewski
* @author Rafał Żukowicz
*/
@RestController
@Slf4j
@@ -32,7 +35,13 @@ public class KlausController {
private final KlausService klausService;
// TODO: Remove method. It's depracated and duplicated.
/**
* Deletes message of given id via client request
* @param clientUUID the key-uuid of given set of messages
* @param mockedResponseId unique id of given message
* @return after deletion the confirmation is send with status 200 OK
*/
@DeleteMapping(value = "/delete/{clientUUID}/{mockedResponseId}")
public ResponseEntity<String> deleteMockedResponse(@PathVariable UUID clientUUID,
@PathVariable int mockedResponseId){
@@ -43,6 +52,13 @@ public class KlausController {
return new ResponseEntity<>("message has been deleted", HttpStatus.OK);
}
//TODO : Remove it's also depracated
/**
* Returns the full list of messages. It's used by javascript on the client side to initialize homepage
* with data from the database.
* @param clientUUID the key-uuid of given set of messages
* @return responds with 200 OK and list of {@link MockedMessageDto}
*/
@GetMapping(value = "/getAll/{clientUUID}")
public ResponseEntity<String> getAllMockedResponses(@PathVariable UUID clientUUID){
TrackingClient.setBusinessKeys(Map.of(BusinessKey.INTERFACE_NAME, "getAllMockedResponse",
@@ -51,6 +67,15 @@ public class KlausController {
return new ResponseEntity<>(mockedMessages.toString(), HttpStatus.OK);
}
/**
* 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
*/
@RequestMapping(value = "/get/{clientUUID}/{mockedResponseId}")
public ResponseEntity getMockedResponse(RequestEntity<String> requestEntity,
@PathVariable UUID clientUUID,

View File

@@ -15,29 +15,34 @@ import org.springframework.web.servlet.ModelAndView;
import java.time.LocalDateTime;
import java.util.*;
/**
* Returns the homepage and provides the api for javascript async requests.
* @author Gabriel Modzelewski
*/
@Slf4j
@Controller
@RequestMapping
@AllArgsConstructor
public class MockController {
private final KlausService klausService;
private final MockedMessageDto defaultMessage = MockedMessageDto.builder().build();
/**
* Responds to first user request. If UUID is given then it's set if it's not, then new one is generated.
* Next recalls method that populates model based on UUID
* @return
* Default path to get the homepage
* @return the view of homepage
*/
@SneakyThrows
@GetMapping
public ModelAndView showHome(){
ModelAndView mov = new ModelAndView();
mov.setViewName("html/mock");
System.out.println("Trying to return view");
return mov;
}
// TODO: Remove object mapper
/**
* Updates queried message with given set of data
* @param body {@link MockedMessageDto} json representation
* @return confirmation and 200 OK
*/
@SneakyThrows
@ResponseBody
@PutMapping("/mock/json")
@@ -47,9 +52,15 @@ public class MockController {
return klausService.setMockedResponse(message);
}
/**
* Returns the full list of messages. It's used by javascript on the client side to initialize homepage
* with data from the database.
* @param uuidValue the key-uuid of given set of messages
* @return responds with 200 OK and list of {@link MockedMessageDto}
*/
@ResponseBody
@GetMapping({"/mock/json", "/mock/json/{uuidValue}"})
public List<MockedMessageDto> getJson(@PathVariable(required = false) String uuidValue){
public List<MockedMessageDto> getListOfMessages(@PathVariable(required = false) String uuidValue){
UUID clientUUID;
if(uuidValue == null || uuidValue.equals("")) clientUUID = UUID.randomUUID();
else clientUUID = UUID.fromString(uuidValue);
@@ -62,6 +73,12 @@ public class MockController {
return messages;
}
/**
* Accepts empty post request and creates new message in given set. The new message has default set of data,
* which is constructed in {@link #buildDefaultMessage(UUID, int)} method.
* @param uuidValue the key-uuid of given set of messages
* @return confirmation response with 200 OK
*/
@ResponseBody
@PostMapping("/mock/json/{uuidValue}")
public ResponseEntity<String> addNewMessage(@PathVariable String uuidValue){
@@ -71,6 +88,12 @@ public class MockController {
return klausService.setMockedResponse(nextMessage);
}
/**
* Deletes message of given id via client request
* @param uuidValue the key-uuid of given set of messages
* @param idValue unique id of given message
* @return after deletion the confirmation is send with status 200 OK
*/
@ResponseBody
@DeleteMapping("/mock/json/{uuidValue}/{idValue}")
public ResponseEntity<String> removeMessage(@PathVariable String uuidValue,
@@ -81,13 +104,23 @@ public class MockController {
}
/**
* Recalls {@link #buildDefaultMessage(UUID)} for message construction and sets id of message
* @param uuid the key-uuid of given set of messages
* @param id unique id of given message
* @return message with default dataset and set id
*/
private static MockedMessageDto buildDefaultMessage(UUID uuid, int id){
MockedMessageDto message = buildDefaultMessage(uuid);
message.setMockedResponseId(id);
return message;
}
/**
* Constructs message with default set of data
* @param uuid the key-uuid of given set of messages
* @return message with default dataset
*/
private static MockedMessageDto buildDefaultMessage(UUID uuid){
Map<String, String> headers = new HashMap<>();
headers.put("Keep-Alive", "timeout=60");
@@ -109,6 +142,11 @@ public class MockController {
.build();
}
/**
* Finds the highest id in the list and returns it incremented by 1
* @param messages list of messages
* @return highest id incremented by 1
*/
public static int findNextId(List<MockedMessageDto> messages) {
int highestId = 0;
for (MockedMessageDto m : messages)

View File

@@ -10,6 +10,7 @@ import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
//TODO: Find usage and document or remove it
@ControllerAdvice
public class MvcExceptionHandler {

View File

@@ -4,6 +4,10 @@ import com.release11.klaus.model.MockedMessage;
import com.release11.klaus.model.MockedMessageDto;
import org.mapstruct.*;
/**
* Creates key value for redis entry
* @author Rafał Źukowicz
*/
@Mapper
public interface MockedMessageMapper {
@Mapping( target = "compositePrimaryKey", expression = "java(mockedMessageDto.getClientUUID() + \"_\"" +

View File

@@ -6,6 +6,10 @@ import org.springframework.lang.Nullable;
import java.time.LocalDateTime;
/**
* Pojo class for Event entity
* @author Rafał Żukowicz
*/
@Data
@Builder
@ToString

View File

@@ -10,7 +10,8 @@ import java.time.LocalDateTime;
import java.util.UUID;
/**
* Pojo for client request
* Pojo for history query request. Contains information necessary to obtain {@link Event} list
* @author Rafał Żukowicz
*/
@Data
@Builder

View File

@@ -14,6 +14,10 @@ import java.io.Serializable;
import java.util.Map;
import java.util.UUID;
/**
* MockedMessage redis entity pojo
* @author Rafał Żukowicz
*/
@Data
@ToString
@RedisHash("mockedMessage")

View File

@@ -10,9 +10,9 @@ import java.util.Map;
import java.util.UUID;
/**
* it appears that instance of this class contains info about mocked response
* To which UUID it is bound, whats its id, the list of headers, type of content and message body,
* as well as status it has to return.
* Alternative version of {@link MockedMessage} used in http body
* @author Rafał Żukowicz
* @author Gabriel Modzelewski
*/
@Data
@Builder
@@ -30,6 +30,7 @@ public class MockedMessageDto implements Serializable, Comparable<MockedMessageD
@HttpCode
private Integer httpStatus;
// TODO: Remove if no use
public MockedMessageDto(UUID clientUUID) {
this.clientUUID = clientUUID;
}

View File

@@ -7,7 +7,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//TODO: Find usage and document or remove it
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = HttpCodeValidation.class )

View File

@@ -1,16 +1,14 @@
package com.release11.klaus.model.constraints;
import com.release11.klaus.repository.MockedResponseRepository;
import org.springframework.http.HttpStatus;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
//TODO: Find usage and document or remove it
public class HttpCodeValidation implements ConstraintValidator<HttpCode, Integer> {
private Set<Integer> allowedValues;

View File

@@ -9,6 +9,10 @@ import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* Event entity dao interface
* @author Rafał Żukowicz
*/
@Repository
@Transactional
public interface EventRepository {

View File

@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
//TODO: Add javadoc
@Repository
@AllArgsConstructor
public class EventRepositoryImpl implements EventRepository {

View File

@@ -8,9 +8,19 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.UUID;
/**
* Spring repository that allows to retrieve message list by key-uuid from redis database
* @author Rafał Żukowicz
*/
@Repository
@Transactional
public interface MockedResponseRepository extends CrudRepository<MockedMessage, String> {
/**
* Finds all messages by their uuid
* @param clientUUID the key-uuid of given set of messages
* @return list of {@link com.release11.klaus.model.MockedMessage}
*/
List<MockedMessage> findAllByClientUUID(UUID clientUUID);
// TODO: Remove if no use
MockedMessage getByCompositePrimaryKey(String compositePrimaryKey);
}

View File

@@ -6,7 +6,16 @@ import org.springframework.stereotype.Service;
import java.util.List;
/**
* Spring service interface for {@link com.release11.klaus.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<Event> getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto);
}

View File

@@ -12,6 +12,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Spring Service for {@link com.release11.klaus.controller.EventController}. Contains logic required for quering
* the database for {@link Event} objects
* @author Rafał Żukowicz
*/
@Slf4j
@Service
@AllArgsConstructor
@@ -19,6 +24,12 @@ public class EtrackServiceImpl implements EtrackService {
private final EventRepository eventRepository;
/**
* Adds {@link BusinessKey} to {@link EventRequestDto}
* in order to create query via{@link com.release11.klaus.repository.EventRepositoryImpl}
* @param eventsDto object containing required data for request
* @return list of {@link Event}
*/
@Override
public List<Event> getEventsByDateTimeAndBusinessKeys(EventRequestDto eventsDto) {
Map<BusinessKey, String> businessKeys = new HashMap<>();

View File

@@ -7,6 +7,10 @@ import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
/**
* Service interface for {@link com.release11.klaus.controller.KlausController} and {@link com.release11.klaus.controller.MockController}
* @author Rafał Żukowicz
*/
@Service
public interface KlausService {
ResponseEntity<String> deleteMockedResponse(UUID clientUUID, int mockedResponseId);

View File

@@ -18,6 +18,12 @@ import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* Service for {@link com.release11.klaus.controller.KlausController} and {@link com.release11.klaus.controller.MockController}
* Allows for performing CRUD operations on {@link MockedMessageDto}
* @author Rafał Żukowicz
* @author Gabriel Modzelewski
*/
@Slf4j
@Service
@AllArgsConstructor
@@ -26,6 +32,12 @@ public class KlausServiceImpl implements KlausService {
private final MockedResponseRepository mockedResponseRepository;
private final ObjectMapper objectMapper;
/**
* Removes message of given id in given key-uuid set
* @param clientUUID the key-uuid of given set of messages
* @param mockedResponseId unique id of given message
* @return confirmation and status 200 OK
*/
@Override
public ResponseEntity<String> deleteMockedResponse(UUID clientUUID, int mockedResponseId) {
String key = clientUUID.toString() + "_" + mockedResponseId;
@@ -35,6 +47,11 @@ public class KlausServiceImpl implements KlausService {
new HttpHeaders(), HttpStatus.ACCEPTED);
}
/**
* Returns all messages of given key-uuid
* @param clientUUID the key-uuid of given set of messages
* @return List of {@link MockedMessageDto}
*/
@Override
public List<MockedMessageDto> getAllMockedResponses(UUID clientUUID) {
return mockedResponseRepository.findAllByClientUUID(clientUUID).stream()
@@ -42,6 +59,13 @@ public class KlausServiceImpl implements KlausService {
.collect(Collectors.toList());
}
// TODO: check logic
/**
* Returns {@link MockedMessageDto} of given id and key-uuid. If message doesn't then empty message is returned
* @param clientUUID the key-uuid of given set of messages
* @param mockedResponseId unique id of given message
* @return {@link MockedMessageDto} object
*/
@SneakyThrows
@Override
public MockedMessageDto getMockedResponse(UUID clientUUID, int mockedResponseId){
@@ -60,10 +84,15 @@ public class KlausServiceImpl implements KlausService {
return mockedMessageDto;
}
// TODO: Remove code of no use
/**
* Allows to modify mocked message. If message of given id and key-uuid doesn't exist a new entry is created
* @param mockedMessageDto message to be saved
* @return Confirmation and status 200 OK
*/
@SneakyThrows
@Override
public ResponseEntity<String> setMockedResponse(MockedMessageDto mockedMessageDto) {
mockedResponseRepository.save(mockedMessageMapper.mockedMessageDtoToMockedMessage(mockedMessageDto));
String s = objectMapper.writeValueAsString(mockedMessageDto);
String s1 = mockedMessageDto.toString();

View File

@@ -2,6 +2,10 @@ package com.release11.klaus.utilis;
import lombok.AllArgsConstructor;
/**
* Enum of keys for redis database.
* @author Rafał Żukowicz
*/
@AllArgsConstructor
public enum BusinessKey {
INTERFACE_NAME("interfaceName"),
@@ -10,6 +14,10 @@ public enum BusinessKey {
private final String phrase;
/**
* Returns string value of given enum variant
* @return string value of enum
*/
public String getReasonPhrase() {
return this.phrase;
}

View File

@@ -4,6 +4,7 @@ import com.release11.klaus.model.MockedMessageDto;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//TODO: is it really necessary? kekw
@Configuration
public class ObjectConfig {
@Bean

View File

@@ -15,6 +15,7 @@ import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Protocol;
//TODO: The check? Check if any of the following methods might be removed...
public class RedisAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
JedisPool pool;

View File

@@ -4,10 +4,20 @@ import org.slf4j.MDC;
import java.util.Map;
//TODO: Check if constructor might be safely removed. It's static class tho
/**
* 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 {
private TrackingClient(){}
/**
* Logs data inside the given map
* @param businessKeysMap map containing all the information about incomming request
*/
public static void setBusinessKeys(Map<BusinessKey, String> businessKeysMap){
for (Map.Entry<BusinessKey, String> entry : businessKeysMap.entrySet()) {
MDC.put(entry.getKey().getReasonPhrase(), entry.getValue());