Intercept request to create RequestBody

Viewed 67

I have a base CreateRequest class which I inherit in a couple of children, each responsible for some custom validations:

Base:

public class CreateEventRequest {

    @NotEmpty
    private String name;

    @NotNull
    @JsonProperty
    private Boolean isPrivate;
}

Child:

public class CreateRegularEventRequest extends CreateEventRequest {

    @NotNull
    @Future
    private LocalDateTime startTime;

    @NotNull
    @Future
    private LocalDateTime endTime;

    public LocalDateTime getStartTime() {
        return startTime;
    }

    public LocalDateTime getEndTime() {
        return endTime;
    }
}

In order to take advantage of the validations, I've tried this:

@PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CreateEventResponse> createEvent(HttpEntity<String> httpEntity,
                                                           @AuthenticationPrincipal SecuredUser user) {
        try {
            CreateEventRequest eventRequest = eventRequestFactory.getEventRequestString(httpEntity.getBody());

            Set<ConstraintViolation<CreateEventRequest>> violations = validator.validate(eventRequest);

            if (!violations.isEmpty()) {
                throw new ConstraintViolationException(violations);
            }

            return new ResponseEntity<>(this.service.createEvent(eventRequest, user), HttpStatus.CREATED);
        } catch (ConstraintViolationException e) {
            throw e;
        } catch (Exception e) {
            return ResponseEntity.badRequest().build();
        }
    }

My factory is:

 public CreateEventRequest getEventRequestString(String json) {
        try {
            String eventTypeRaw = new ObjectMapper().readTree(json)
                    .get("event_type").asText();

            if (!StringUtils.isEmpty(eventTypeRaw)) {
                EventType eventType = EventType.valueOf(eventTypeRaw);

                if (EventType.REGULAR.equals(eventType)) {
                    return objectMapper.readValue(json, CreateRegularEventRequest.class);
                } else if (EventType.RECURRING.equals(eventType)) {
                    return objectMapper.readValue(json, CreateRecurringEventRequest.class);
                }
            }

            return null;
        } catch (JsonProcessingException e) {
            return null;
        }
    }

This seems really hacky to me and do not scale for future Parent-Child relation, my question is, is there a way to intercept this request to create this child classes and pass it to the controller or some built-in validations to handle this scenario?

Thanks!

1 Answers

Did yo try:

public ResponseEntity<CreateEventResponse> createEvent( @Valid @RequestBody  CreateRegularEventRequest reqBody ...) {
..

all the mapping and validation are done automatically

Related