Closed pintomau closed 2 years ago
We would need to know what exactly you would like to extend.
The client instance has not been exposed in the ApiRoots to avoid accidental closing of the client which is AutoClosable.
Besides there are btw different options what also could be done. For example the ApiMethod allows to add any headers (withHeader
, addHeader
) and query parameters (withQueryParameter
, addQueryParameter
)
And the ApiRootBuilder allows to just build an ApiClient instance which itself could be wrapped inside another ApiClient.
ApiHttpClient client = ApiRootBuilder.of().buildClient();
ProjectApiRoot apiRoot = ProjectApiRoot.fromClient(client);
ApiHttpClient wrappedClient = ApiRootBuilder.of(client).buildClient();
ProjectApiRoot wrappedApiRoot = ProjectApiRoot.fromClient(wrappedClient);
This is mainly a nitpick and perfectly "work-aroundable", feel free to close. The goal is to be able to create more portable and easier to reuse decorators across multiple projects. I think lazy evaluation of the decoration step is also a benefit we've lost.
Maybe, the better solution would be pulling up the methods only ApiMethod
has to interfaces? For example, all execute
and send*
methods to (Client)RequestCommand? There are other methods within ApiMethod without interface, but not as necessary.
Regarding what we want to extend, it's what's already available in the api, all kinds of params, including sorting, paging, querying...
This would allow us to achieve something like:
var request = new MyDecorator3(new MyDecorator2(new MyDecorator(commercetoolsClient.productProjections().get(), args1...), args2...), args3...)...
// or, of course a composite decorator
return request.execute(...) // actual decoration takes place somewhere during the execution
.thenApply(...);
// instead of
// initialize decorators
ByProjectKeyProductProjectionsGet request = commercetoolsClient.productProjections().get();
// actual decoration takes place here
request = decorator3.decorate(decorator2.decorate(decorator1.decorate(request)));
return request.execute...
ProjectApiRoot wrappedApiRoot = ProjectApiRoot.fromClient(wrappedClient);
does kind of solve it, but comes with a lot of baggage and is missing lazy evaluation.
Thanks.
I added with #284 the option to apply a function or even multiple ones to the ApiHttpRequest after it has been build and before it gets executed.
And I also added a method to apply a decorator function to the ApiMethod itself. See #285
Version 8.3.0 has been released. The ApiMethod class now has methods which allow their decoration. Either by applying a lambda function to the ApiMethod instance or by apply a function at the ApiHttpRequest before being executed
Example usage can be seen here https://github.com/commercetools/commercetools-sdk-java-v2/blob/ac9ae00e51dd1889fc72c0bdfd26c694651ad995/rmf/rmf-java-base/src/test/java/io/vrap/rmf/base/client/ApiMethodTest.java#L232-L279
Sometimes, it may be useful to decorate specific requests, instead of the more generic middleware strategy.
One could create adapter classes that trigger the add and with methods, but we lose lazy evaluation (ie, trigger only when needed, on execution).
Is there already some straightforward way to achieve this that I'm missing?
The issue:
ApiMethod
depends onApiHttpClient
that is not easily accessible from theProjectApiRoot
or otherApiMethod
s we intend to decorate.Some suggestions to achieve this:
ApiHttpClient
accessible onApiMethod
orProjectApiRoot
.ApiMethod
(ie, something likeaddDecorator(UnaryOperator<T>)
, althoughT extends ApiMethod
may be too broad as it also contains execute* methods).