In that case, instead of changing every single jclouds api method, I'd
follow a different approach: add an interceptor in the jclouds HTTP
layer to have direct access to every request/response that is being
sent.

jclouds has the concept of drivers to allow users to configure some
parts of jclouds to fit in their environment: logging drivers to pick
the preferred logging framework, security drivers, and http drivers to
configure how http requests are made (currently we support the java
HttpUrlConnection, Apache HTTP client and OkHttp). The HTTP drivers
are the ones that perform the actual requests, and are invoked by the
jclouds HttpCommandExecutionService. That one is the responsible of
performing the requests and invoking the retry and error handling
logic when they fail.

This said, you have two good options:

* Configure the concrete driver to call your logic to persist every
response. This implies invoking the logic for *every*
request/response, including the retried/failed ones.
* Extend the default jclouds http command execution service and call
your logic when the request has been completed, that is, after the
retries (if any) and the error handling.

It depends on the level of detail you want to persist.


IMPLEMENTING OPTION 1

I'd recommend you configure the project to use the OkHttp driver [1]
(you'll have to add the jclouds-okhttp dependency), as it provides a
convenient interceptor mechanism [2]. Configuring it in jclouds just
requires you to provide an OkHttpClientSupplier [3] that is configured
with an interceptor that persists the request/response. You can do
that  as follows:

// Create the supplier that will configure your interceptor
OkHttpClientSupplier supplier = new OkHttpClientSupplier() {
   @Override public OkHttpClient get() {
      return new OkHttpClient.Builder()
         .addInterceptor(new YourInterceptor())
         .build();
   }
};

// Bind your supplier to the Guice context so that is the instance
injected in the OkHttp driver
Module customClientModule = new AbstractModule() {
   @Override protected void configure() {
      bind(OkHttpClientSupplier.class).toInstance(supplier);
   }
};

// Create the jclouds context with the required modules
ContextBuilder.newBuilder("provider")
     ...
    .modules(ImmutableSet.of(customClientModule, new
OkHttpCommandExecutorServiceModule()))
    ...
    .build();


IMPLEMENTING OPTION 2

If you don't want your logic to be invoked for retried and/or failed
requests, you can implement a decorator of the http command execution
service [4], so you can persist the response. It could be something
like:

public class DelegatingHttpCommandExecutorService implements
HttpCommandExecutorService {
   // You have to use the concrete implementation here to avoid
injection issues (we'll bind this "delegating" implementatin
   // as the one to be injected in the Guice context, so we have to
resolve the concrete delegate here to avoid a cyclic dep).
   // (Change to OkHttpCommandExecutorService or whatever driver
implementation you are using)
   private final JavaUrlHttpCommandExecutorService delegate;

   @Inject 
DelegatingHttpCommandExecutorService(JavaUrlHttpCommandExecutorService
delegate) {
      this.delegate = delegate;
   }

   @Override public HttpResponse invoke(HttpCommand command) {
      try {
           HttpResponse response = delegate.invoke(command);
           // do stuff :-)
           return response;
      } catch (Exception ex) {
         // Failed responses (4xx, 5xx) are propagated as Exceptions.
      }
   }
}

// Configure your command execution service as the default one
@ConfiguresHttpCommandExecutorService   // This annotation is
important. Don't miss it!
public class CustomHttpModule extends AbstractModule {
   @Override protected void configure() {
      install(new SSLModule());
      
bind(HttpCommandExecutorService.class).to(DelegatingHttpCommandExecutorService.class).in(Scopes.SINGLETON);
   }
}

// Create the jclouds context with the required modules
ContextBuilder.newBuilder("provider")
     ...
    .modules(ImmutableSet.of(new CustomHttpModule()))
    ...
    .build();



This should allow you to to some more clever handling of the HTTP
request/responses without having to patch the jclouds code. Take it as
a pseudocode. I've mostly typed/pasted the code directly here so there
can be typos :)


HTH!

I.



[1] https://github.com/jclouds/jclouds/tree/master/drivers/okhttp
[2] https://github.com/square/okhttp/wiki/Interceptors
[3] 
https://github.com/jclouds/jclouds/blob/master/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpClientSupplier.java
[4] 
https://github.com/jclouds/jclouds/blob/master/core/src/main/java/org/jclouds/http/HttpCommandExecutorService.java

On 6 January 2016 at 16:57, Antonio Galletta <anto...@hotmail.it> wrote:
> Hi, I'm sorry for my delay in reply.Yes we want to save all returned json.
>
>> Date: Mon, 4 Jan 2016 11:06:05 +0100
>> Subject: Re: R: How to modify jclouds ServerApi
>> From: n...@apache.org
>> To: dev@jclouds.apache.org
>> CC: andr...@apache.org
>>
>> Oh, I forgot to paste the link. Here it is:
>> https://cwiki.apache.org/confluence/display/JCLOUDS/Annotations
>>
>> Regarding the json persistence: do you need to persist just the one
>> returned by that call or do you need to persist *every* returned json
>> response?
>> El 4/1/2016 10:32, "Antonio Galletta" <anto...@hotmail.it> escribió:
>>
>> > Hi,
>> > Ok I sent a pull request just now. I'm very happy to contribute.
>> >
>> > Regarding the returned json, we need to put into mongoDb it. We try to
>> > create a federeted system between openstack and opennebula.
>> >
>> > Please could you send me the link to the WIP documentation?
>> >
>> > Thankyou a lot
>> > Bests,
>> > Antonio
>> > ________________________________
>> > Da: Ignasi Barrera<mailto:n...@apache.org>
>> > Inviato: ‎03/‎01/‎2016 08:31
>> > A: dev@jclouds.apache.org<mailto:dev@jclouds.apache.org>
>> > Cc: Andrew Phillips<mailto:andr...@apache.org>
>> > Oggetto: RE: How to modify jclouds ServerApi
>> >
>> > As Andrew says, implementations are dynamically generated at runtime so
>> > there is no default impl you can look at. There is a WIP documentation of
>> > the available annotations here [1] but is incomplete. Use it as a starting
>> > point to understand the jclouds declarative approach.
>> >
>> > If you are extending the api with methods that would be useful to others
>> > (the token ones) we would highly appreciate a pull request.
>> >
>> > Regarding the returned json, could you share which is the use case? You can
>> > easily change/add that by making the method return a String (jclouds would
>> > simply put the response body in it) or an HttpResponse (you'll get the
>> > entire raw http response).
>> >
>> > I.
>> > El 2/1/2016 17:57, "Antonio Galletta" <anto...@hotmail.it> escribió:
>> >
>> > > Hi,
>> > > thank you for your quick answer.
>> > > I interested just to patch my version adding new functionalities (for
>> > > example I would to add the method getToken to TokenApi)
>> > > and modifying the existing ones ( for example I woud to get the Json
>> > > retrived by the server).Cheers,
>> > > Antonio
>> > >
>> > >
>> > >
>> > > > Date: Sat, 2 Jan 2016 16:20:32 +0000
>> > > > From: andr...@apache.org
>> > > > To: dev@jclouds.apache.org
>> > > > CC: anto...@hotmail.it
>> > > > Subject: Re: How to modify jclouds ServerApi
>> > > >
>> > > > Hi Antonio
>> > > >
>> > > > Are you interested in submitted a pull request with a change to the
>> > > > ServerApi? Or would you just like to "patch" your version of jclouds in
>> > > > your own application?
>> > > >
>> > > > In jclouds, interfaces like ServerApi are not implemented explicitly
>> > > > anywhere - the implementation is generated on the basis of the
>> > > > annotations. What is the change you are looking to make?
>> > > >
>> > > > Regards
>> > > >
>> > > > ap
>> > > >
>> > > > On 2016-01-02 16:13, Antonio Galletta wrote:
>> > > > > Hi,I would like to modify some functionalities of ServerApi.Into the
>> > > > > package org.jclouds.openstack.nova.v2_0.features there is the
>> > > > > interface ServerApi, which class implements this interface?For
>> > > > > example, I should to modify the method get. How can I achieve this
>> > > > > target ?
>> > > > > Bests,Antonio
>> > >
>> >
>

Reply via email to