mirror of https://github.com/apache/jclouds.git
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.
This commit is contained in:
parent
b90f74352f
commit
0387b1bb92
|
@ -777,9 +777,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
public static Key<? extends Function<HttpResponse, ?>> getParserOrThrowException(Method method) {
|
public static Key<? extends Function<HttpResponse, ?>> getParserOrThrowException(Method method) {
|
||||||
ResponseParser annotation = method.getAnnotation(ResponseParser.class);
|
ResponseParser annotation = method.getAnnotation(ResponseParser.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
if (method.isAnnotationPresent(JAXBResponseParser.class)) {
|
if (method.getReturnType().equals(void.class)
|
||||||
return getJAXBParserKeyForMethod(method);
|
|
||||||
} else if (method.getReturnType().equals(void.class)
|
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) {
|
||||||
return Key.get(ReleasePayloadAndReturn.class);
|
return Key.get(ReleasePayloadAndReturn.class);
|
||||||
} else if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class)
|
} else if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class)
|
||||||
|
@ -793,6 +791,9 @@ public class RestAnnotationProcessor<T> {
|
||||||
return Key.get((Class) IdentityFunction.class);
|
return Key.get((Class) IdentityFunction.class);
|
||||||
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
|
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
|
||||||
return getJsonParserKeyForMethod(method);
|
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)
|
} else if (method.getReturnType().equals(String.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
|
||||||
return Key.get(ReturnStringIf2xx.class);
|
return Key.get(ReturnStringIf2xx.class);
|
||||||
|
|
|
@ -32,7 +32,6 @@ import static org.jclouds.io.Payloads.newStringPayload;
|
||||||
import static org.jclouds.rest.RestContextFactory.contextSpec;
|
import static org.jclouds.rest.RestContextFactory.contextSpec;
|
||||||
import static org.jclouds.rest.RestContextFactory.createContextBuilder;
|
import static org.jclouds.rest.RestContextFactory.createContextBuilder;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -2456,9 +2455,14 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
|
|
||||||
public interface TestJAXBResponseParser {
|
public interface TestJAXBResponseParser {
|
||||||
@GET
|
@GET
|
||||||
@Path("/jaxb")
|
@Path("/jaxb/annotation")
|
||||||
@JAXBResponseParser
|
@JAXBResponseParser
|
||||||
public ListenableFuture<TestJAXBDomain> jaxbGet();
|
public ListenableFuture<TestJAXBDomain> jaxbGetWithAnnotation();
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/jaxb/header")
|
||||||
|
@Consumes(MediaType.APPLICATION_XML)
|
||||||
|
public ListenableFuture<TestJAXBDomain> jaxbGetWithAcceptHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@XmlRootElement(name = "test")
|
@XmlRootElement(name = "test")
|
||||||
|
@ -2474,9 +2478,20 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateJAXBResponseParser() throws SecurityException, NoSuchMethodException {
|
public void testCreateJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException {
|
||||||
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
|
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
|
||||||
Method method = TestJAXBResponseParser.class.getMethod("jaxbGet");
|
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation");
|
||||||
|
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser> builder().method("GET")
|
||||||
|
.endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class).javaMethod(method).args(
|
||||||
|
new Object[] {}).build();
|
||||||
|
Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
|
||||||
|
assertEquals(transformer.getClass(), ParseXMLWithJAXB.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException {
|
||||||
|
RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
|
||||||
|
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader");
|
||||||
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser> builder().method("GET")
|
GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser> builder().method("GET")
|
||||||
.endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class).javaMethod(method).args(
|
.endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class).javaMethod(method).args(
|
||||||
new Object[] {}).build();
|
new Object[] {}).build();
|
||||||
|
@ -2486,8 +2501,26 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testJAXBResponseParser() throws SecurityException, NoSuchMethodException, IOException {
|
public void testJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
Method method = TestJAXBResponseParser.class.getMethod("jaxbGet");
|
Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation");
|
||||||
|
HttpRequest request = factory(TestJAXBResponseParser.class).createRequest(method);
|
||||||
|
|
||||||
|
assertResponseParserClassEquals(method, request, ParseXMLWithJAXB.class);
|
||||||
|
// now test that it works!
|
||||||
|
|
||||||
|
Function<HttpResponse, TestJAXBDomain> parser = (Function<HttpResponse, TestJAXBDomain>) RestAnnotationProcessor
|
||||||
|
.createResponseParser(parserFactory, injector, method, request);
|
||||||
|
|
||||||
|
StringBuffer payload = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
|
||||||
|
payload.append("<test><elem>Hello World</elem></test>");
|
||||||
|
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);
|
HttpRequest request = factory(TestJAXBResponseParser.class).createRequest(method);
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, request, ParseXMLWithJAXB.class);
|
assertResponseParserClassEquals(method, request, ParseXMLWithJAXB.class);
|
||||||
|
|
Loading…
Reference in New Issue