jak rzucic wyjatek 404?

0

Chce rzucic kod błędu 404 zamiast 400, jak to zrobić, mam taki kod, ale zanim rzuce wyjatek jest odpowiedz z bazy 400.

public PersonDto putPerson(PersonDto personDto) {

        //TODO return 404
        if (personRepository.findOne(personDto.getId())== null ){
            throw new ResourceBadRequestException();
        }
4

W spring boot'cie wystarczy zrobić swój wyjątek i dodać odpowiedni status w adnotacji

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {
    public NotFoundException(String s) {
        super(s);
    }
}
0

Spróbuj:

return new ResponseEntity<>(HttpStatus.NOT_FOUND);

EDIT: Ok, nie spojrzałem dokładnie, że to nie kontroler, ale na przyszłość niech zostanie :P

0

Podstawowe pytanie OPie- czemu nie korzystasz z Optionala?

1
scibi92 napisał(a):

Podstawowe pytanie OPie- czemu nie korzystasz z Optionala?

a optional rzuci 404?

0
masjav napisał(a):
scibi92 napisał(a):

Podstawowe pytanie OPie- czemu nie korzystasz z Optionala?

a optional rzuci 404?

Optional to wrapper na obiekt, który pozwala Ci w eleganacki sposób pracować z ewentualnymi nullami, nie ma to związku z rzucaniem wyjątku, kolega pyta pewnie dlatego, że w fragmencie kodu, który wrzuciłeś, masz sprawdzenie

if (personRepository.findOne(personDto.getId())== null )

0
throw new WebApplicationException(Response.Status.NOT_FOUND);
0

@masjav:

personRepository.findById(personDto.getId()).orElseThrow(NotFoundException::new)

Musisz dodać mapowanie NotFoundExceptiona...

0
if (personRepository.findOne(personDto.getId())== null )

skoro metoda findOne zwraca null to zrobienie null checka jest i najlepszym najprostszym rozwiązanie.
Opakowywanie tego w optionala "na siłę" nie jest konieczne.

0

Ale findById zwraca Optional

0
scibi92 napisał(a):

Ale findById zwraca Optional

Być może, nie widać tego na załączonym fragmencie kodu

0

W jakiej warstwie jesteśmy? Jeżeli w jakimś kontrolerze, to można zwrócić status nie przez DTO, a zwyczajny Response. Jeżeli jednak gdzieś głębiej, to rzucanie wyjątkiem zamiast zwrócenia optionala mija się z celem.

2

@Aisekai:
Błędy imo powinno być propagowane na krańce systemu. Rzucanie wyjątku gdzieś głębiej to trochę jak używanie goto. Ja zamiast wyjątków rozszerzam własną klasę abstrakcyjną z polami typu kod błędu i msg i zwracam ją jako lewą wartość w Either z io.vavr. W kontrolerach (końcówki) wstrzykuje sobie resolver, który mi te eithery sprawdza, mam w nim mapę statusów MyErrorCode -> HttpStatus. Coś w tym stylu:

public class ResponseResolver {

    private final static Map<ErrorCode, HttpStatus> HTTP_STATUS_MAP =
            HashMap.of(
                    ErrorCode.USER_NOT_FOUND, HttpStatus.NOT_FOUND,
                    ErrorCode.USER_EMPTY_REQUIRED_DATA, HttpStatus.BAD_REQUEST
            );

    public <T> ResponseEntity<Object> resolve(Either<? extends AppError, T> either) {
        return either
                .map(this::createObject)
                .getOrElseGet(this::createError);
    }

    private ResponseEntity<Object> createObject(Object object) {
        return new ResponseEntity<>(object, HttpStatus.OK);
    }

    private ResponseEntity<Object> createError(AppError error) {
        return new ResponseEntity<>(error, HTTP_STATUS_MAP.getOrElse(error.getErrorCode(), HttpStatus.BAD_REQUEST));
    }

}
1

A co w przypadku, gdyby w aplikacji byłaby potrzeba zwrócenia różnych kodów błędów/ wiadomości np: Użytkownik o podanym loginie istnieje, niepoprawny format loginu, niepoprawny format hasła, podane hasła się nie zgadzają itd. Nie łatwiej rzucić wyjątkiem, dołożyć jedną warstwę gdzie byłby stworzony odpowiedni Response i zwrócić go w Kontrolerze?

@Aisekai: odpowiedź krótka brzmi nie. Odpowiedź dłuższa poniżej.

Wyjątki służą do obsługi sytuacji wyjątkowych (so obvious). Jednak żaden z podanych przez ciebie przypadków nie jest sytuacją wyjątkową. Co więcej większość sytuacji, gdzie następuje interakcja z użytkownikiem systemu nie powoduje wyjątków. Niepoprawny login, hasło, próba założenia konta za pomocą istniejącego już w bazie emaila to są sytuacje sensowne biznesowo, ale powinny kończyć się czymś co operator białkowy rozumie jako błąd.
Niestety błędy tego rodzaju bardzo szybką stają się tożsame z wyjątkami. W ten sposób powstaje Exception Driven Development, gdzie ścieżka przebiegu programu jest sterowana wyrzucaniem wyjątków.
Drugim źródłem takiego podejścia, na szczęście coraz rzadszym, jest próba przeniesienia mechanizmu przerwań do wysokopoziomowego kodu. W Javie sprzyja temu metoda Thread.interrupt oraz historyczne zaszłości związane z pisaniem kodu wielowątkowego na niskim poziomie. W takim przypadku wyjątki są stosowane, by obsługiwać sytuacje, które są na poziomie technicznym do przewidzenia i które powinny finalnie informować użytkownika, że jest aplikacja ma np. niespójne dane.

Wyjątki zostawmy dla błędów technicznych np. braku plików konfiguracyjnych.

Jak nie wyjątek to co?

Status, a na poziomie kontrolera np. pattern matching z vavr:

return Match(order).of(
        Case($(ord -> ord.alreadyExist()),
                Response.Conflict_409
        ),
        Case($(v ->ord.notExist()),
                Response.NotFound_404
        Case($(), Response.OK_200)
);

0

Szczerze mówiąc nie rozumiem tego, co napisał @Koziołek

Idąc tym tropem rozumowania, to jeśli gdzieś mamy catch, to nie powinien to być wyjątek? Wszak jeśli łapiemy wyjątek, to znaczy, że przewidujemy, że może on być rzucony i wiemy, jak nań zareagować, a w takim razie jest to sytuacja "sensowna biznesowo" (bo możemy obsłużyć wyjątek na poziomie aplikacji i kontynuować działanie, a nie się wywalić), więc nie jest to sytuacja wyjątkowa.

Jak nie wyjątek to co?

Status,

No ale chyba właśnie wyjątki były przewidziane jako alternatywa dla zwracania kodów błędów, których obsługa jest niewygodna i sama jest błędogenna?

To podejście "Nie używać wyjątków" sprowadza się do tego, że wracamy się do zabaw rodem z C?

1

@kmph Dla Ciebie do pooglądania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1