Skip to content

Latest commit

 

History

History
115 lines (94 loc) · 4.26 KB

File metadata and controls

115 lines (94 loc) · 4.26 KB

MicroProfile Context Propagation Examples

This section includes some additional examples of spec usage.

Contextualize a new CompletableFuture and all dependent stages

    executor = ManagedExecutor.builder()
                   .cleared(ThreadContext.TRANSACTION, ThreadContext.SECURITY)
                   .propagated(ThreadContext.ALL_REMAINING)
                   .build();

    CompletableFuture<Long> stage1 = executor.newIncompleteFuture();
    stage1.thenApply(function1)      // runs with captured context
          .thenApply(function2);     // runs with captured context
    stage1.completeAsync(supplier1); // runs with captured context

Apply thread context to a CompletionStage and all its dependent stages

    threadContext = ThreadContext.builder()
                        .propagated(ThreadContext.SECURITY)
                        .unchanged()
                        .cleared(ThreadContext.ALL_REMAINING)
                        .build();

    stage = threadContext.withContextCapture(invokeSomeMethodThatReturnsUnmanagedCompletionStage());
    stage.thenApply(function1)  // runs with captured context
         .thenAccept(consumer); // runs with captured context

Apply thread context to a single CompletionStage action

    threadContext = ThreadContext.builder()
                        .propagated(ThreadContext.SECURITY)
                        .unchanged()
                        .cleared(ThreadContext.ALL_REMAINING)
                        .build();

    Consumer<String> contextualConsumer = threadContext.contextualConsumer(s -> {
            ... do something that requires context
        });

    stage = invokeSomeMethodThatReturnsUnmanagedCompletionStage();
    stage.thenApply(function1)            // context is unpredictable
         .thenAccept(contextualConsumer); // runs with captured context

Reusable Context Snapshot

    threadContext = ThreadContext.builder()
                                 .cleared(ThreadContext.TRANSACTION)
                                 .unchanged(ThreadContext.SECURITY)
                                 .propagated(ThreadContext.ALL_REMAINING)
                                 .build();
    contextSnapshot = threadContext.currentContextExecutor();

    ... on some other thread,
    contextSnapshot.execute(() -> {
        ... do something that requires the previously captured context
    });

Run under the transaction of the executing thread

If you do not want to either propagate or clear a context, you need to explicitly mark it as unchanged. In this example we want to capture and propagate only the application context, but we don’t want to clear the transaction context because we’re going to manually set it up for the new thread where we’re going to use the captured application context:

    threadContext = ThreadContext.builder()
                        .propagated(ThreadContext.APPLICATION)
                        .unchanged(ThreadContext.TRANSACTION)
                        .cleared(ThreadContext.ALL_REMAINING)
                        .build();

    Callable<Integer> updateDatabase = threadContext.contextualCallable(() -> {
        DataSource ds = InitialContext.doLookup("java:comp/env/ds1");
        try (Connection con = ds.getConnection()) {
            return con.createStatement().executeUpdate(sql);
        }
    }));

    ... on some other thread,

    tx.begin();
    ... do transactional work
    // runs as part of the transaction, but with the captured application scope
    updateDatabase.call();
    ... more transactional work
    tx.commit();