skip to Main Content

I’m trying to send PUT request and I want to check if there’re some extra fields. Is there any chance to check these extra fields, so I can throw an exception?
For example, I’ve got this JSON file and this one is okay to add

    "id": 9999,
    "name": "Film Updated",
    "description": "New film update decription",
    "releaseDate": "1989-04-17",
    "duration": 190

As you can see, in the following file, there’s an extra field rate

  "id": 9999,
  "name": "Film Updated",
  "releaseDate": "1989-04-17",
  "description": "New film update decription",
  "duration": 190,
  "rate": 4

So I want to check if PUT request contains any extra fields to prevent from putting this information into HashMap. The following method is putting information into HashMap

    @PostMapping(value = "/films")
    public Film create(@Valid @RequestBody Film film) {
        if (film.getDuration() <= 0
                || film.getReleaseDate().isBefore(FILM_DATE)
                || film.getDescription().length() > 200 || film.getName().isEmpty()) {
            throw new ValidationException("Incorrect data");
        } else {
            if (film.getId() == 0) {
                film.setId(1);
            }
            log.info("'{}' movie was added to a library, the identifier is '{}'", film.getName(), film.getId());
            films.put(film.getId(), film);
        }
        return film;
    }

But I have no idea how to check extra fields. Any ideas?

2

Answers


  1. As far as i can see, you dont want to use extra properties from JSON? The best option for that is to create DTO object only with properties that you want to use called for example "FilmDTO" with @JsonIgnoreProperties(ignoreUnknown=true) class annotation.

    I would also recommend not to put all the logic inside of Controller Class, try to create for example "FilmService" which will encapsulate whole business logic inside:

    Controller:

    @RestController
    public class FilmController {
    
        private final FilmService filmService;
    
        public FilmController(FilmService filmService) {
            this.filmService = filmService;
        }
    
        @PutMapping("/films")
        public Film create(@RequestBody @Validated FilmDTO filmDTO ){
            return filmService.addFilm(filmDTO);
        }
    }
    

    Film

    public class Film {
        private final Integer id;
        private final String name;
        private final String description;
        private final LocalDate releaseDate;
        private final int duration;
    
        public Film(Integer id, String name, String description, LocalDate releaseDate, int duration) {
            this.id = id;
            this.name = name;
            this.description = description;
            this.releaseDate = releaseDate;
            this.duration = duration;
        }
    
        public static Film fromDto(FilmDTO filmDto) {
            return new Film(filmDto.getId(), filmDto.getName(), filmDto.getDescription(), filmDto.getReleaseDate(), filmDto.getDuration());
        }
    
        public Integer getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public String getDescription() {
            return description;
        }
    
        public LocalDate getReleaseDate() {
            return releaseDate;
        }
    
        public int getDuration() {
            return duration;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Film film = (Film) o;
            return duration == film.duration && Objects.equals(id, film.id) && Objects.equals(name, film.name) && Objects.equals(description, film.description) && Objects.equals(releaseDate, film.releaseDate);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(id, name, description, releaseDate, duration);
        }
    }
    
    

    FilmDto

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class FilmDTO {
        private final Integer id;
        @NotEmpty
        private final String name;
        @Size(max = 200)
        private final String description;
        private final LocalDate releaseDate;
        @Min(value = 1)
        private final int duration;
    
        public FilmDTO(Integer id, String name, String description, LocalDate releaseDate, int duration) {
            this.id = id;
            this.name = name;
            this.description = description;
            this.releaseDate = releaseDate;
            this.duration = duration;
        }
    
        public Integer getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public String getDescription() {
            return description;
        }
    
        public LocalDate getReleaseDate() {
            return releaseDate;
        }
    
        public int getDuration() {
            return duration;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            FilmDTO filmDTO = (FilmDTO) o;
            return duration == filmDTO.duration && Objects.equals(id, filmDTO.id) && Objects.equals(name, filmDTO.name) && Objects.equals(description, filmDTO.description) && Objects.equals(releaseDate, filmDTO.releaseDate);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(id, name, description, releaseDate, duration);
        }
    }
    

    FilmService

    @Service
    public class FilmService {
    
        private static final Logger logger = LoggerFactory.getLogger(FilmService.class);
        // Change that hashmap with some sort of repository.
        private final Map<Integer, Film> films = new HashMap<>();
    
        public Film addFilm(FilmDTO filmDTO) {
            if (filmDTO.getReleaseDate().isBefore(FILM_DATE)) {
                logger.error("Validation exception");
                throw new ValidationException("Incorrect data");
            }
            Film addedFilm = Film.fromDto(filmDTO);
            logger.info("'{}' movie was added to a library, the identifier is '{}'", addedFilm.getName(), addedFilm.getId());
            films.put(addedFilm.getId(), addedFilm);
            return addedFilm;
        }
    }
    
    Login or Signup to reply.
  2. This will throw an exception that you can gracefully handle. However, you might want to move the processFilm method to a service class.

    @RestController
    @Slf4j
    @RequestMapping()
    public class EmployeeController {
        private static final LocalDate FILM_DATE = LocalDate.now();
    
        private ObjectMapper objectMapper = new ObjectMapper();
    
        @PostMapping(value = "/films")
        public Film create(@RequestBody String requestBody) {
            Map<Integer, Film> films = new HashMap<>();
    
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
            objectMapper.registerModule(new JavaTimeModule());
    
            Film film;
            try {
               film = objectMapper.readValue(requestBody, Film.class);
                processFilm(films, film);
                return film;
            } catch (JsonMappingException e) {
                throw new ResponseStatusException(
                        HttpStatus.BAD_REQUEST, "Invalid request body", e);
            } catch (JsonProcessingException e) {
                throw new ResponseStatusException(
                        HttpStatus.INTERNAL_SERVER_ERROR, "Unable to convert request body", e);
            }
        }
    
        private static void processFilm(Map<Integer, Film> films, Film film) {
            if (film.getDuration() <= 0
                    || film.getReleaseDate().isAfter(FILM_DATE)
                    || film.getDescription().length() > 200 || film.getName().isEmpty()) {
                throw new RuntimeException("Incorrect data");
            } else {
                if (film.getId() == 0) {
                    film.setId(1);
                }
                log.info("'{}' movie was added to a library, the identifier is '{}'", film.getName(), film.getId());
                films.put(film.getId(), film);
            }
        }
    
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search