From 0387b1bb926703c8ec9d38a93e9b6abaa48e45a5 Mon Sep 17 00:00:00 2001 From: Ignasi Barrera Date: Wed, 26 Oct 2011 10:12:45 +0200 Subject: [PATCH] Updated JAXB parser configuration Now JAXB response parser is activated by default if the Accept header is set to application/xml or the method is annotated with the @JAXBResponseParser annotation (this way we can still use it to parse documents with vendor-specific mime-types). This will not break current XML parsers, since they must be explicitly defined with the @XMLResponseParser annotation, and will provide a default XML parsing mechanism. The only requirement will be to have domain objects annotated with standard Java JAXB annotations. It would be great to refactor the @XMLResponseParser annotation to be more flexible and to allow using other parsers than SAX, this way the @JAXBResponseParser annotation could be removed. However, this change may affect existing providers and must be studied with care. --- .../internal/RestAnnotationProcessor.java | 7 +-- .../internal/RestAnnotationProcessorTest.java | 47 ++++++++++++++++--- 2 files changed, 44 insertions(+), 10 deletions(-) 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 df2b0ed22f..1de7fa947e 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -777,9 +777,7 @@ public class RestAnnotationProcessor { public static Key> getParserOrThrowException(Method method) { ResponseParser annotation = method.getAnnotation(ResponseParser.class); if (annotation == null) { - if (method.isAnnotationPresent(JAXBResponseParser.class)) { - return getJAXBParserKeyForMethod(method); - } else if (method.getReturnType().equals(void.class) + if (method.getReturnType().equals(void.class) || TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) { return Key.get(ReleasePayloadAndReturn.class); } else if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class) @@ -793,6 +791,9 @@ public class RestAnnotationProcessor { return Key.get((Class) IdentityFunction.class); } else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) { return getJsonParserKeyForMethod(method); + } else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_XML) + || method.isAnnotationPresent(JAXBResponseParser.class)) { + return getJAXBParserKeyForMethod(method); } else if (method.getReturnType().equals(String.class) || TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) { return Key.get(ReturnStringIf2xx.class); 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 1b33ea6db3..11785926f2 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -32,7 +32,6 @@ import static org.jclouds.io.Payloads.newStringPayload; import static org.jclouds.rest.RestContextFactory.contextSpec; import static org.jclouds.rest.RestContextFactory.createContextBuilder; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; import java.io.File; import java.io.IOException; @@ -2456,9 +2455,14 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { public interface TestJAXBResponseParser { @GET - @Path("/jaxb") + @Path("/jaxb/annotation") @JAXBResponseParser - public ListenableFuture jaxbGet(); + public ListenableFuture jaxbGetWithAnnotation(); + + @GET + @Path("/jaxb/header") + @Consumes(MediaType.APPLICATION_XML) + public ListenableFuture jaxbGetWithAcceptHeader(); } @XmlRootElement(name = "test") @@ -2474,9 +2478,20 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { } @Test - public void testCreateJAXBResponseParser() throws SecurityException, NoSuchMethodException { + public void testCreateJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException { RestAnnotationProcessor processor = factory(TestJAXBResponseParser.class); - Method method = TestJAXBResponseParser.class.getMethod("jaxbGet"); + Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation"); + GeneratedHttpRequest request = GeneratedHttpRequest. builder().method("GET") + .endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class).javaMethod(method).args( + new Object[] {}).build(); + Function transformer = processor.createResponseParser(method, request); + assertEquals(transformer.getClass(), ParseXMLWithJAXB.class); + } + + @Test + public void testCreateJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException { + RestAnnotationProcessor processor = factory(TestJAXBResponseParser.class); + Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader"); GeneratedHttpRequest request = GeneratedHttpRequest. builder().method("GET") .endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class).javaMethod(method).args( new Object[] {}).build(); @@ -2486,8 +2501,26 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { @SuppressWarnings("unchecked") @Test - public void testJAXBResponseParser() throws SecurityException, NoSuchMethodException, IOException { - Method method = TestJAXBResponseParser.class.getMethod("jaxbGet"); + public void testJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation"); + HttpRequest request = factory(TestJAXBResponseParser.class).createRequest(method); + + assertResponseParserClassEquals(method, request, ParseXMLWithJAXB.class); + // now test that it works! + + Function parser = (Function) RestAnnotationProcessor + .createResponseParser(parserFactory, injector, method, request); + + StringBuffer payload = new StringBuffer(""); + payload.append("Hello World"); + TestJAXBDomain domain = parser.apply(new HttpResponse(200, "ok", newStringPayload(payload.toString()))); + assertEquals(domain.getElem(), "Hello World"); + } + + @SuppressWarnings("unchecked") + @Test + public void testJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader"); HttpRequest request = factory(TestJAXBResponseParser.class).createRequest(method); assertResponseParserClassEquals(method, request, ParseXMLWithJAXB.class);