From b968329fb30ec545a41bfb58905de2073aa876e4 Mon Sep 17 00:00:00 2001 From: Fabio Formosa Date: Sat, 29 Oct 2022 11:31:28 +0200 Subject: [PATCH] #57 added new validation checks to the simple trigger input --- .../api/dto/SimpleTriggerInputDTO.java | 10 +++--- .../api/dto/TriggerCommandDTO.java | 6 ++-- .../api/dto/TriggerPeriodDTO.java | 11 ++++++ ...tionDTO.java => TriggerRepetitionDTO.java} | 2 +- .../validators/ValidRepetitionValidator.java | 6 ++-- .../api/validators/ValidTriggerPeriod.java | 17 +++++++++ .../ValidTriggerPeriodValidator.java | 15 ++++++++ ...ition.java => ValidTriggerRepetition.java} | 6 ++-- ...SimpleTriggerControllerValidationTest.java | 20 +++++++++++ ...nvalidSimpleTriggerCommandDTOProvider.java | 36 +++++++++++++++++-- .../ValidRepetitionValidatorTest.java | 8 ++--- 11 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerPeriodDTO.java rename quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/{RepetitionDTO.java => TriggerRepetitionDTO.java} (83%) create mode 100644 quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriod.java create mode 100644 quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriodValidator.java rename quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/{ValidRepetition.java => ValidTriggerRepetition.java} (75%) diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/SimpleTriggerInputDTO.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/SimpleTriggerInputDTO.java index d5e4f24..2a95ebc 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/SimpleTriggerInputDTO.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/SimpleTriggerInputDTO.java @@ -1,19 +1,21 @@ package it.fabioformosa.quartzmanager.api.dto; -import it.fabioformosa.quartzmanager.api.validators.ValidRepetition; +import it.fabioformosa.quartzmanager.api.validators.ValidTriggerRepetition; import lombok.*; import lombok.experimental.SuperBuilder; +import javax.validation.constraints.Positive; + +@ValidTriggerRepetition @SuperBuilder @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) @Data @ToString(callSuper = true) -@ValidRepetition -public class SimpleTriggerInputDTO extends TriggerCommandDTO implements RepetitionDTO { - +public class SimpleTriggerInputDTO extends TriggerCommandDTO implements TriggerRepetitionDTO { private Integer repeatCount; + @Positive private Long repeatInterval; } diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerCommandDTO.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerCommandDTO.java index 7d4d249..6474bf2 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerCommandDTO.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerCommandDTO.java @@ -1,20 +1,21 @@ package it.fabioformosa.quartzmanager.api.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import it.fabioformosa.quartzmanager.api.validators.ValidTriggerPeriod; import lombok.*; import lombok.experimental.SuperBuilder; import javax.validation.constraints.NotBlank; import java.util.Date; +@ValidTriggerPeriod @SuperBuilder @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @ToString @Data -public class TriggerCommandDTO { - +public class TriggerCommandDTO implements TriggerPeriodDTO { @NotBlank private String jobClass; @@ -26,5 +27,4 @@ public class TriggerCommandDTO { @Builder.Default private MisfireInstruction misfireInstruction = MisfireInstruction.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT; - } diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerPeriodDTO.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerPeriodDTO.java new file mode 100644 index 0000000..e930d91 --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerPeriodDTO.java @@ -0,0 +1,11 @@ +package it.fabioformosa.quartzmanager.api.dto; + +public interface TriggerPeriodDTO { + java.util.Date getStartDate(); + + java.util.Date getEndDate(); + + void setStartDate(java.util.Date startDate); + + void setEndDate(java.util.Date endDate); +} diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/RepetitionDTO.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerRepetitionDTO.java similarity index 83% rename from quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/RepetitionDTO.java rename to quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerRepetitionDTO.java index d5293fd..d71d293 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/RepetitionDTO.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/dto/TriggerRepetitionDTO.java @@ -1,6 +1,6 @@ package it.fabioformosa.quartzmanager.api.dto; -public interface RepetitionDTO { +public interface TriggerRepetitionDTO { Integer getRepeatCount(); Long getRepeatInterval(); diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidator.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidator.java index 578808d..ccc3580 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidator.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidator.java @@ -1,14 +1,14 @@ package it.fabioformosa.quartzmanager.api.validators; -import it.fabioformosa.quartzmanager.api.dto.RepetitionDTO; +import it.fabioformosa.quartzmanager.api.dto.TriggerRepetitionDTO; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; -public class ValidRepetitionValidator implements ConstraintValidator { +public class ValidRepetitionValidator implements ConstraintValidator { @Override - public boolean isValid(RepetitionDTO repetitionDTO, ConstraintValidatorContext constraintValidatorContext) { + public boolean isValid(TriggerRepetitionDTO repetitionDTO, ConstraintValidatorContext constraintValidatorContext) { return (repetitionDTO.getRepeatCount() == null && repetitionDTO.getRepeatInterval() == null) || (repetitionDTO.getRepeatCount() != null && repetitionDTO.getRepeatInterval() != null); } diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriod.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriod.java new file mode 100644 index 0000000..9fb9c1e --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriod.java @@ -0,0 +1,17 @@ +package it.fabioformosa.quartzmanager.api.validators; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Constraint(validatedBy = ValidTriggerPeriodValidator.class) +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidTriggerPeriod { + String message() default "Invalid period values. The end date cannot be before the start date"; + Class[] groups() default {}; + Class[] payload() default {}; +} diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriodValidator.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriodValidator.java new file mode 100644 index 0000000..55856f2 --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerPeriodValidator.java @@ -0,0 +1,15 @@ +package it.fabioformosa.quartzmanager.api.validators; + +import it.fabioformosa.quartzmanager.api.dto.TriggerPeriodDTO; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class ValidTriggerPeriodValidator implements ConstraintValidator { + @Override + public boolean isValid(TriggerPeriodDTO triggerPeriodDTO, ConstraintValidatorContext constraintValidatorContext) { + if(triggerPeriodDTO.getStartDate() != null && triggerPeriodDTO.getEndDate() != null) + return !triggerPeriodDTO.getEndDate().before(triggerPeriodDTO.getStartDate()); + return true; + } +} diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetition.java b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerRepetition.java similarity index 75% rename from quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetition.java rename to quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerRepetition.java index 2384d25..919420e 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetition.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/main/java/it/fabioformosa/quartzmanager/api/validators/ValidTriggerRepetition.java @@ -10,10 +10,8 @@ import java.lang.annotation.Target; @Constraint(validatedBy = ValidRepetitionValidator.class) @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -public @interface ValidRepetition { - - String message() default "Invalid repetition values"; +public @interface ValidTriggerRepetition { + String message() default "Invalid repetition values. Repeat Count and Repeat interval must be both set or unset."; Class[] groups() default {}; Class[] payload() default {}; - } diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/SimpleTriggerControllerValidationTest.java b/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/SimpleTriggerControllerValidationTest.java index 33e6612..36d20e3 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/SimpleTriggerControllerValidationTest.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/SimpleTriggerControllerValidationTest.java @@ -21,6 +21,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import java.util.Date; + import static org.mockito.ArgumentMatchers.any; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -72,6 +74,24 @@ class SimpleTriggerControllerValidationTest { .build(); } + @Test + void givenStartDateAndEndDateEqual_whenScheduled_thenANewSimpleTriggerIsCreated() throws Exception { + SimpleTriggerInputDTO simpleTriggerInputDTO = buildAMinimalSimpleTriggerCommandDTO(); + Date now = new Date(); + simpleTriggerInputDTO.setStartDate(now); + simpleTriggerInputDTO.setEndDate(now); + SimpleTriggerDTO expectedSimpleTriggerDTO = TriggerUtils.getSimpleTriggerInstance("my-puntual-trigger"); + Mockito.when(simpleTriggerService.scheduleSimpleTrigger(any())).thenReturn(expectedSimpleTriggerDTO); + mockMvc.perform( + post(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/my-puntual-trigger") + .contentType(MediaType.APPLICATION_JSON) + .content(TestUtils.toJson(simpleTriggerInputDTO)) + ) + .andExpect(MockMvcResultMatchers.status().isCreated()) + .andExpect(MockMvcResultMatchers.content().json(TestUtils.toJson(expectedSimpleTriggerDTO))) + ; + } + @ParameterizedTest @ArgumentsSource(InvalidSimpleTriggerCommandDTOProvider.class) void givenAnInvalidSimpleTriggerCommandDTO_whenPostedANewTrigger_thenAnErrorIsReturned(SimpleTriggerInputDTO invalidSimpleTriggerComandDTO) throws Exception { diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/utils/InvalidSimpleTriggerCommandDTOProvider.java b/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/utils/InvalidSimpleTriggerCommandDTOProvider.java index 3745f9f..4364f1c 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/utils/InvalidSimpleTriggerCommandDTOProvider.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/controllers/utils/InvalidSimpleTriggerCommandDTOProvider.java @@ -1,19 +1,49 @@ package it.fabioformosa.quartzmanager.api.controllers.utils; +import it.fabioformosa.quartzmanager.api.common.utils.DateUtils; import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerInputDTO; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; +import java.util.Date; import java.util.stream.Stream; public class InvalidSimpleTriggerCommandDTOProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext extensionContext) { return Stream.of( - Arguments.of(SimpleTriggerInputDTO.builder().build()), - Arguments.of(SimpleTriggerInputDTO.builder().repeatCount(1).build()), - Arguments.of(SimpleTriggerInputDTO.builder().repeatInterval(1L).build()) + Arguments.of(buildSimpleTriggerWithBlankMandatoryFields()), + Arguments.of(buildSimpleTriggerWithRepeatCountAndWithoutRepeatInterval()), + Arguments.of(buildSimpleTriggerWithRepeatIntervalAndWithoutRepeatCount()), + Arguments.of(buildSimpleTriggerWithNegativeRepeatInterval()), + Arguments.of(buildSimpleTriggerWithInvalidTriggerPeriod()) ); } + + private SimpleTriggerInputDTO buildSimpleTriggerWithNegativeRepeatInterval() { + return minimalSimpleTriggerBuilder().repeatInterval(-2000L).repeatCount(10).build(); + } + + private static SimpleTriggerInputDTO buildSimpleTriggerWithRepeatIntervalAndWithoutRepeatCount() { + return minimalSimpleTriggerBuilder().repeatInterval(1L).build(); + } + + private static SimpleTriggerInputDTO.SimpleTriggerInputDTOBuilder minimalSimpleTriggerBuilder() { + return SimpleTriggerInputDTO.builder() + .jobClass("it.fabioformosa.quartzmanager.api.jobs.SampleJob"); + } + + private static SimpleTriggerInputDTO buildSimpleTriggerWithRepeatCountAndWithoutRepeatInterval() { + return minimalSimpleTriggerBuilder().repeatCount(1).build(); + } + + private static SimpleTriggerInputDTO buildSimpleTriggerWithBlankMandatoryFields() { + return SimpleTriggerInputDTO.builder().build(); + } + + private static SimpleTriggerInputDTO buildSimpleTriggerWithInvalidTriggerPeriod() { + return minimalSimpleTriggerBuilder().endDate(new Date()).startDate(DateUtils.addHoursToNow(1)).build(); + } + } diff --git a/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidatorTest.java b/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidatorTest.java index b07f78b..7d6662b 100644 --- a/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidatorTest.java +++ b/quartz-manager-parent/quartz-manager-starter-api/src/test/java/it/fabioformosa/quartzmanager/api/validators/ValidRepetitionValidatorTest.java @@ -1,6 +1,6 @@ package it.fabioformosa.quartzmanager.api.validators; -import it.fabioformosa.quartzmanager.api.dto.RepetitionDTO; +import it.fabioformosa.quartzmanager.api.dto.TriggerRepetitionDTO; import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerInputDTO; import org.apache.commons.lang3.StringUtils; import org.assertj.core.api.Assertions; @@ -14,7 +14,7 @@ class ValidRepetitionValidatorTest { @Test public void givenACountAndIntervalSet_whenTheValidatorIsCalled_shouldReturnValid() { - RepetitionDTO repetitionDTO = new SimpleTriggerInputDTO(); + TriggerRepetitionDTO repetitionDTO = new SimpleTriggerInputDTO(); repetitionDTO.setRepeatCount(10); repetitionDTO.setRepeatInterval(1000L); boolean valid = validRepetitionValidator.isValid(repetitionDTO, null); @@ -23,7 +23,7 @@ class ValidRepetitionValidatorTest { @Test public void givenACountAndIntervalUnSet_whenTheValidatorIsCalled_shouldReturnInValid() { - RepetitionDTO repetitionDTO = new SimpleTriggerInputDTO(); + TriggerRepetitionDTO repetitionDTO = new SimpleTriggerInputDTO(); boolean valid = validRepetitionValidator.isValid(repetitionDTO, null); Assertions.assertThat(valid).isTrue(); } @@ -39,7 +39,7 @@ class ValidRepetitionValidatorTest { if (StringUtils.isNotBlank(repeatIntervalStr)) repeatInterval = Long.valueOf(repeatIntervalStr); - RepetitionDTO repetitionDTO = new SimpleTriggerInputDTO(); + TriggerRepetitionDTO repetitionDTO = new SimpleTriggerInputDTO(); repetitionDTO.setRepeatInterval(repeatInterval); repetitionDTO.setRepeatCount(repeatCount);