#57 added new validation checks to the simple trigger input

This commit is contained in:
Fabio Formosa
2022-10-29 11:31:28 +02:00
parent d9ff379d59
commit b968329fb3
11 changed files with 115 additions and 22 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -1,6 +1,6 @@
package it.fabioformosa.quartzmanager.api.dto;
public interface RepetitionDTO {
public interface TriggerRepetitionDTO {
Integer getRepeatCount();
Long getRepeatInterval();

View File

@@ -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<ValidRepetition, RepetitionDTO> {
public class ValidRepetitionValidator implements ConstraintValidator<ValidTriggerRepetition, TriggerRepetitionDTO> {
@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);
}

View File

@@ -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<? extends Payload>[] payload() default {};
}

View File

@@ -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<ValidTriggerPeriod, TriggerPeriodDTO> {
@Override
public boolean isValid(TriggerPeriodDTO triggerPeriodDTO, ConstraintValidatorContext constraintValidatorContext) {
if(triggerPeriodDTO.getStartDate() != null && triggerPeriodDTO.getEndDate() != null)
return !triggerPeriodDTO.getEndDate().before(triggerPeriodDTO.getStartDate());
return true;
}
}

View File

@@ -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<? extends Payload>[] payload() default {};
}

View File

@@ -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 {

View File

@@ -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<? extends Arguments> 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();
}
}

View File

@@ -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);