Ответы Spring Webflux и Observable не работают

Я только что создал простое приложение Spring Boot, используя spring-boot-starter-webflux с версией 2.0.0.BUILD-SNAPSHOT, которое приносит spring-webflux версии 5.0.0.BUILD-SNAPSHOT и то же самое для Spring Core, Beans, Context и т. Д.

Если я создам простой @RestController и предоставлю @GetMapping, который просто возвращает Flux<String>, тогда все будет работать, как ожидалось.

Однако, если я перейду с Flux на Observable RxJava, я получу эту ошибку:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

Немного отладив код, я обнаружил, что ObjectMapper Джексона каким-то образом регистрирует Flux, Mono и остальные реактивные типы в своем typeFactory, поэтому позже MappingJackson2HttpMessageConverter знает, как (де) -сериализовать их.

Однако это не тот случай, когда я использую Observable: я не нахожу тип Observable или Single, зарегистрированный в фабрике типов ObjectMapper, поэтому я получаю вышеупомянутую ошибку.

Кто-нибудь сталкивался с этой проблемой? Мне не хватает зависимости? Нужно ли мне вручную указывать Джексону, как (де) -сериализовать из конструкций RxJava? Но почему Джексон уже знает о Flux и Mono?

Спасибо за вашу помощь.

ИЗМЕНЕНО:

Я использую RxJava 1.2.7. Вот мой pom.xml:

<dependencies>
    <!-- Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
        <version>2.0.0.BUILD-SNAPSHOT</version>
    </dependency>
    <!-- RxJava dependeencies -->
    <dependency>
        <groupId>io.reactivex</groupId>
        <artifactId>rxjava</artifactId>
        <version>1.2.7</version>
    </dependency>
</dependencies>

А вот пример кода моего контроллера:

/**
 * Get all the available tasks.
 *
 * @return the list of tasks
 */
@GetMapping(path = "/task")
@ResponseStatus(HttpStatus.OK)
public Observable<TaskView> allTasks(@AuthenticationPrincipal LoggedUserVO principal) {
    return this.pocComponent.getAllTasks()
            .map(t -> ViewConverter.convertFromTaskDocument(t, principal));
}

person Enrique Medina    schedule 12.03.2017    source источник
comment
Можете ли вы опубликовать свой файл pom / gradle? Какую версию RxJava вы используете? Также добавьте код, например, ваш контроллер.   -  person M. Deinum    schedule 13.03.2017
comment
Я бы удалил version, поскольку Spring Boot уже управляет этим, вам также понадобится расширение reactive-streams для rxjava, чтобы сделать его интеграцию с Reactive.io, поскольку реактивные потоки являются точкой интеграции для различных реактивных реализаций.   -  person M. Deinum    schedule 13.03.2017
comment
Если я удалю версию для RxJava, я получу 1.1.8. Зависимость reactive-streams (версия 1.0.0) транзитивно получается через зависимость spring-boot-starter-webflux. В любом случае все равно не работает.   -  person Enrique Medina    schedule 13.03.2017
comment
Это странно, потому что когда я смотрю на управляемую зависимость 1.2.7 ... Все ли вы используете из Spring Boot 2.0.0 ??? Или вы только что включили эту зависимость в существующую старую версию весенней загрузки? Или короче можете добавить свой полный пом? Вам нужна зависимость rxjava-reactive-streams ...   -  person M. Deinum    schedule 13.03.2017


Ответы (2)


Вероятно, вам не хватает следующей зависимости, чтобы он работал:

<dependency>
    <groupId>io.reactivex</groupId>
    <artifactId>rxjava-reactive-streams</artifactId>
    <version>1.2.1</version>
</dependency>

Из-за изменений в различных версиях RxJava 1.x нам было сложно поддерживать его из коробки, поэтому мы предпочитаем полагаться на официальный адаптер RxJava -> Reactive Streams. Обратите внимание, что RxJava 2.x поддерживается без дополнительных зависимостей (изначально он построен поверх реактивных потоков).

Я собираюсь обновить Справочная документация Spring WebFlux, чтобы указать, что это необходимо для поддержки RxJava 1.x.

person Sébastien Deleuze    schedule 13.03.2017
comment
Себастьен, я добавил эту новую зависимость в свой pom.xml, но все равно получаю ту же ошибку. Также безуспешно пробовал с RxJava2. Не могли бы вы указать мне на код, в котором вы регистрируете тип Observable в Jackson, чтобы я мог проверить, действительно ли это сделано или нет? Спасибо. - person Enrique Medina; 13.03.2017
comment
Пока используется этот обходной путь: private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() { ... JsonSerializer<?> s = new StdSerializer<Observable<?>>(Observable.class, true) { @Override public void serialize( Observable<?> obs, JsonGenerator jgen, SerializerProvider p ) throws IOException { provider.findValueSerializer(Iterator.class, null) .serialize(obs.blockingIterable().iterator(), jgen, p); } }; om.registerModule(new SimpleModule("Observable API", Version.unknownVersion(), Arrays.asList(s))); return jackson; } - person Enrique Medina; 14.03.2017
comment
Хорошо, сегодня я посмотрю поглубже - person Sébastien Deleuze; 15.03.2017

Итак, Flux и Mono - это имена Spring, поскольку у Spring есть синдром Not-Invented-Here.

Вы можете либо зарегистрировать обработчик, который выполняет преобразование в типы, о которых знает Spring, использовать средство AsyncResponse, предоставляемое Джерси, либо везде добавить toBlocking.

person Tassos Bassoukos    schedule 12.03.2017
comment
Но в официальной документации Spring четко указано, что он поддерживает также RxJava с Observable и Single. Хотя заставить работать не могу. - person Enrique Medina; 12.03.2017
comment
Вместо того, чтобы пытаться разрушить фреймворк, вы хотите дать конструктивный ответ. (Насколько это можно считать ответом, поскольку на самом деле он не отвечает на вопрос). - person M. Deinum; 13.03.2017
comment
@ M.Deinum Я не критикую Spring, я использую его каждый день (и самый простой способ распознать ценность, которую он добавляет, - это попытаться использовать внутренний фреймворк после использования Spring) - я просто утверждаю, что у него есть тенденция к дублированию концепций в собственном пространстве имен. - person Tassos Bassoukos; 13.03.2017
comment
Что кричит в моей книге. Кроме того, вместо того, чтобы делать этот комментарий, вы можете проверить, ПОЧЕМУ под капотом есть реактивность (на самом деле для этого есть довольно веская причина, и это не имеет ничего общего с not-invented-here). - person M. Deinum; 13.03.2017