• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zwracanie error kodu jako ResponseEntity po walidacji DTO w REST API

0 głosów
655 wizyt
pytanie zadane 27 lipca 2017 w Java przez Jonki Dyskutant (8,180 p.)

Korzystając z poradnika https://www.leveluplunch.com/[...]ring-rest-webservice-request/ chcę dokonać walidacji formularza za pomocą java bez przeładowywania strony. Robię to w REST API.
Mój kontroler

@PutMapping(value = "/changeEmail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public HttpEntity<ChangeEmailDTO> showChangeEMail(
            @RequestBody @Valid ChangeEmailDTO changeEmailDTO,
            BindingResult result
    ) {
        System.out.println("Email: " + changeEmailDTO.getEmail());
 
        if(result.hasErrors()) {
            System.out.println("Error: " + changeEmailDTO.getEmail());
            return ResponseEntity.badRequest().body(changeEmailDTO);
        }
 
        System.out.println("Success: " + changeEmailDTO.getEmail());
        return ResponseEntity.ok(changeEmailDTO);
    }

przyjmuje adres email, waliduje w adnotacjach

 @NotEmpty
    @Getter @Setter private String email;

Według podanego wyżej poradnika, podobno powinno zwrócić error code w postaci json. Natomiast jedyny efekt jaki otrzymuje to https://zapodaj.net/81a6db4635168.png.html
Czyli zwraca mi sam obiekt, a nie tak jak np. w poradniku

{"timestamp":1417379464584,"status":400,"error":"Bad Request","exception":"org.springframework.web.bind.MethodArgumentNotValidException","message":"Validation failed for argument at index 0 in method: public org.springframework.http.ResponseEntity<demo.AgencyResource> demo.AgencyController.saveAgency(demo.AgencyResource), with 2 error(s): [Field error in object 'agencyResource' on field 'name': rejected value [null]; codes [NotNull.agencyResource.name,NotNull.name,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [agencyResource.name,name]; arguments []; default message [name]]; default message [may not be null]] [Field error in object 'agencyResource' on field 'id': rejected value [50]; codes [Max.agencyResource.id,Max.id,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [agencyResource.id,id]; arguments []; default message [id],20]; default message [must be less than or equal to 20]] ","path":"/agencies"}

W jaki sposób zwrócić takie dane?

komentarz 27 lipca 2017 przez Mateusz51 Nałogowiec (28,180 p.)
Samo throw httpexception nie wystarczy?
komentarz 28 lipca 2017 przez Jonki Dyskutant (8,180 p.)

Nie udało mi się zwrócić takich danych ja w poradniku, ale bardzo podobny.

Zmieniłem kontroler:

@PutMapping(value = "/changeEmail", consumes = MediaType.APPLICATION_JSON_VALUE)
    public HttpEntity<ChangeEmailDTO> showChangeEMail(
            @RequestBody @Valid ChangeEmailDTO changeEmailDTO
    ) {
        System.out.println("Email: " + changeEmailDTO.getEmail());

        return ResponseEntity.ok(changeEmailDTO);
    }

i stworzyłem exception handler dla MethodArgumentNotValidException

@ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        List<FieldError> fieldErrors = result.getFieldErrors();

        return processFieldErrors(fieldErrors);
    }

    private ValidationErrorDTO processFieldErrors(List<FieldError> fieldErrors) {
        ValidationErrorDTO dto = new ValidationErrorDTO();

        for (FieldError fieldError: fieldErrors) {
            String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
            dto.addFieldError(fieldError.getField(), localizedErrorMessage);
        }

        return dto;
    }

    private String resolveLocalizedErrorMessage(FieldError fieldError) {
        Locale currentLocale =  LocaleContextHolder.getLocale();
        String localizedErrorMessage = messageSource.getMessage(fieldError, currentLocale);

        //If the message was not found, return the most accurate field error code instead.
        //You can remove this check if you prefer to get the default error message.
        if (localizedErrorMessage.equals(fieldError.getDefaultMessage())) {
            String[] fieldErrorCodes = fieldError.getCodes();
            localizedErrorMessage = fieldErrorCodes[0];
        }

        return localizedErrorMessage;
    }

dzięki temu zwraca mi ładną listę błędów https://zapodaj.net/7e359361ed05a.png.html

Tylko jest mały szczególik, że podczas gdy ten wyjątek ma być obsłużony przez ExceptionHandler to wyrzuca mi go również w konsoli

org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument at index 0 in method: public org.springframework.http.HttpEntity<com.movie.database.app.dto.ChangeEmailDTO> com.movie.database.app.rest.controller.UserController.showChangeEMail(com.movie.database.app.dto.ChangeEmailDTO), with 2 error(s): [Field error in object 'changeEmailDTO' on field 'email': rejected value []; codes [IsValidEmail.changeEmailDTO.email,IsValidEmail.email,IsValidEmail.java.lang.String,IsValidEmail]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [changeEmailDTO.email,email]; arguments []; default message [email]]; default message [Please enter a valid e-mail address.]] [Field error in object 'changeEmailDTO' on field 'email': rejected value []; codes [NotEmpty.changeEmailDTO.email,NotEmpty.email,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [changeEmailDTO.email,email]; arguments []; default message [email]]; default message [may not be empty]] 

Jak go obsłużyć, aby nie wyświetlał się w konsoli.

komentarz 31 lipca 2017 przez event15 Szeryf (93,790 p.)
Chciałbym zauważyć, że samo podanie w endpoincie "/changeEmail" deklasyfikuje to API jako REST.

1 odpowiedź

0 głosów
odpowiedź 31 lipca 2017 przez Mar Cin Dyskutant (8,900 p.)
BindingResult result - bezsensu w to iść.

@Adnotacje na encjach

Zrób sobie jakiegoś checkState(T t) - i rzucaj wyjątkiem, prościej, ładniej :)

 

ps żeby ten checkState ładniej wyglądał, niech przyjmuję jakieś wyrażenie lambda.

Podobne pytania

+1 głos
2 odpowiedzi 803 wizyt
pytanie zadane 26 lipca 2017 w Java przez Jonki Dyskutant (8,180 p.)
0 głosów
1 odpowiedź 298 wizyt
pytanie zadane 25 listopada 2019 w JavaScript przez varespol Użytkownik (710 p.)
0 głosów
2 odpowiedzi 770 wizyt
pytanie zadane 24 lutego 2018 w Java przez KubenQPL Maniak (62,840 p.)

93,425 zapytań

142,421 odpowiedzi

322,646 komentarzy

62,785 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...