WebFlux возвращает http.okay порок http.notFound - PullRequest
0 голосов
/ 01 июля 2019

Новое в WebFlux, реактиве и обработчиках. У меня все «работает», но я не понимаю, почему следующий код возвращает «хорошо» с пустым телом, а «не найден».

Разъяснение: проблема заключается в заключительном операторе возврата DemoPOJOHandler.getById () . Код «короткого замыкания» работает должным образом (т. Е. Возвращает состояние «Неверный запрос»), но путь «switchIfEmpty» в последнем операторе возврата не выполняется, если DemoPOJORepo.getById (int) возвращает Mono.empty () .

(Примечание: я взломал «репо» на основе списка, чтобы избежать работы с базой данных при выяснении обработчиков и типов возврата http.)

Реализация маршрутизатора ("/ v1" - это набор конечных точек RESTful на основе аннотаций) ...

@Configuration
public class DemoPOJORouter {

    @Bean
    public RouterFunction<ServerResponse> route(DemoPOJOHandler requestHandler) {
        return nest(path("/v2"),
               nest(accept(APPLICATION_JSON),
               RouterFunctions.route(RequestPredicates.GET("/DemoPOJO"), requestHandler::getAll)
                           .andRoute(RequestPredicates.GET("/DemoPOJO/{id}"), requestHandler::getById)
                           .andRoute(RequestPredicates.POST("/DemoPOJO"), requestHandler::add)));
    }
}

Реализация обработчика была "урезана" только до рассматриваемого кода. У меня есть ощущение, что большая часть стиля «все еще обязательна», но я попытался поставить реактивные вещи там, где они «наиболее разумны».

Если я предоставлю неверное значение в URI (то есть, "foo"), тогда я получу http "неверный запрос". Но, похоже, никогда не получит «not found», которое должно быть сгенерировано « switchIfEmpty », если указано правильно отформатированное значение int, но оно не отображается на запись в репо.

@Component
public class DemoPOJOHandler {

    public static final String PATH_VAR_ID = "id";

    private DemoPOJORepo repo = null;

    public Mono<ServerResponse> getById(ServerRequest request) {
        Mono<DemoPOJO>      monoDemoPOJO  = null;
        Map<String, String> pathVariables = request.pathVariables();
        int                 id            = -1;

        checkRepoRef(); // part of the list hack

        // short-circuit if request doesn't contain id (should never happen)
        if ((pathVariables == null)
         || (!pathVariables.containsKey(PATH_VAR_ID))) {
            return ServerResponse.badRequest().build();
        }

        // short-circuit if bad id value
        try {
            id = Integer.parseInt(pathVariables.get(PATH_VAR_ID));
        } catch(NumberFormatException e) {
            return ServerResponse.badRequest().build();
        }

        // get entity by keyValue
        monoDemoPOJO = repo.getById(id);

        return monoDemoPOJO
                   .flatMap(demoPOJO -> ServerResponse.ok()
                                                      .contentType(MediaType.APPLICATION_JSON)
                                                      .syncBody(demoPOJO)
                   .switchIfEmpty(ServerResponse.notFound().build()));
    }

}

Хак репозитория на основе списка, чтобы избежать работы с данными / API при работе с обработчиками и типами возврата http.

// local hack to avoid a database for testing
public class DemoPOJORepo {

    private static DemoPOJORepo fpRepo   = null;
    private static int          NUM_ROWS = 100;

    private Map<Integer, DemoPOJO> fooPOJOMap;

    private DemoPOJORepo() {
        initMap();
    }

    public static DemoPOJORepo getInstance() {
        if (fpRepo == null) {
            fpRepo = new DemoPOJORepo();
        }
        return fpRepo;
    }

    public Mono<DemoPOJO> getById(int id) {
        Mono<DemoPOJO> monoDP;

        if (fooPOJOMap.containsKey(id)) {
            monoDP = Mono.just(fooPOJOMap.get(id));
        } else {
            monoDP = Mono.empty();
        }
        return monoDP;
    }

    private Mono<Void> initMap() {
        fooPOJOMap = new TreeMap<Integer, DemoPOJO>();
        int offset = -1;

        for(int ndx=0; ndx<NUM_ROWS; ndx++) {
            offset = ndx + 1;
            fooPOJOMap.put(offset, new DemoPOJO(offset, "foo_" + offset, offset+100));
        }
        return Mono.empty();
    }
}

Ответы [ 2 ]

0 голосов
/ 02 июля 2019

Ваши скобки находятся не в том месте, в результате чего swithIfEmpy применяется к ServerResponse.ok() издателю, а не monoDemoPOJO, замените возврат на это, и оно должно работать:

return monoDemoPOJO
                   .flatMap(demoPOJO -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).syncBody(demoPOJO))
                   .switchIfEmpty(ServerResponse.notFound().build());
0 голосов
/ 01 июля 2019

Как я вижу, код правильный.Код ответа - Плохой запрос, потому что вы пытаетесь преобразовать «foo» в Integer, и когда он выдает исключение, вы возвращаете ответ «Плохой запрос», поэтому я думаю, что он работает отлично.Если вы используете целочисленный идентификатор, которого нет в вашей базе данных, ответ должен быть не найден

...