Operacja usuwania w Spring Reactive, a manipulowanie odpowiedzią servera

0

Witam,
Mam taki kod

  public Mono<ServerResponse> deleteItem(ServerRequest serverRequest) {
        String id = serverRequest.pathVariable("id");
        Mono<Void> voidMono = itemReactiveRepository.deleteById(id);

        return ServerResponse.ok()
                .contentType(APPLICATION_JSON)
                .body(voidMono, Void.class);

    }

Tutaj, w powyższym kodzie zawsze dostaję odpowiedź od serwera OK. W jaki sposób mógłbym zmienić tą metodę, aby w przypadku braku obiektu w repozytorium zwrócić status "not found". Myślałem nad dodaniem metody existsById, a następnie czy zwraca "false", "true" to dopiero zrobić operację usuwania. Tak miałem w zwyczaju czynić w aplikacjach w Springu MVC imperatywnie. Jestem nowy w Spring Reactive i chciałbym się dowiedzieć jak tutaj mógłbym obsługiwać takie wyjątki i manipulować odpowiedzią serwera. Dzięki za odpowiedź

2

Pierwszy z brzegu link ze Stacka: https://stackoverflow.com/questions/51024279/how-to-handle-errors-in-spring-reactor-mono-or-flux

Musisz zmienić myślenie. Zamiast sprawdzać czy jest wartość czy nie dostajesz strumień, który wyemituje wartość lub będzie pusty i zapinasz się operatorem switchIfEmpty(). Zamiast wyjątków masz strumień z błędem, który możesz obsłużyć operatorem z rodziny onErrorXXX().

W Twoim przykładzie z controllera możesz zwrócić po prostu Mono<Void>, jeśli jest to @RestController, to Spring prawdopodobnie to skonwertuje na pustego jsona z 200 OK by default.

Do nauki Reactora, który stanowi tutaj fundament, proponuję https://github.com/nurkiewicz/reactor-workshop i oczywiście dokumentację, która jest całkiem przystępna.

0

Dzięki wielkie!

0

Chciałbym zwracać Mono<ServerResponse>, Próbowałem coś takiego stworzyć, jednak wciąż mam problem

    public Mono<ServerResponse> deleteItem(ServerRequest serverRequest) {
        String id = serverRequest.pathVariable("id");
        Mono<ServerResponse> notFound = ServerResponse.notFound().build()
        Mono<Item> deletedItem =
                itemReactiveRepository.findById(id).doOnSuccess(item -> itemReactiveRepository.deleteById(item.getId()));


        return ServerResponse.ok()
                .contentType(APPLICATION_JSON)
                .body(deletedItem, Item.class)
                .switchIfEmpty(notFound);

    }
1
prop_solo napisał(a):

Chciałbym zwracać Mono<ServerResponse>, Próbowałem coś takiego stworzyć, jednak wciąż mam problem

    public Mono<ServerResponse> deleteItem(ServerRequest serverRequest) {
        ...
        return ServerResponse.ok()
    }

zgaduje że chodzi ci o to że zwracasz ServerResponse a w metodzie podajesz Mono<ServerResponse>
opakuj to w mono za pomocą Mono.just()

0

Chodzi mi o to, aby zwracać status 404 albo 200 w zależności czy Item istniał w bazie danych i został usunięty (200) --- czy nie istniał i nie został usunięty (404).

1

Ciągle masz błędne myślenie. ServerResponse.ok().body() zwraca Mono<ServerResponse>, które nigdy nie będzie puste.
Chcesz zareagować na pusty stream, który pochodzi z repozytorium, a nie na stream, który tworzysz poprzez ServerResponse.ok().body().

0

Dzięki Panowie za rady, siedziałem dzisiaj nad tym popołudnie niedzielne ale się udało, tutaj rozwiązanie jakby ktoś chciał.


    public Mono<ServerResponse> deleteItem(ServerRequest request) {
        String itemId = request.pathVariable("id");
        return itemReactiveRepository.findById(itemId)
                .flatMap(item -> itemReactiveRepository
                        .delete(item)
                        .then(ServerResponse.ok().build()))
                .switchIfEmpty(ServerResponse.notFound().build());
    }
2

To działa ok :)
Wołasz metodę delete, która zapewne zwraca Mono (sądząc po nazwie zmiennej), ale element nigdy nie zostanie usunięty, ponieważ nic nie subskrybuje rezultatu, toteż przy kolejnym wywołaniu findById znowu znajduje item o danym id.
Możesz na przykład mapować item zwrócony przez findById na rezultat zwrócony przez funkcję delete(), dopiero potem mapowanie na ServerResponse lub switchIfEmpty.

0

Dzięki, już zrozumiałem jak to działa, powyżej wrzuciłem rozwiązanie. Miłej niedzieli!

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