Not getting ThreadContext values even after setting "isThreadContextMapInheritable" to true, using Vert.x and Log4j2

1.3k views Asked by At

I am using Vertx and Log4j2.

This is the code for Remote.java

public class Remote extends AbstractVerticle {

    @Override
    public void start() throws Exception {
        System.setProperty("isThreadContextMapInheritable", "true");
        ThreadContext.put("1", "Company");
        ThreadContext.put("2", "Sector");
        ThreadContext.put("3", "Address");
        ArrayList<String> arrayList = new ArrayList<>();
        for (int i = 1; i < 4; i++) {
            arrayList.add(String.valueOf(i));
        }
        arrayList.parallelStream().forEach(s -> {
            System.out.println("Key " + s + " Value is " + ThreadContext.get(s) + " Name: " + Thread.currentThread().getName());
        });
        System.out.println("After parallelStream");
    }
}

This is my code for StartVerticle.java

public class StartVerticle {

    public static void main(String[] args) {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(new Remote());
    }
}

My output when I run the above the code is

Key 2 Value is Sector Name: vert.x-eventloop-thread-0
Key 1 Value is null Name: ForkJoinPool.commonPool-worker-3
Key 3 Value is null Name: ForkJoinPool.commonPool-worker-5
After parallelStream

Could you please help me in getting the following output?

Key 2 Value is Sector Name: vert.x-eventloop-thread-0
Key 1 Value is Company Name: ForkJoinPool.commonPool-worker-3
Key 3 Value is Address Name: ForkJoinPool.commonPool-worker-5
After parallelStream

I also printed the thread name for reference. Without using the Vertx, I was able to print all the contents in the ThreadContext, after setting isThreadContextMapInheritable to true.

1

There are 1 answers

1
Prasanna On

Vertx and Parallel Stream both use the Fork Join Common Pool. Only the thread context values set before the initialization of common pool are available in the child threads.


Even without Vertx, the ThreadContext values set after the first parallel stream, will not be available in the child threads. For example,

public static void main(String[] args) throws Exception {
    System.setProperty("isThreadContextMapInheritable", "true");
    IntStream.range(0, 5)
             .parallel()
             .forEach(System.out::println);
    ThreadContext.put("1", "Company");
    ThreadContext.put("2", "Sector");
    ThreadContext.put("3", "Address");

    ArrayList<String> arrayList = new ArrayList<>();
    for (int i = 1; i < 4; i++) {
        arrayList.add(String.valueOf(i));
    }
    arrayList.parallelStream()
             .forEach(s -> {
                 System.out.println("Key " + s + " Value is " + ThreadContext.get(s) + " Name: " + Thread.currentThread()
                                                                                                         .getName());
             });
}

This would print

Key 1 Value is null Name: ForkJoinPool.commonPool-worker-5
Key 3 Value is null Name: ForkJoinPool.commonPool-worker-1
Key 2 Value is Sector Name: main

In our case, common pool is initialized when Vertx starts. At that point, there are no thread context values are set.
So one option is to set the thread context in main() before starting vertx.

public static void main(String[] args) {
    System.setProperty("isThreadContextMapInheritable", "true");
    ThreadContext.put("1", "Company");
    ThreadContext.put("2", "Sector");
    ThreadContext.put("3", "Address");
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(new Remote());
}

which produces the output,

Key 2 Value is Sector Name: vert.x-eventloop-thread-0
Key 3 Value is Address Name: ForkJoinPool.commonPool-worker-2
Key 1 Value is Company Name: ForkJoinPool.commonPool-worker-1
After parallelStream