Условное исполнение проекта Реактор

У меня есть объект для сохранения (в MongoDB), но перед этим мне нужно проверить, верны ли некоторые условия.

Объект содержит идентификаторы других объектов. Это выглядит как

"object": {
   "id": "123",
   "subobject1": { "id": "1" },
   "subobject2": { "id": "2" }
}

Подобъекты содержат только идентификатор, остальная информация находится в другой коллекции, поэтому я должен проверить, существует ли эта информация.

В блочном стиле я могу сделать что-то вроде

    if (!languageRepository.exists(Example.of(wordSet.getNativeLanguage())).block()) {
        throw new RuntimeException("Native language doesn't exist");
    }

    if (!languageRepository.exists(Example.of(wordSet.getTargetLanguage())).block()) {
        throw new RuntimeException("Target language doesn't exist");
    }

и только тогда я могу сохранить свой объект

return wordSetRepository.save(wordSet);

Как сделать это в "реактивном" стиле без блокировки?

languageRepository.exists, Example.of, wordSet.getTargetLanguage () - что все это значит?

Alexei Kaigorodov 16.04.2018 17:21

Мы переходим в languageRepository, чтобы проверить, существуют ли там nativeLanguage и targetLanguage (подобъект1 и подобъект2). Если они существуют в languageRepository, мы можем сохранить этот объект (wordSet) в wordSetRepository

Вадим Парафенюк 16.04.2018 17:27

wordSet будет сохранен только с идентификаторами nativeLanguage и targetLanguage, а не с полными объектами. Полные объекты находятся в languageRepository.

Вадим Парафенюк 16.04.2018 17:28

Я имею в виду, что это за объекты? использование block() указывает на то, что languageRepository.exists - это Mono<Boolean>. Какие еще?

Alexei Kaigorodov 16.04.2018 20:34

targetLanguage и nativeLanguage относятся к типу Language (только некоторые поля и идентификатор). WordSet содержит несколько полей (включая targetLanguage и nativeLanguage) и идентификатор.

Вадим Парафенюк 16.04.2018 21:16

in Если я проверю, сохранены ли уже эти объекты в languageRepository (exists (...). block ()). Если нет - исключение. Если они существуют -> сохраните набор слов (но вместо языков я сохраняю только идентификаторы языков в наборе слов).

Вадим Парафенюк 16.04.2018 21:18

Когда я хочу получить набор слов, я использую агрегацию для получения языков по идентификатору. Но когда я сохраняю WordSet, я хочу сохранить только идентификаторы языков (поэтому необходимо гарантировать наличие языков в другом репозитории)

Вадим Парафенюк 16.04.2018 21:20
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
7
10 536
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите распространять отдельные ошибки для случаев ошибок на родном и целевом языках, вам необходимо выполнить асинхронную фильтрацию внутри flatMap:

objectFlux.flatMap(o ->
    Mono.just(o)
        .filterWhen(languageRepository.exists(...)) //native
        .switchIfEmpty(Mono.error(new RuntimeException("Native language doesn't exist"))
        .filterWhen(languageRepository.exists(...)) //target
        .switchIfEmpty(Mono.error(new RuntimeException("Target language doesn't exist"))
    )
    .flatMap(wordSetRepository::save);

Асинхронная фильтрация внутри flatMap гарантирует, что если тест не пройдет, внутренняя последовательность будет пустой. Это, в свою очередь, позволяет нам обнаружить случай и распространить соответствующую ошибку. Если оба теста пройдены, исходный o распространяется в основной последовательности.

Второй flatMap берет его оттуда, только принимая элементы, прошедшие оба фильтра, и сохраняет их в БД.

Обратите внимание, что первый элемент, не прошедший фильтры, прервет всю последовательность (но это было то же самое в коде блокировки, так как было сгенерировано исключение).

Спасибо! Еще один вопрос: в методе должен быть входной параметр objectFlux? Я имею в виду, что этот метод находится на уровне сервиса и требует только «Object» (без Mono <Object> или Flux <Object>). Можно ли использовать только «Mono.just (object)»?

Вадим Парафенюк 18.04.2018 11:30

оба хороши, типичное использование Mono.just заключается в том, чтобы действовать как метод преобразования на границе, где императивный устаревший код встречается с обновленным реактивным кодом.

Simon Baslé 23.04.2018 10:41

Другие вопросы по теме