Tengo un problema de comprensión contextual . Así documentaciones dice que Contexto es:
Una tienda de clave / valor que se propaga entre los componentes tales como los operadores a través del protocolo contexto. Los contextos son ideales para el transporte de la información ortogonal como el trazado o tokens de seguridad.
Excelente.
Ahora supongamos que queremos para propagar algo utilizando Contexto tenerlo en todas partes. Para llamar a otro código asíncrono simplemente usamos el flatMap () método.
Problema : ¿Cómo acceder Contexto dentro denominado método?
Muestra (simple) código:
public class TestFlatMap {
public static void main(final String ...args) {
final Flux<String> greetings = Flux.just("Hubert", "Sharon")
.flatMap(TestFlatMap::nameToGreeting)
.subscriberContext(context ->
Context.of("greetingWord", "Hello") // context initialized
);
greetings.subscribe(System.out::println);
}
private static Mono<String> nameToGreeting(final String name) {
return Mono.just("Hello " + name + " !!!"); // ALERT: we don't have Context here
}
}
El método llamado puede ser (y lo más probable será) en otra clase.
Gracias por la ayuda de antemano !
Editar : retira un poco de código para hacer la pregunta más conciso y directo al grano.
Cadena tu Publisher
s y que el Context
estar contigo
En el caso, conectado todos sus Publisher
s (y esto incluye conexiones dentro de la flatMap
/ concatMap
y operadores similares) se ha Context
propagado correctamente entre todo el tiempo de ejecución de flujo.
Para el acceso Context
en el nameToGreeting
método, puede llamar Mono.subscribeContext
y recuperar información almacenada caso si parece que los métodos no están relacionados. A continuación se muestra el concepto antes mencionado:
public class TestFlatMap {
public static void main(final String ...args) {
final Flux<String> greetings = Flux.just("Hubert", "Sharon")
.flatMap(TestFlatMap::nameToGreeting)
.subscriberContext(context ->
Context.of("greetingWord", "Hello") // context initialized
);
greetings.subscribe(System.out::println);
}
private static Mono<String> nameToGreeting(final String name) {
return Mono.subscriberContext()
.filter(c -> c.hasKey("greetingWord"))
.map(c -> c.get("greetingWord"))
.flatMap(greetingWord -> Mono.just(greetingWord + " " + name + " " + "!!!"));// ALERT: we have Context here !!!
}
}
Además, se puede hacer lo mismo de la siguiente manera, usando zip
el operador, para combinar los resultados más adelante:
public class TestFlatMap {
public static void main(final String ...args) {
final Flux<String> greetings = Flux.just("Hubert", "Sharon")
.flatMap(TestFlatMap::nameToGreeting)
.subscriberContext(context ->
Context.of("greetingWord", "Hello") // context initialized
);
greetings.subscribe(System.out::println);
}
private static Mono<String> nameToGreeting(final String name) {
return Mono.zip(
Mono.subscriberContext()
.filter(c -> c.hasKey("greetingWord"))
.map(c -> c.get("greetingWord")), // ALERT: we have Context here !!!
Mono.just(name),
(greetingWord, receivedName) -> greetingWord + " " + receivedName + " " + "!!!"
);
}
}
Por lo tanto, por qué funciona?
Como podemos ver en el ejemplo anterior, la nameToGreeting
que se llama en el contexto de la principal Flux
. Bajo el capó -> (Aquí algunos detalles internos FluxFlatMap) , cada una asignada Publisher
está suscrito por FlatMapInner
. Si nos fijamos en el FlatMapInner
y el aspecto de la currentContext
anulación veremos, que FlatMapInner
usos de los padres Context
, que significa que si el padre tiene un Reactor Context
- entonces este contexto se propagará a cada interno Publisher
.
Por lo tanto, devuelto por el nameToGreeting
método Mono
tendrá el mismo Context
como su padre