You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2013/12/11 13:24:48 UTC
git commit: JCLOUDS-400: Allow the HeaderParam annotation to be used
in a Caller.
Updated Branches:
refs/heads/master 83e77d230 -> c40dc996d
JCLOUDS-400: Allow the HeaderParam annotation to be used in a Caller.
This allows jclouds to factor out common headers into the Caller so they don't
have to be repeated in the Callee.
The Produces/Consumes annotations (Content-Type/Accept headers) will also
propagate from the Caller to the Callee.
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/c40dc996
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/c40dc996
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/c40dc996
Branch: refs/heads/master
Commit: c40dc996d96b05ce755f28728a4fb2bcd632b247
Parents: 83e77d2
Author: Everett Toews <ev...@rackspace.com>
Authored: Mon Dec 9 20:53:23 2013 -0600
Committer: Andrew Phillips <an...@apache.org>
Committed: Wed Dec 11 13:24:07 2013 +0100
----------------------------------------------------------------------
.../rest/internal/RestAnnotationProcessor.java | 12 +-
.../internal/RestAnnotationProcessorTest.java | 173 +++++++++++++++++++
2 files changed, 183 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/c40dc996/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
index d48d876..9624c8f 100644
--- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
+++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
@@ -234,9 +234,17 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
formParams.putAll(addFormParams(tokenValues, invocation));
} else {
formParams = addFormParams(tokenValues, invocation);
- }
+ }
+
Multimap<String, Object> queryParams = addQueryParams(tokenValues, invocation);
- Multimap<String, String> headers = buildHeaders(tokenValues, invocation);
+
+ Multimap<String, String> headers;
+ if (caller != null) {
+ headers = buildHeaders(tokenValues, caller);
+ headers.putAll(buildHeaders(tokenValues, invocation));
+ } else {
+ headers = buildHeaders(tokenValues, invocation);
+ }
if (r != null)
headers.putAll(r.getHeaders());
http://git-wip-us.apache.org/repos/asf/jclouds/blob/c40dc996/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
index 3506572..879bb3b 100644
--- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
+++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
@@ -181,6 +181,22 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@GET
@Path("/{path}")
ListenableFuture<Void> onePath(@PathParam("path") String path);
+
+ @POST
+ ListenableFuture<Void> testWithoutProducesAndConsumes();
+
+ @POST
+ @Produces(MediaType.APPLICATION_XML)
+ @Consumes(MediaType.APPLICATION_XML)
+ ListenableFuture<Void> testProducesAndConsumesOnMethod();
+ }
+
+ @Path("/client/{jclouds.api-version}")
+ @Produces(MediaType.APPLICATION_XML)
+ @Consumes(MediaType.APPLICATION_XML)
+ public interface AsyncCalleeWithProducesAndConsumesOnClass extends Closeable {
+ @POST
+ ListenableFuture<Void> testProducesAndConsumesOnClass();
}
@Path("/client/{jclouds.api-version}")
@@ -213,10 +229,28 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Delegate
@Path("/testing/testing/{wibble}")
Callee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble);
+
+ @Delegate
+ Callee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
+
+ @Delegate
+ Callee getCalleeWithoutProducesAndConsumes();
+
+ @Delegate
+ Callee getCalleeWithProducesAndConsumesOnMethod();
+
+ @Delegate
+ CalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
}
public interface Callee extends Closeable {
void onePath(String path);
+ void testWithoutProducesAndConsumes();
+ void testProducesAndConsumesOnMethod();
+ }
+
+ public interface CalleeWithProducesAndConsumesOnClass extends Closeable {
+ void testProducesAndConsumesOnClass();
}
public interface Callee2 {
@@ -243,6 +277,24 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
@Delegate
@Path("/testing/testing/{wibble}")
AsyncCallee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble);
+
+ @Delegate
+ AsyncCallee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
+
+ @Delegate
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCallee getCalleeWithoutProducesAndConsumes();
+
+ @Delegate
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCallee getCalleeWithProducesAndConsumesOnMethod();
+
+ @Delegate
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ AsyncCalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
}
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
@@ -371,6 +423,127 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
}
+ public void testAsyncDelegateWithHeaderParamIsLazyLoadedAndRequestIncludesEndpointVersionAndHeader()
+ throws InterruptedException, ExecutionException {
+ Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+ @Override
+ public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+ return Futures.immediateFuture(invoke(command));
+ }
+
+ @Override
+ public HttpResponse invoke(HttpCommand command) {
+ assertEquals(command.getCurrentRequest().getFirstHeaderOrNull("header"), "theheaderparam");
+ return HttpResponse.builder().build();
+ }
+
+ });
+
+ try {
+ child.getInstance(AsyncCallee.class);
+ fail("Callee shouldn't be bound yet");
+ } catch (ConfigurationException e) {
+
+ }
+
+ child.getInstance(AsyncCaller.class).getCalleeWithHeader(URI.create("http://howdyboys"), "theheaderparam")
+ .onePath("foo").get();
+ }
+
+ public void testAsyncDelegateWithoutProducesAndConsumes()
+ throws InterruptedException, ExecutionException {
+ Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+ @Override
+ public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+ return Futures.immediateFuture(invoke(command));
+ }
+
+ @Override
+ public HttpResponse invoke(HttpCommand command) {
+ assertEquals(
+ command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
+ MediaType.APPLICATION_JSON);
+ assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_JSON));
+ return HttpResponse.builder().build();
+ }
+
+ });
+
+ try {
+ child.getInstance(AsyncCallee.class);
+ fail("Callee shouldn't be bound yet");
+ } catch (ConfigurationException e) {
+
+ }
+
+ child.getInstance(AsyncCaller.class).getCalleeWithoutProducesAndConsumes()
+ .testWithoutProducesAndConsumes().get();
+ }
+
+ public void testAsyncDelegateWithProducesAndConsumesOnMethodIsLazyLoaded()
+ throws InterruptedException, ExecutionException {
+ Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+ @Override
+ public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+ return Futures.immediateFuture(invoke(command));
+ }
+
+ @Override
+ public HttpResponse invoke(HttpCommand command) {
+ assertEquals(
+ command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
+ MediaType.APPLICATION_XML);
+ assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_XML));
+ return HttpResponse.builder().build();
+ }
+
+ });
+
+ try {
+ child.getInstance(AsyncCallee.class);
+ fail("Callee shouldn't be bound yet");
+ } catch (ConfigurationException e) {
+
+ }
+
+ child.getInstance(AsyncCaller.class).getCalleeWithProducesAndConsumesOnMethod()
+ .testProducesAndConsumesOnMethod().get();
+ }
+
+ public void testAsyncDelegateWithProducesAndConsumesOnClassIsLazyLoaded()
+ throws InterruptedException, ExecutionException {
+ Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+ @Override
+ public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+ return Futures.immediateFuture(invoke(command));
+ }
+
+ @Override
+ public HttpResponse invoke(HttpCommand command) {
+ assertEquals(
+ command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
+ MediaType.APPLICATION_XML);
+ assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_XML));
+ return HttpResponse.builder().build();
+ }
+
+ });
+
+ try {
+ child.getInstance(AsyncCallee.class);
+ fail("Callee shouldn't be bound yet");
+ } catch (ConfigurationException e) {
+
+ }
+
+ child.getInstance(AsyncCaller.class).getCalleeWithProducesAndConsumesOnClass()
+ .testProducesAndConsumesOnClass().get();
+ }
+
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathOptionalPresent()
throws InterruptedException, ExecutionException {
Injector child = injectorForCaller(new HttpCommandExecutorService() {