From ec4175b8bc6aae025ff56f56c32bd999807527a9 Mon Sep 17 00:00:00 2001 From: Felix Dittrich <31076102+f11h@users.noreply.github.com> Date: Tue, 27 Sep 2022 09:52:31 +0200 Subject: [PATCH] Feat: Add Validation for JRC Response (#206) * Add Validation for JRC Response * Add Unit Test --- .../ec/dgc/gateway/client/JrcClient.java | 7 +++++-- .../ec/dgc/gateway/model/JrcRatValueset.java | 13 +++++++++++++ .../gateway/model/JrcRatValuesetResponse.java | 3 +++ .../service/RatValuesetUpdateService.java | 4 ++++ .../service/RatValuesetUpdateServiceTest.java | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/main/java/eu/europa/ec/dgc/gateway/client/JrcClient.java b/src/main/java/eu/europa/ec/dgc/gateway/client/JrcClient.java index cbc3fb57..b43e2863 100644 --- a/src/main/java/eu/europa/ec/dgc/gateway/client/JrcClient.java +++ b/src/main/java/eu/europa/ec/dgc/gateway/client/JrcClient.java @@ -21,14 +21,17 @@ package eu.europa.ec.dgc.gateway.client; import eu.europa.ec.dgc.gateway.model.JrcRatValuesetResponse; +import javax.validation.Valid; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @FeignClient( name = "jrcClient", url = "${dgc.jrc.url}", configuration = JrcClientConfig.class) +@Validated public interface JrcClient { /** @@ -36,7 +39,7 @@ public interface JrcClient { * * @return List of RAT values. */ - @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE - ) + @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) + @Valid JrcRatValuesetResponse downloadRatValues(); } diff --git a/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValueset.java b/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValueset.java index 28c811b3..647a67ea 100644 --- a/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValueset.java +++ b/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValueset.java @@ -24,24 +24,30 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.time.ZonedDateTime; import java.util.List; +import javax.validation.constraints.NotNull; import lombok.Data; @Data public class JrcRatValueset { @JsonProperty("id_device") + @NotNull String idDevice; @JsonProperty("commercial_name") + @NotNull String commercialName; @JsonProperty("manufacturer") + @NotNull Manufacturer manufacturer; @JsonProperty("hsc_common_list") + @NotNull Boolean hscCommonList; @JsonProperty("hsc_mutual_recognition") + @NotNull Boolean hscMutualRecognition; @JsonProperty("last_updated") @@ -56,12 +62,15 @@ public static class HscListHistory { @JsonProperty("list_date") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss z") + @NotNull ZonedDateTime listDate; @JsonProperty("in_common_list") + @NotNull Boolean inCommonList; @JsonProperty("in_mutual_recognition") + @NotNull Boolean inMutualRecognition; } @@ -69,15 +78,19 @@ public static class HscListHistory { public static class Manufacturer { @JsonProperty("id_manufacturer") + @NotNull String id; @JsonProperty("name") + @NotNull String name; @JsonProperty("country") + @NotNull String country; @JsonProperty("website") + @NotNull String website; } } diff --git a/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValuesetResponse.java b/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValuesetResponse.java index 767a0af2..46173393 100644 --- a/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValuesetResponse.java +++ b/src/main/java/eu/europa/ec/dgc/gateway/model/JrcRatValuesetResponse.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.time.ZonedDateTime; import java.util.List; +import javax.validation.constraints.NotNull; import lombok.Data; @Data @@ -31,8 +32,10 @@ public class JrcRatValuesetResponse { @JsonProperty("extracted_on") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss z") + @NotNull ZonedDateTime extractedOn; @JsonProperty("deviceList") + @NotNull List deviceList; } diff --git a/src/main/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateService.java b/src/main/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateService.java index 46a9f4ae..0d9d0f8f 100644 --- a/src/main/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateService.java +++ b/src/main/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateService.java @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.Optional; import javax.annotation.PostConstruct; +import javax.validation.ConstraintViolationException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; @@ -93,6 +94,9 @@ public void update() { } catch (FeignException e) { log.error("Failed to download RatValueset from JRC", e); return; + } catch (ConstraintViolationException e) { + log.error("Failed to parse RatValueset from JRC", e); + return; } for (JrcRatValueset device : jrcResponse.getDeviceList()) { diff --git a/src/test/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateServiceTest.java b/src/test/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateServiceTest.java index 5147fedd..a386d8bd 100644 --- a/src/test/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateServiceTest.java +++ b/src/test/java/eu/europa/ec/dgc/gateway/service/RatValuesetUpdateServiceTest.java @@ -43,6 +43,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.validation.ConstraintViolationException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -379,6 +380,24 @@ void testRatValuesetUpdateShouldNotUpdateWhenRequestFails() throws JsonProcessin assertEquals(rat2, updatedValueset.getValue().get(RAT2_ID)); } + @Test + void testRatValuesetUpdateShouldNotUpdateWhenJsonIsInvalid() throws JsonProcessingException { + + doThrow(new ConstraintViolationException("Invalid JSON", Collections.emptySet())) + .when(jrcClientMock).downloadRatValues(); + + ratValuesetUpdateService.update(); + + String updatedValuesetJson = valuesetService.getValueSetById(RAT_VALUESET_ID).orElseThrow(); + Valueset updatedValueset = objectMapper.readValue(updatedValuesetJson, typeReference); + + Assertions.assertEquals(LocalDate.now().minus(1, ChronoUnit.DAYS), updatedValueset.getDate(), + "Valueset Date has been updated."); + Assertions.assertEquals(2, updatedValueset.getValue().size(), "Valueset List size has been changed"); + assertEquals(rat1, updatedValueset.getValue().get(RAT1_ID)); + assertEquals(rat2, updatedValueset.getValue().get(RAT2_ID)); + } + @Test void testRatValuesetUpdateLatestAllHistoryEntriesAreInFuture() throws JsonProcessingException { JrcRatValueset.Manufacturer manufacturer = new JrcRatValueset.Manufacturer();