I have tried a solution. In which I have added my request header in reactor context. Than I used MdcContextLifter and MdcContextLifterConfiguration classes to update MDC whenever request changes the thread. So that Mdc data always in correct thread. But context getting empty somehow in the middle of request processing.
I added few debug logs and found that it becomes empty after this: [DEBUG] 2020-07-13 12:46:39.695 [reactor-http-epoll-3] r.n.h.c.HttpClientOperations
Actually I am new to reactor.
This is the way I am setting the reactor context inside the custom filter.
return chain.filter(exchange.mutate().request(builder.build()).build()).
subscriberContext(Context.of("myRequestHeader",headerValue))
Here is MdcContextLifter and MdcContextLifterConfiguration.
public class MdcContextLifter implements CoreSubscriber {
private CoreSubscriber coreSubscriber;
public MdcContextLifter(CoreSubscriber coreSubscriber) {
this.coreSubscriber = coreSubscriber;
}
@Override
public void onNext(T t) {
System.out.println("In onNext");
copyToMdc(coreSubscriber.currentContext());
coreSubscriber.onNext(t);
}
@Override
public void onSubscribe(Subscription subscription) {
coreSubscriber.onSubscribe(subscription);
}
@Override
public void onComplete() {
coreSubscriber.onComplete();
}
@Override
public void onError(Throwable throwable) {
coreSubscriber.onError(throwable);
}
@Override
public Context currentContext() {
return coreSubscriber.currentContext();
}
private void copyToMdc(Context context) {
if (!context.isEmpty()) {
System.out.println("Context not empty : ");
Map<String, String> map = context.stream()
.collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString()));
map.forEach((k,v) -> System.out.println(k + " : " + v));
MDC.setContextMap(map);
} else {
System.out.println("Context is empty");
MDC.clear();
}
}
}
@configuration
public class MdcContextLifterConfiguration {
private static final String MDC_CONTEXT_REACTOR_KEY = MdcContextLifterConfiguration.class.getName();
@PostConstruct
public void contextOperatorHook(){
Hooks.onEachOperator(MDC_CONTEXT_REACTOR_KEY, Operators.lift((scannable, coreSubscriber) -> new MdcContextLifter<>(coreSubscriber)));
}
@PreDestroy
public void cleanupHook(){
Hooks.resetOnEachOperator(MDC_CONTEXT_REACTOR_KEY);
}
}