Контекст Spring Webflux Reactor

В следующем примере test2 должен иметь доступ к значениям context из test и test1, но похоже, что этого не происходит.

Любое понимание приветствуется.

Рекомендации:

  1. http://projectreactor.io/docs/core/release/reference/#context
  2. https://jira.spring.io/browse/SPR-15680
  3. https://simonbasle.github.io/2018/02/contextual-logging-with-reactor-context-and-mdc/.

    import reactor.core.publisher.Mono;
    public class Test {
    
        public static void main(final String[] args) {
            System.out.println(Thread.currentThread().getName()
                + " main "
                + test());
        }
    
        public static String test() {
            final String key = "message";
            return test1().subscriberContext(ctx -> ctx.put(key, "test")).block();
        }
    
        public static Mono<String> test1() {
            final String key = "message1";
            return test2().subscriberContext(ctx -> ctx.put(key, "test1 "));
        }
    
        public static Mono<String> test2() {
            return Mono.just("test2").map(item -> {
                Mono.subscriberContext().map(context -> {
                    System.err.println(Thread.currentThread().getName()
                        + " test2 "
                        + context);
                    return context;
                });
                return item;
            });
        }}
    

Выход:

main main test2
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
7 694
2

Ответы 2

Похоже, что следующий код работает нормально, но все еще не уверен, почему код в вопросе не работает.

import reactor.core.publisher.Mono;

public class Test {

    public static void main(final String[] args) {
        System.out.println(Thread.currentThread().getName()
            + " main "
            + test());
    }

    public static String test() {
        final String key = "message";
        return test1().subscriberContext(ctx -> ctx.put(key, "test")).block();
    }

    public static Mono<String> test1() {
        final String key = "message1";
        return test2().flatMap(item -> {
            Mono.subscriberContext().map(context -> {
                System.err.println(Thread.currentThread().getName()
                    + " test1 "
                    + context);
                return context;
            });
            return Mono.just(item);
        }).subscriberContext(ctx -> ctx.put(key, "test1 "));
    }

    public static Mono<String> test2() {
        final String key = "message2";
        return Mono.subscriberContext().flatMap(context -> {
            System.err.println(context);
            return Mono.just("test2");
        }).subscriberContext(ctx -> ctx.put(key, "test2"));
    }

}

Я думаю, вы хотели получить доступ к контексту подписчика в test2 (), верно? Это работает, только если вы действительно находитесь в одном потоке, поэтому этот фрагмент исправит исходный код: Оригинал:

public static Mono<String> test2() {
    return Mono.just("test2").map(item -> {
        // you're creating a new Mono context here, and don't return it/use it anymore
        Mono.subscriberContext().map(context -> {
            System.err.println(Thread.currentThread().getName()
                + " test2 "
                + context);
            return context;
        });
        return item;
    });

Исправлено (с минимальным количеством изменений, можно было бы улучшить):

public static Mono<String> test2() {
  return Mono.just("test2").flatMap(item -> { // changed map to flatmap, otherwise would be Mono<Mono<String>> here
    Mono<Context> contextMono = Mono.subscriberContext()
        .map(context -> {
          System.err.println(Thread.currentThread()
                                 .getName() + " test2 " + context);
          return context;
        });
    // let item be returned from "inside" of context Mono
    return contextMono.map(context -> item);
  });

Я постоянно борюсь с контекстом подписчика - мне не очень понятно, когда контекст использовался по назначению, а когда нет. Надеюсь, это поможет.

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