Java Code Examples for org.eclipse.microprofile.context.ManagedExecutor

The following examples show how to use org.eclipse.microprofile.context.ManagedExecutor. These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
/**
 * Set some state on Request scoped bean and verify
 * the state is propagated to the thread where the other task runs.
 *
 * If the CDI context in question is not active, the test is deemed successful as there is no propagation to be done.
 *
 * @throws Exception indicates test failure
 */
@Test
public void testCDIMECtxPropagatesRequestScopedBean() throws Exception {
    // check if given context is active, if it isn't test ends successfully
    try {
        bm.getContext(RequestScoped.class);
    } catch (ContextNotActiveException e) {
        return;
    }

    ManagedExecutor propagateCDI = ManagedExecutor.builder().propagated(ThreadContext.CDI)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Instance<RequestScopedBean> selectedInstance = instance.select(RequestScopedBean.class);
    assertTrue(selectedInstance.isResolvable());
    try {
        checkCDIPropagation(true, "testCDI_ME_Ctx_Propagate-REQUEST", propagateCDI,
                selectedInstance.get());
    } 
    finally {
        propagateCDI.shutdown();
    }
}
 
Example 2
/**
 * Set some state on Session scoped bean and verify
 * the state is propagated to the thread where the other task runs.
 *
 * If the CDI context in question is not active, the test is deemed successful as there is no propagation to be done.
 *
 * @throws Exception indicates test failure
 */
@Test
public void testCDIMECtxPropagatesSessionScopedBean() throws Exception {
    // check if given context is active, if it isn't test ends successfully
    try {
        bm.getContext(SessionScoped.class);
    } catch (ContextNotActiveException e) {
        return;
    }

    ManagedExecutor propagateCDI = ManagedExecutor.builder().propagated(ThreadContext.CDI)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Instance<SessionScopedBean> selectedInstance = instance.select(SessionScopedBean.class);
    assertTrue(selectedInstance.isResolvable());
    try {
        checkCDIPropagation(true, "testCDI_ME_Ctx_Propagate-SESSION", propagateCDI,
                selectedInstance.get());
    }
    finally {
        propagateCDI.shutdown();
    }
}
 
Example 3
/**
 * Set some state on Conversation scoped beans and verify
 * the state is propagated to the thread where the other task runs.
 *
 * If the CDI context in question is not active, the test is deemed successful as there is no propagation to be done.
 *
 * @throws Exception indicates test failure
 */
@Test
public void testCDIMECtxPropagatesConversationScopedBean() throws Exception {
    // check if given context is active, if it isn't test ends successfully
    try {
        bm.getContext(ConversationScoped.class);
    } catch (ContextNotActiveException e) {
        return;
    }

    ManagedExecutor propagateCDI = ManagedExecutor.builder().propagated(ThreadContext.CDI)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Instance<ConversationScopedBean> selectedInstance = instance.select(ConversationScopedBean.class);
    assertTrue(selectedInstance.isResolvable());
    try {
        checkCDIPropagation(true, "testCDI_ME_Ctx_Propagate-CONVERSATION", propagateCDI,
                selectedInstance.get());
    }
    finally {
        propagateCDI.shutdown();
    }
}
 
Example 4
/**
 * Set some state on Request scoped bean and verify
 * the state is cleared on the thread where the other task runs.
 *
 * If the CDI context in question is not active, the test is deemed successful as there is no propagation to be done.
 *
 * @throws Exception indicates test failure
 */
@Test
public void testCDIMECtxClearsRequestScopedBean() throws Exception {
    // check if given context is active, if it isn't test ends successfully
    try {
        bm.getContext(RequestScoped.class);
    } catch (ContextNotActiveException e) {
        return;
    }

    ManagedExecutor propagatedNone = ManagedExecutor.builder()
            .propagated() // none
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Instance<RequestScopedBean> selectedInstance = instance.select(RequestScopedBean.class);
    assertTrue(selectedInstance.isResolvable());
    try {
        checkCDIPropagation(false, "testCDI_ME_Ctx_Clear-REQUEST", propagatedNone,
                selectedInstance.get());
    } 
    finally {
        propagatedNone.shutdown();
    }
}
 
Example 5
/**
 * Set some state on Session scoped bean and verify
 * the state is cleared on the thread where the other task runs.
 *
 * If the CDI context in question is not active, the test is deemed successful as there is no propagation to be done.
 *
 * @throws Exception indicates test failure
 */
@Test
public void testCDIMECtxClearsSessionScopedBeans() throws Exception {
    // check if given context is active, if it isn't test ends successfully
    try {
        bm.getContext(SessionScoped.class);
    } catch (ContextNotActiveException e) {
        return;
    }

    ManagedExecutor propagatedNone = ManagedExecutor.builder()
            .propagated() // none
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Instance<SessionScopedBean> selectedInstance = instance.select(SessionScopedBean.class);
    assertTrue(selectedInstance.isResolvable());

    try {
        checkCDIPropagation(false, "testCDI_ME_Ctx_Clear-SESSION", propagatedNone,
                selectedInstance.get());
    }
    finally {
        propagatedNone.shutdown();
    }
}
 
Example 6
/**
 * Set some state on Conversation scoped bean and verify
 * the state is cleared on the thread where the other task runs.
 *
 * If the CDI context in question is not active, the test is deemed successful as there is no propagation to be done.
 *
 * @throws Exception indicates test failure
 */
@Test
public void testCDIMECtxClearsConversationScopedBeans() throws Exception {
    // check if given context is active, if it isn't test ends successfully
    try {
        bm.getContext(ConversationScoped.class);
    } catch (ContextNotActiveException e) {
        return;
    }

    ManagedExecutor propagatedNone = ManagedExecutor.builder()
            .propagated() // none
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Instance<ConversationScopedBean> selectedInstance = instance.select(ConversationScopedBean.class);
    assertTrue(selectedInstance.isResolvable());
    try {
        checkCDIPropagation(false, "testCDI_ME_Ctx_Clear-CONVERSATION", propagatedNone,
                selectedInstance.get());
    }
    finally {
        propagatedNone.shutdown();
    }
}
 
Example 7
@Test
public void testAsyncTransaction() {
    // create an executor that propagates the transaction context
    ManagedExecutor executor = createExecutor("testAsyncTransaction");

    if (executor == null) {
        return; // the implementation does not support transaction propagation
    }

    try {
        // delegate this test to transactionalService which manages transactional
        // boundaries using the @Transactional annotation
        int result = transactionalService.testAsync(executor);
        if (result != UNSUPPORTED) {
            Assert.assertEquals(1, result,
                    "testAsyncTransaction failed%n");
        }
        verifyNoTransaction();
    }
    finally {
        executor.shutdownNow();
    }
}
 
Example 8
@Test
@Ignore
public void testConcurrentTransactionPropagation() {
    // create an executor that propagates the transaction context
    ManagedExecutor executor = createExecutor("testConcurrentTransactionPropagation");
    UserTransaction ut = getUserTransaction("testConcurrentTransactionPropagation");

    if (executor == null || ut == null) {
        return; // the implementation does not support transaction propagation
    }

    try {
        int result = transactionalService.testConcurrentTransactionPropagation(executor);
        if (result != UNSUPPORTED) {
            Assert.assertEquals(2, result, "testTransactionPropagation failed%n");
        }
        verifyNoTransaction();
    }
    finally {
        executor.shutdownNow();
    }
}
 
Example 9
Source Project: quarkus   Source File: CaffeineCacheBuildRecorder.java    License: Apache License 2.0 6 votes vote down vote up
public void buildCaches(boolean managedExecutorInitialized, BeanContainer beanContainer,
        Set<CaffeineCacheInfo> cacheInfos) {
    // The number of caches is known at build time so we can use fixed initialCapacity and loadFactor for the caches map.
    Map<String, CaffeineCache> caches = new HashMap<>(cacheInfos.size() + 1, 1.0F);

    ManagedExecutor managedExecutor = null;
    if (managedExecutorInitialized) {
        managedExecutor = beanContainer.instance(ManagedExecutor.class);
    }

    for (CaffeineCacheInfo cacheInfo : cacheInfos) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debugf(
                    "Building Caffeine cache [%s] with [initialCapacity=%s], [maximumSize=%s], [expireAfterWrite=%s] and [expireAfterAccess=%s]",
                    cacheInfo.name, cacheInfo.initialCapacity, cacheInfo.maximumSize, cacheInfo.expireAfterWrite,
                    cacheInfo.expireAfterAccess);
        }
        CaffeineCache cache = new CaffeineCache(cacheInfo, managedExecutor);
        caches.put(cacheInfo.name, cache);
    }

    beanContainer.instance(CacheRepository.class).setCaches(caches);
}
 
Example 10
/**
 * Verify that the ManagedExecutor implementation clears context
 * types that are not configured under propagated, or cleared.
 *
 * @throws TimeoutException indicates test failure
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 */
@Test
public void clearUnspecifiedContexts() throws InterruptedException, ExecutionException, TimeoutException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Buffer.CONTEXT_NAME)
            .build();
    
    int originalPriority = Thread.currentThread().getPriority();
    try {
        // Set non-default values
        int newPriority = originalPriority == 3 ? 2 : 3;
        Thread.currentThread().setPriority(newPriority);
        Buffer.set(new StringBuffer("clearUnspecifiedContexts-test-buffer-A"));

        Future<Void> future = executor.completedFuture(1).thenRun(() -> {
                Assert.assertEquals(Buffer.get().toString(), "clearUnspecifiedContexts-test-buffer-A",
                        "Context type was not propagated to contextual action.");

                Buffer.set(new StringBuffer("clearUnspecifiedContexts-test-buffer-B"));

                Assert.assertEquals(Thread.currentThread().getPriority(), Thread.NORM_PRIORITY,
                        "Context type that remained unspecified was not cleared by default.");
        });

        Assert.assertNull(future.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Non-null value returned by stage that runs Runnable.");
        
        Assert.assertEquals(Buffer.get().toString(), "clearUnspecifiedContexts-test-buffer-A",
                "Previous context (Buffer) was not restored after context was propagated for contextual action.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Thread.currentThread().setPriority(originalPriority);
    }
}
 
Example 11
/**
 * Verify that thread context is cleared per the configuration of the ManagedExecutor builder
 * for all tasks that are executed via the execute method. This test supplies the ManagedExecutor
 * to a Java SE CompletableFuture, which invokes the execute method to run tasks asynchronously.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void executedTaskRunsWithClearedContext() throws ExecutionException, InterruptedException, TimeoutException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    try {
        Buffer.set(new StringBuffer("executed-task-test-buffer-A"));
        Label.set("executed-task-test-label-A");

        CompletableFuture<Integer> cf1 = new CompletableFuture<Integer>();

        CompletableFuture<Void> cf2 = cf1.thenAcceptAsync(i -> {
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Label.set("executed-task-test-label-B");
        }, executor);

        cf1.complete(1000);

        cf2.join();

        Assert.assertEquals(Buffer.get().toString(), "executed-task-test-buffer-A",
                "Context unexpectedly changed on thread.");
        Assert.assertEquals(Label.get(), "executed-task-test-label-A",
                "Context unexpectedly changed on thread.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 12
@Produces
@ApplicationScoped
@MPConfigBean.Max5Queue
protected ManagedExecutor createExecutor() {
    // rely on MP Config for defaults of maxAsync=1, cleared=Remaining
    return ManagedExecutor.builder()
            .maxQueued(5)
            .propagated()
            .build();
}
 
Example 13
private void checkCDIPropagation(boolean expectPropagate, String stateToPropagate, ManagedExecutor me, AbstractBean bean) throws Exception {
    bean.setState(stateToPropagate);
    CompletableFuture<String> cf = me.supplyAsync(() -> {
        String state = bean.getState();
        return state;
    });
    assertEquals(cf.get(TIMEOUT_MIN, TimeUnit.MINUTES), expectPropagate ? stateToPropagate : AbstractBean.UNINITIALIZED);
}
 
Example 14
private ManagedExecutor createExecutor(String testName) {
    try {
        return ManagedExecutor.builder()
                .maxAsync(2)
                .propagated(ThreadContext.TRANSACTION)
                .cleared(ThreadContext.ALL_REMAINING)
                .build();
    }
    catch (IllegalStateException x) {
        System.out.printf("Skipping test %s. Transaction context propagation is not supported.%n",
                testName);
        return null;
    }
}
 
Example 15
Source Project: quarkus   Source File: RestClientBase.java    License: Apache License 2.0 5 votes vote down vote up
public Object create() {
    RestClientBuilder builder = RestClientBuilder.newBuilder();
    configureBaseUrl(builder);
    configureTimeouts(builder);
    configureProviders(builder);
    configureSsl(builder);
    // If we have context propagation, then propagate context to the async client threads
    InstanceHandle<ManagedExecutor> managedExecutor = Arc.container().instance(ManagedExecutor.class);
    if (managedExecutor.isAvailable()) {
        builder.executorService(managedExecutor.get());
    }

    Object result = builder.build(proxyType);
    return result;
}
 
Example 16
@Typed(ManagedExecutor.class)
@Produces
@Singleton
@DefaultBean
public ManagedExecutor getAllManagedExecutor() {
    return managedExecutor;
}
 
Example 17
@Override
public ExecutorService createCoreExecutor(int size) {
    return ManagedExecutor.builder().maxAsync(size).build();
}
 
Example 18
@Override
public ExecutorService createExecutor(int coreSize, int size) {
    SmallRyeManagedExecutor.Builder builder = (SmallRyeManagedExecutor.Builder) ManagedExecutor.builder();
    return builder.maxAsync(size).build();
}
 
Example 19
@Test
public void builderForManagedExecutorIsProvided() {
    Assert.assertNotNull(ManagedExecutor.builder(),
            "MicroProfile Context Propagation implementation does not provide a ManagedExecutor builder.");
}
 
Example 20
/**
 * Verify that thread context is captured and propagated per the configuration of the
 * ManagedExecutor builder for all dependent stages of the completed future that is created
 * by the ManagedExecutor's completedStage implementation. Thread context is captured
 * at each point where a dependent stage is added, rather than solely upon creation of the
 * initial stage or construction of the builder.
 *
 * @throws InterruptedException indicates test failure
 */
@Test
public void completedStageDependentStagesRunWithContext() throws InterruptedException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    try {
        // Set non-default values
        Buffer.set(new StringBuffer("completedStage-test-buffer"));
        Label.set("completedStage-test-label-A");

        CompletionStage<String> stage1 = executor.completedStage("5A");

        // The following incomplete future prevents subsequent stages from completing
        CompletableFuture<Integer> stage2 = new CompletableFuture<Integer>();

        Label.set("completedStage-test-label-B");

        CompletionStage<Integer> stage3 = stage1.thenCompose(s -> {
            Assert.assertEquals(s, "5A",
                    "Value supplied to compose function was lost or altered.");

            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "completedStage-test-label-B",
                    "Context type was not propagated to contextual action.");

            return stage2.thenApply(i -> i + Integer.parseInt(s, 16));
        });

        Label.set("completedStage-test-label-C");

        CompletionStage<Integer> stage4 = stage3.applyToEither(new CompletableFuture<Integer>(), i -> {
            Assert.assertEquals(i, Integer.valueOf(99),
                    "Value supplied to function was lost or altered.");

            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "completedStage-test-label-C",
                    "Context type was not propagated to contextual action.");

            return i + 1;
        });

        Label.set("completedStage-test-label-D");

        CountDownLatch completed = new CountDownLatch(1);
        AtomicInteger resultRef = new AtomicInteger();
        stage4.whenComplete((result, failure) -> {
            resultRef.set(result);
            completed.countDown();
        });

        // allow stages 3 and 4 to complete
        stage2.complete(9);

        Assert.assertTrue(completed.await(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Completion stage did not finish in a reasonable amount of time.");

        Assert.assertEquals(resultRef.get(), 100,
                "Unexpected result for stage 4.");

        // Is context properly restored on current thread?
        Assert.assertEquals(Buffer.get().toString(), "completedStage-test-buffer",
                "Previous context was not restored after context was cleared for managed executor tasks.");
        Assert.assertEquals(Label.get(), "completedStage-test-label-D",
                "Previous context was not restored after context was propagated for managed executor tasks.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 21
/**
 * When an already-contextualized Callable is specified as the action/task,
 * the action/task runs with its already-captured context rather than
 * capturing and applying context per the configuration of the managed executor.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void contextOfContextualCallableOverridesContextOfManagedExecutor() throws ExecutionException, InterruptedException, TimeoutException {
    ThreadContext bufferContext = ThreadContext.builder()
            .propagated(Buffer.CONTEXT_NAME)
            .unchanged()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();
    try {
        Callable<String> getBuffer = () -> {
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");
            return Buffer.get().toString();
        };

        Callable<String> getLabel = () -> {
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return Label.get();
        };

        Buffer.set(new StringBuffer("contextualCallableOverride-buffer-1"));
        Label.set("contextualCallableOverride-label-1");

        Callable<String> precontextualizedTask1 = bufferContext.contextualCallable(getBuffer);

        Buffer.set(new StringBuffer("contextualCallableOverride-buffer-2"));
        Label.set("contextualCallableOverride-label-2");

        Callable<String> precontextualizedTask2 = bufferContext.contextualCallable(getBuffer);

        Buffer.set(new StringBuffer("contextualCallableOverride-buffer-3"));
        Label.set("contextualCallableOverride-label-3");

        Future<String> future = executor.submit(precontextualizedTask1);
        Assert.assertEquals(future.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS), "contextualCallableOverride-buffer-1",
                "Previously captured context type not found on thread.");

        List<Future<String>> futures = executor.invokeAll(
                Arrays.asList(precontextualizedTask2, getLabel, precontextualizedTask1, precontextualizedTask2),
                MAX_WAIT_NS,
                TimeUnit.NANOSECONDS);

        future = futures.get(0);
        Assert.assertEquals(future.get(), "contextualCallableOverride-buffer-2",
                "Previously captured context type not found on thread.");

        future = futures.get(1);
        Assert.assertEquals(future.get(), "contextualCallableOverride-label-3",
                "Context type captured by managed executor not found on thread.");

        future = futures.get(2);
        Assert.assertEquals(future.get(), "contextualCallableOverride-buffer-1",
                "Previously captured context type not found on thread.");

        future = futures.get(3);
        Assert.assertEquals(future.get(), "contextualCallableOverride-buffer-2",
                "Previously captured context type not found on thread.");

        String result = executor.invokeAny(
                Arrays.asList(precontextualizedTask1, precontextualizedTask1),
                MAX_WAIT_NS,
                TimeUnit.NANOSECONDS);
        Assert.assertEquals(result, "contextualCallableOverride-buffer-1",
                "Previously captured context type not found on thread.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 22
/**
 * When an already-contextualized Consumer or BiFunction is specified as the action/task,
 * the action/task runs with its already-captured context rather than
 * capturing and applying context per the configuration of the managed executor.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void contextOfContextualConsumerAndBiFunctionOverrideContextOfManagedExecutor()
        throws ExecutionException, InterruptedException, TimeoutException {
    ThreadContext labelContext = ThreadContext.builder()
            .propagated(Label.CONTEXT_NAME)
            .unchanged()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Buffer.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();
    try {
        Buffer.set(new StringBuffer("contextualBiFunctionOverride-buffer-1"));
        Label.set("contextualBiFunctionOverride-label-1");

        BiFunction<Integer, Throwable, Integer> precontextualizedFunction1 = labelContext.contextualFunction((result, failure) -> {
            Assert.assertEquals(Label.get(), "contextualBiFunctionOverride-label-1",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return failure == null ? result : 100;
        });

        Buffer.set(new StringBuffer("contextualBiFunctionOverride-buffer-2"));
        Label.set("contextualBiFunctionOverride-label-2");

        BiFunction<Integer, Integer, Integer> precontextualizedFunction2 = labelContext.contextualFunction((i, j) -> {
            Assert.assertEquals(Label.get(), "contextualBiFunctionOverride-label-2",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return i - j;
        });

        Buffer.set(new StringBuffer("contextualConsumerOverride-buffer-3"));
        Label.set("contextualConsumerOverride-label-3");

        Consumer<Integer> precontextualizedConsumer3 = labelContext.contextualConsumer(i -> {
            Assert.assertEquals(Label.get(), "contextualConsumerOverride-label-3",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
        });

        Buffer.set(new StringBuffer("contextualConsuemrOverride-buffer-4"));
        Label.set("contextualConsumerOverride-label-4");

        Consumer<Integer> precontextualizedConsumer4 = labelContext.contextualConsumer(i -> {
            Assert.assertEquals(Label.get(), "contextualConsumerOverride-label-4",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
        });

        BiFunction<Void, Void, String> normalFunction5 = (unused1, unused2) -> {
            Assert.assertEquals(Buffer.get().toString(), "contextualConsumerAndBiFunctionOverride-buffer-5",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");
            return "done";
        };

        Buffer.set(new StringBuffer("contextualConsumerAndBiFunctionOverride-buffer-5"));
        Label.set("contextualConsumerAndBiFunctionOverride-label-5");

        CompletableFuture<Integer> stage0 = executor.failedFuture(new ArrayIndexOutOfBoundsException("Expected error."));
        CompletableFuture<Integer> stage1 = stage0.handleAsync(precontextualizedFunction1);
        CompletableFuture<Integer> stage2 = executor.completedFuture(200).thenCombineAsync(stage1, precontextualizedFunction2);
        CompletableFuture<Void> stage3 = stage2.thenAccept(precontextualizedConsumer3);
        CompletableFuture<Void> stage4 = stage2.acceptEitherAsync(stage1, precontextualizedConsumer4);
        CompletableFuture<String> stage5 = stage4.thenCombine(stage3, normalFunction5);

        Assert.assertEquals(stage5.join(), "done",
                "Unexpected result for completion stage.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 23
/**
 * When an already-contextualized Function is specified as the action/task,
 * the action/task runs with its already-captured context rather than
 * capturing and applying context per the configuration of the managed executor.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void contextOfContextualFunctionOverridesContextOfManagedExecutor() throws ExecutionException, InterruptedException, TimeoutException {
    ThreadContext labelContext = ThreadContext.builder()
            .propagated(Label.CONTEXT_NAME)
            .unchanged()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Buffer.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();
    try {
        Buffer.set(new StringBuffer("contextualFunctionOverride-buffer-1"));
        Label.set("contextualFunctionOverride-label-1");

        Function<Integer, Integer> precontextualizedFunction1 = labelContext.contextualFunction(i -> {
            Assert.assertEquals(Label.get(), "contextualFunctionOverride-label-1",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return i + 1;
        });

        Buffer.set(new StringBuffer("contextualFunctionOverride-buffer-2"));
        Label.set("contextualFunctionOverride-label-2");

        Function<Integer, Integer> precontextualizedFunction2 = labelContext.contextualFunction(i -> {
            Assert.assertEquals(Label.get(), "contextualFunctionOverride-label-2",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return i + 20;
        });

        Function<Throwable, Integer> precontextualizedErrorHandler = labelContext.contextualFunction(failure -> {
            Assert.assertEquals(Label.get(), "contextualFunctionOverride-label-2",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return -1;
        });

        Buffer.set(new StringBuffer("contextualFunctionOverride-buffer-3"));
        Label.set("contextualFunctionOverride-label-3");

        Function<Integer, Integer> normalFunction = i -> {
            Assert.assertEquals(Buffer.get().toString(), "contextualFunctionOverride-buffer-3",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");
            return i + 300;
        };

        CompletableFuture<Integer> stage0 = executor.newIncompleteFuture();
        CompletableFuture<Integer> stage1 = stage0.thenApplyAsync(precontextualizedFunction1);

        Buffer.set(new StringBuffer("contextualFunctionOverride-buffer-4"));
        Label.set("contextualFunctionOverride-label-4");

        Function<Integer, CompletableFuture<Integer>> precontextualizedFunction4 = labelContext.contextualFunction(i -> {
            Assert.assertEquals(Label.get(), "contextualFunctionOverride-label-4",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
            return stage1;
        });

        Buffer.set(new StringBuffer("contextualFunctionOverride-buffer-3"));
        Label.set("contextualFunctionOverride-label-3");

        CompletableFuture<Integer> stage2 = stage0.thenComposeAsync(precontextualizedFunction4);
        CompletableFuture<Integer> stage3 = stage2.applyToEither(stage1, precontextualizedFunction2);
        CompletableFuture<Integer> stage4 = stage3.thenApply(normalFunction);
        CompletableFuture<Integer> stage5 = stage4.thenApply(i -> i / (i - 321)) // intentional ArithmeticException for division by 0
                .exceptionally(precontextualizedErrorHandler);

        stage0.complete(0);

        Assert.assertEquals(stage2.join(), Integer.valueOf(1),
                "Unexpected result for completion stage.");

        Assert.assertEquals(stage5.join(), Integer.valueOf(-1),
                "Unexpected result for completion stage.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 24
/**
 * When an already-contextualized Runnable is specified as the action/task,
 * the action/task runs with its already-captured context rather than
 * capturing and applying context per the configuration of the managed executor.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void contextOfContextualRunnableOverridesContextOfManagedExecutor() throws ExecutionException, InterruptedException, TimeoutException {
    ThreadContext labelContext = ThreadContext.builder()
            .propagated(Label.CONTEXT_NAME)
            .unchanged()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Buffer.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();
    try {
        Buffer.set(new StringBuffer("contextualRunnableOverride-buffer-1"));
        Label.set("contextualRunnableOverride-label-1");

        Runnable precontextualizedTask1 = labelContext.contextualRunnable(() -> {
            Assert.assertEquals(Label.get(), "contextualRunnableOverride-label-1",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
        });

        Buffer.set(new StringBuffer("contextualRunnableOverride-buffer-2"));
        Label.set("contextualRunnableOverride-label-2");

        Runnable precontextualizedTask2 = labelContext.contextualRunnable(() -> {
            Assert.assertEquals(Label.get(), "contextualRunnableOverride-label-2",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
        });

        Buffer.set(new StringBuffer("contextualRunnableOverride-buffer-3"));
        Label.set("contextualRunnableOverride-label-3");

        Runnable normalTask = () -> {
            Assert.assertEquals(Buffer.get().toString(), "contextualRunnableOverride-buffer-3",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");
        };

        Future<Integer> future = executor.submit(precontextualizedTask1, 1);
        Assert.assertEquals(future.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS), Integer.valueOf(1),
                "Unexpected result of task.");

        CompletableFuture<Void> stage0 = executor.runAsync(precontextualizedTask1);
        CompletableFuture<Void> stage1 = stage0.thenRunAsync(precontextualizedTask1);
        CompletableFuture<Void> stage2 = stage0.thenRun(precontextualizedTask2);
        CompletableFuture<Void> stage3 = stage1.runAfterEither(stage2, precontextualizedTask2);
        CompletableFuture<Void> stage4 = stage1.runAfterBothAsync(stage2, precontextualizedTask1);
        CompletableFuture<Void> stage5 = stage4.runAfterBoth(stage3, normalTask);
        stage5.join();

        LinkedBlockingQueue<String> results = new LinkedBlockingQueue<String>();
        Runnable precontextualizedTask3 = labelContext.contextualRunnable(() -> results.add(Label.get()));

        Buffer.set(new StringBuffer("contextualRunnableOverride-buffer-4"));
        Label.set("contextualRunnableOverride-label-4");

        executor.execute(precontextualizedTask3);
        Assert.assertEquals(results.poll(MAX_WAIT_NS, TimeUnit.NANOSECONDS), "contextualRunnableOverride-label-3",
                "Previously captured context type not found on thread.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 25
/**
 * When an already-contextualized Supplier or BiFunction is specified as the action/task,
 * the action/task runs with its already-captured context rather than
 * capturing and applying context per the configuration of the managed executor.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void contextOfContextualSuppplierAndBiConsumerOverrideContextOfManagedExecutor()
        throws ExecutionException, InterruptedException, TimeoutException {
    ThreadContext bufferContext = ThreadContext.builder()
            .propagated(Buffer.CONTEXT_NAME)
            .unchanged()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();
    try {
        Supplier<String> getBuffer = () -> {
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");
            return Buffer.get().toString();
        };

        Buffer.set(new StringBuffer("contextualSupplierOverride-buffer-1"));
        Label.set("contextualSupplierOverride-label-1");

        Supplier<String> precontextualizedSupplier1 = bufferContext.contextualSupplier(getBuffer);

        Buffer.set(new StringBuffer("contextualSupplierOverride-buffer-2"));
        Label.set("contextualSupplierOverride-label-2");

        Supplier<String> precontextualizedSupplier2 = bufferContext.contextualSupplier(getBuffer);

        Buffer.set(new StringBuffer("contextualBiConsumerOverride-buffer-3"));
        Label.set("contextualBiConsumerOverride-label-3");

        BiConsumer<String, String> precontextualizedConsumer3 = bufferContext.contextualConsumer((b1, b2) -> {
            Assert.assertEquals(Buffer.get().toString(), "contextualBiConsumerOverride-buffer-3",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");

            Assert.assertEquals(b1, "contextualSupplierOverride-buffer-1",
                    "Previously captured context type not found on Supplier's thread.");

            Assert.assertEquals(b2, "contextualSupplierOverride-buffer-2",
                    "Previously captured context type not found on Supplier's thread.");
        });

        Buffer.set(new StringBuffer("contextualBiConsumerOverride-buffer-4"));
        Label.set("contextualBiConsumerOverride-label-4");

        BiConsumer<Void, Throwable> precontextualizedConsumer4 = bufferContext.contextualConsumer((unused, failure) -> {
            Assert.assertEquals(Buffer.get().toString(), "contextualBiConsumerOverride-buffer-4",
                    "Previously captured context type not found on thread.");
            Assert.assertEquals(Label.get(), "",
                    "Context type not cleared from thread.");
        });

        Buffer.set(new StringBuffer("contextualSupplierAndBiConsumerOverride-buffer-5"));
        Label.set("contextualSupplierAndBiConsumerOverride-label-5");

        CompletableFuture<String> stage1 = executor.supplyAsync(precontextualizedSupplier1);
        CompletableFuture<String> stage2 = executor.supplyAsync(precontextualizedSupplier2);
        CompletableFuture<Void> stage3 = stage1.thenAcceptBoth(stage2, precontextualizedConsumer3);
        CompletableFuture<Void> stage4 = stage3.whenCompleteAsync(precontextualizedConsumer4);
        CompletableFuture<Void> stage5 = stage4.whenComplete((unused, failure) -> {
            Assert.assertEquals(Label.get(), "contextualSupplierAndBiConsumerOverride-label-5",
                    "Context type captured by managed executor not found on thread.");
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type not cleared from thread.");
        });

        stage5.join();
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 26
/**
 * Verify that thread context is propagated per the configuration of the ManagedExecutor builder
 * for all tasks that are executed via the execute method.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void executedTaskRunsWithContext() throws ExecutionException, InterruptedException, TimeoutException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Buffer.CONTEXT_NAME, Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    try {
        Buffer.set(new StringBuffer("executed-task-test-buffer-C"));
        Label.set("executed-task-test-label-C");

        CompletableFuture<String> result = new CompletableFuture<String>();
        executor.execute(() -> {
            try {
                Assert.assertEquals(Buffer.get().toString(), "executed-task-test-buffer-C",
                        "Context type that is configured to be propagated was not propagated.");

                Assert.assertEquals(Label.get(), "executed-task-test-label-C",
                        "Context type that is configured to be propagated was not propagated.");

                Label.set("executed-task-test-label-D");

                result.complete("successful");
            }
            catch (Throwable x) {
                result.completeExceptionally(x);
            }
        });

        // Force exception to be raised, if any
        result.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS);

        Assert.assertEquals(Buffer.get().toString(), "executed-task-test-buffer-C",
                "Context unexpectedly changed on thread.");
        Assert.assertEquals(Label.get(), "executed-task-test-label-C",
                "Context unexpectedly changed on thread.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 27
/**
 * Verify that the ManagedExecutor implementation starts 2 async tasks/actions, and no more,
 * when maxAsync is configured to 2.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void maxAsync2() throws ExecutionException, InterruptedException, TimeoutException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .maxAsync(2)
            .propagated()
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    Phaser barrier = new Phaser(2);
    try {
        // Use up both maxAsync slots on blocking operations and wait for them to start
        Future<Integer> future1 = executor.submit(() -> barrier.awaitAdvance(barrier.arriveAndAwaitAdvance()));
        CompletableFuture<Integer> future2 = executor.supplyAsync(() -> barrier.awaitAdvance(barrier.arriveAndAwaitAdvance()));
        barrier.awaitAdvanceInterruptibly(0, MAX_WAIT_NS, TimeUnit.NANOSECONDS);

        // This data structure holds the results of tasks which shouldn't be able to run yet
        LinkedBlockingQueue<String> results = new LinkedBlockingQueue<String>();

        // Submit additional tasks/actions for async execution.
        // These should queue, but otherwise be unable to start yet due to maxAsync=2.
        CompletableFuture<Void> future3 = executor.runAsync(() -> results.offer("Result3"));
        CompletableFuture<Boolean> future4 = executor.supplyAsync(() -> results.offer("Result4"));
        Future<Boolean> future5 = executor.submit(() -> results.offer("Result5"));
        CompletableFuture<Boolean> future6 = executor.completedFuture("6")
                .thenApplyAsync(s -> results.offer("Result" + s));

        // Detect whether any of the above tasks/actions run within the next 5 seconds
        Assert.assertNull(results.poll(5, TimeUnit.SECONDS),
                "Should not be able start more than 2 async tasks when maxAsync is 2.");

        // unblock and allow tasks to finish
        barrier.arrive();
        barrier.arrive(); // there are 2 parties in each phase

        Assert.assertNotNull(results.poll(MAX_WAIT_NS, TimeUnit.SECONDS), "None of the queued tasks ran.");
        Assert.assertNotNull(results.poll(MAX_WAIT_NS, TimeUnit.SECONDS), "Only 1 of the queued tasks ran.");
        Assert.assertNotNull(results.poll(MAX_WAIT_NS, TimeUnit.SECONDS), "Only 2 of the queued tasks ran.");
        Assert.assertNotNull(results.poll(MAX_WAIT_NS, TimeUnit.SECONDS), "Only 3 of the queued tasks ran.");

        Assert.assertEquals(future1.get(), Integer.valueOf(2), "Unexpected result of first task.");
        Assert.assertEquals(future2.get(), Integer.valueOf(2), "Unexpected result of second task.");
        Assert.assertNull(future3.join(), "Unexpected result of third task.");
        Assert.assertEquals(future4.join(), Boolean.TRUE, "Unexpected result of fourth task.");
        Assert.assertEquals(future5.get(), Boolean.TRUE, "Unexpected result of fifth task.");
        Assert.assertEquals(future6.get(), Boolean.TRUE, "Unexpected result of sixth task.");
    }
    finally {
        barrier.forceTermination();
        executor.shutdownNow();
    }
}
 
Example 28
/**
 * Verify that thread context is captured and propagated per the configuration of the
 * ManagedExecutor builder for all dependent stages of the incomplete future that is created
 * by the ManagedExecutor's newIncompleteFuture implementation. Thread context is captured
 * at each point where a dependent stage is added, rather than solely upon creation of the
 * initial stage or construction of the builder.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 */
@Test
public void newIncompleteFutureDependentStagesRunWithContext() throws ExecutionException, InterruptedException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    try {
        CompletableFuture<Integer> stage1 = executor.newIncompleteFuture();

        Assert.assertFalse(stage1.isDone(),
                "Completable future created by newIncompleteFuture did not start out as incomplete.");

        // Set non-default values
        Buffer.get().append("newIncompleteFuture-test-buffer");
        Label.set("newIncompleteFuture-test-label-A");

        CompletableFuture<Integer> stage2 = stage1.thenApply(i -> {
            Assert.assertEquals(i, Integer.valueOf(10),
                    "Value supplied to second stage was lost or altered.");

            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "newIncompleteFuture-test-label-A",
                    "Context type was not correctly propagated to contextual action.");
            
            return i * 2;
        });

        Label.set("newIncompleteFuture-test-label-B");

        CompletableFuture<Integer> stage3 = stage2.thenApply(i -> {
            Assert.assertEquals(i, Integer.valueOf(20),
                    "Value supplied to third stage was lost or altered.");

            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "newIncompleteFuture-test-label-B",
                    "Context type was not correctly propagated to contextual action.");
            
            return i + 10;
        });

        Label.set("newIncompleteFuture-test-label-C");

        // To avoid the possibility that CompletableFuture.get might cause the action to run
        // on the current thread, which would bypass the intent of testing context propagation,
        // use a countdown latch to independently wait for completion.
        CountDownLatch completed = new CountDownLatch(1);
        stage3.whenComplete((result, failure) -> completed.countDown());

        Assert.assertTrue(stage1.complete(10),
                "Unable to complete the future that was created by newIncompleteFuture.");

        Assert.assertTrue(completed.await(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Completable future did not finish in a reasonable amount of time.");

        Assert.assertTrue(stage1.isDone(), "First stage did not transition to done upon completion.");
        Assert.assertTrue(stage2.isDone(), "Second stage did not transition to done upon completion.");
        Assert.assertTrue(stage3.isDone(), "Third stage did not transition to done upon completion.");

        Assert.assertEquals(stage1.get(), Integer.valueOf(10),
                "Result of first stage does not match the value with which it was completed.");

        Assert.assertEquals(stage2.getNow(22), Integer.valueOf(20),
                "Result of second stage was lost or altered.");

        Assert.assertEquals(stage3.join(), Integer.valueOf(30),
                "Result of third stage was lost or altered.");

        Assert.assertFalse(stage1.isCompletedExceptionally(), "First stage should not report exceptional completion.");
        Assert.assertFalse(stage2.isCompletedExceptionally(), "Second stage should not report exceptional completion.");
        Assert.assertFalse(stage3.isCompletedExceptionally(), "Third stage should not report exceptional completion.");

        // Is context properly restored on current thread?
        Assert.assertEquals(Buffer.get().toString(), "newIncompleteFuture-test-buffer",
                "Previous context was not restored after context was cleared for managed executor tasks.");
        Assert.assertEquals(Label.get(), "newIncompleteFuture-test-label-C",
                "Previous context was not restored after context was propagated for managed executor tasks.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 29
/**
 * Verify that the ManagedExecutor.Builder can be used to create multiple ManagedExecutors with 
 * different configured contexts.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void reuseManagedExecutorBuilder() throws ExecutionException, InterruptedException, TimeoutException {
    ManagedExecutor.Builder builder = ManagedExecutor.builder()
            .propagated()
            .cleared(Buffer.CONTEXT_NAME);
    
    ManagedExecutor clearingExecutor = builder.build();

    ManagedExecutor propagatingExecutor = builder.propagated(Buffer.CONTEXT_NAME)
            .cleared()
            .build();

    try {
        // Set non-default value
        Buffer.set(new StringBuffer("reuseBuilder-test-buffer-A"));

        Future<Void> clearedFuture = clearingExecutor.completedFuture(1).thenRun(() -> {
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Buffer.set(new StringBuffer("reuseBuilder-test-buffer-B"));
        });

        Future<Void> propagatedFuture = propagatingExecutor.completedFuture(1).thenRunAsync(() -> {
            Assert.assertEquals(Buffer.get().toString(), "reuseBuilder-test-buffer-A",
                    "Context type was not propagated to contextual action.");

            Buffer.set(new StringBuffer("reuseBuilder-test-buffer-C"));
        });

        Assert.assertNull(propagatedFuture.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Non-null value returned by stage that runs Runnable.");

        Assert.assertNull(clearedFuture.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Non-null value returned by stage that runs Runnable.");

        Assert.assertEquals(Buffer.get().toString(), "reuseBuilder-test-buffer-A",
                "Previous context (Buffer) was not restored after context was propagated for contextual action.");
    }
    finally {
        clearingExecutor.shutdownNow();
        propagatingExecutor.shutdownNow();
        // Restore original value
        Buffer.set(null);
    }
}
 
Example 30
/**
 * Verify that thread context is captured and propagated per the configuration of the
 * ManagedExecutor builder for all tasks that are submitted via the submit(Callable),
 * submit(Runnable) and submit(Runnable, result) methods.
 *
 * @throws ExecutionException indicates test failure
 * @throws InterruptedException indicates test failure
 * @throws TimeoutException indicates test failure
 */
@Test
public void submittedTasksRunWithContext() throws ExecutionException, InterruptedException, TimeoutException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    try {
        Buffer.set(new StringBuffer("submitted-tasks-test-buffer-A"));
        Label.set("submitted-tasks-test-label-A");

        Future<?> futureA = executor.submit(() -> {
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "submitted-tasks-test-label-A",
                    "Context type was not correctly propagated to contextual action.");

            throw new Error("Fake error intentionally raised by test Runnable.");
        });

        Label.set("submitted-tasks-test-label-B");

        Future<String> futureB = executor.submit(() -> {
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "submitted-tasks-test-label-B",
                    "Context type was not correctly propagated to contextual action.");
        }, "Task-B-Result");

        Label.set("submitted-tasks-test-label-C");

        Future<String> futureC = executor.submit(() -> {
            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "submitted-tasks-test-label-C",
                    "Context type was not correctly propagated to contextual action.");

            return "Task-C-Result";
        });

        try {
            Object result = futureA.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS);
            Assert.fail("Result of " + result + " returned for Runnable that throws an Error.");
        }
        catch (ExecutionException x) {
            if (x.getCause() == null
                    || (!(x.getCause() instanceof Error))
                    || (!"Fake error intentionally raised by test Runnable.".equals(x.getCause().getMessage()))) {
                throw x;
            }
        }

        Assert.assertEquals("Task-B-Result", futureB.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Result does not match the predetermined result that was specified when submitting the Runnable.");

        Assert.assertEquals("Task-C-Result", futureC.get(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Result does not match the result returned by the Callable.");

        Assert.assertTrue(futureA.isDone(),
                "Future for first Runnable should report being done after test case awaits its completion.");

        Assert.assertTrue(futureB.isDone(),
                "Future for second Runnable should report being done after test case awaits its completion.");

        Assert.assertTrue(futureC.isDone(),
                "Future for Callable should report being done after test case awaits its completion.");

        Assert.assertFalse(futureA.isCancelled(),
                "Future for first Runnable should not be canceled because the test case did not cancel it.");

        Assert.assertFalse(futureB.isCancelled(),
                "Future for second Runnable should not be canceled because the test case did not cancel it.");

        Assert.assertFalse(futureC.isCancelled(),
                "Future for Callable should not be canceled because the test case did not cancel it.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}