code: @Trivial // traced by caller
      public static <U> CompletableFuture<U> supplyAsync(Supplier<U> action, Executor executor) {
          // Reject ManagedTask so that we have the flexibility to decide later how to handle ManagedTaskListener and execution properties
          if (action instanceof ManagedTask)
              throw new IllegalArgumentException(ManagedTask.class.getName());
  
          FutureRefExecutor futureExecutor = supportsAsync(executor);
  
          ThreadContextDescriptor contextDescriptor;
          if (action instanceof ContextualSupplier) {
              ContextualSupplier<U> s = (ContextualSupplier<U>) action;
              contextDescriptor = s.getContextDescriptor();
              action = s.getAction();
          } else if (executor instanceof WSManagedExecutorService) {
              WSContextService contextSvc = ((WSManagedExecutorService) executor).getContextService();
              contextDescriptor = contextSvc.captureThreadContext(XPROPS_SUSPEND_TRAN);
          } else {
              contextDescriptor = null;
          }
  
          if (JAVA8) {
              if (contextDescriptor != null)
                  action = new ContextualSupplier<U>(contextDescriptor, action);
              CompletableFuture<U> completableFuture = CompletableFuture.supplyAsync(action, futureExecutor == null ? executor : futureExecutor);
              return new ManagedCompletableFuture<U>(completableFuture, executor, futureExecutor);
          } else {
              ManagedCompletableFuture<U> completableFuture = new ManagedCompletableFuture<U>(executor, futureExecutor);
              Runnable task = new ContextualSupplierAction<U>(contextDescriptor, action, completableFuture, true);
              (futureExecutor == null ? executor : futureExecutor).execute(task);
              return completableFuture;
          }
      }
docs: Alternative to CompletableFuture.supplyAsync(supplier, executor) with an implementation that switches the
  default asynchronous execution facility to be the specified managed executor.
  
  @param action the supplier to invoke asynchronously.
  @param executor the executor, typically a managed executor, that becomes the default asynchronous execution facility for the completable future.
  @return completable future where the specified managed executor is the default asynchronous execution facility.