commercetools / commercetools-sdk-java-v2

The e-commerce SDK from commercetools for Java.
https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/index.html
Apache License 2.0
35 stars 15 forks source link

Add way to specify executorservice to be used when returning commercetools SDK result #332

Open ChristianMattarVT opened 2 years ago

ChristianMattarVT commented 2 years ago

Is your feature request related to a problem? Please describe. Modern async Java applications need control on which Threadpool which tasks are running. Currently, by default, all responses returning from commercetools SDK will continue running in a thread managed by a threadpool from the SDK.

Describe the solution you'd like Add a way (potentially via Middleware?) to automatically return from any call to commercetools SDK running on a thread from a configurable threadpool AKA Executor

Describe alternatives you've considered Alternatively, we could manually do:

ctApi.<omitted>.execute().thenApplyAsync(e -> e, myExecutorService); on each call to commercetools. However, this would clutter the code and can be easily forgotten. Same for any explicit decorator that would be needed.

jenschude commented 2 years ago

It's already possible to define the executor for the underlying HTTP client. E.g. for OkHttp:

ApiRootBuilder.of(new CtOkHttp4Client(new ForkJoinPool(), 64, 64))
   .defaultClient()

As some middlewares use also executors e.g. RetryMiddleware or QueueMiddleware you will have to configure there the executor too (available in the builder since 8.10.0).

ApiRootBuilder.of().withRetryMiddleware(new ForkJoinPool(), 3)

For the OAuthMiddleware it's a bit more complicated as the token provider has to be instantiated before

ExecutorService executorService = new ForkJoinPool();

ClientCredentials credentials = ClientCredentials.of()
        .withClientId(CommercetoolsTestUtils.getClientId())
        .withClientSecret(CommercetoolsTestUtils.getClientSecret())
        .build();

TokenSupplier supplier = new InMemoryTokenSupplier(
        executorService,
        new ClientCredentialsTokenSupplier(
                executorService,
                credentials.getClientId(),
                credentials.getClientSecret(),
                credentials.getScopes(),
                tokenEndpoint,
                HttpClientSupplier.of().get()
        )
);

ApiRootBuilder.of().defaultClient(apiEndpoint).withOAuthMiddleware(
        OAuthMiddleware.of(
                executorService,
                new OAuthHandler(supplier)
        )
);

We will still investigate how to simplify this or use a centrally defined executor.

jenschude commented 2 years ago

Besides this you could always add a middleware specifying the executor:

ApiRootBuilder.of().addMiddleware((request, next) -> next.apply(request).thenApplyAsync(Function.identity(), executorService));
jenschude commented 1 year ago

FYI: In the more recent versions the Client & ApiRootBuilders have methods which allow to specify the ExecutorService to be used for each of the middlewares and handlers.

Still checking if a central defined executor may be useful