From b38e6e885b7d793ee99018dc229be2963dd9f2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Kr=C3=A1l?= Date: Fri, 6 Sep 2019 17:07:53 +0200 Subject: [PATCH] Fixes #4239 MediaType in method parameter not overridden by annotation (#4243) * Fixes #4239 MediaType in method parameter not overridden by annotation Signed-off-by: David Kral --- .../microprofile/restclient/MethodModel.java | 29 +++++++++++++------ .../restclient/RestClientProducer.java | 3 +- pom.xml | 9 +++--- .../microprofile/rest-client/pom.xml | 18 ++++++++++++ .../restclient/ApplicationResource.java | 10 ++++++- .../restclient/ApplicationResourceImpl.java | 6 ++++ .../restclient/ConsumesAndProducesTest.java | 21 ++++++++++---- 7 files changed, 76 insertions(+), 20 deletions(-) diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java index bfb64ab86f..605e0a72f3 100644 --- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java +++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/MethodModel.java @@ -178,10 +178,11 @@ Object invokeMethod(WebTarget classLevelTarget, Method method, Object[] args) { webTarget = addQueryParams(webTarget, args); webTarget = addMatrixParams(webTarget, args); + MultivaluedMap customHeaders = addCustomHeaders(args); Invocation.Builder builder = webTarget .request(produces) .property(INVOKED_METHOD, method) - .headers(addCustomHeaders(args)); + .headers(customHeaders); builder = addCookies(builder, args); Object entityToUse = entity.get(); @@ -192,9 +193,9 @@ Object invokeMethod(WebTarget classLevelTarget, Method method, Object[] args) { Object response; if (CompletionStage.class.isAssignableFrom(method.getReturnType())) { - response = asynchronousCall(builder, entityToUse, method); + response = asynchronousCall(builder, entityToUse, method, customHeaders); } else { - response = synchronousCall(builder, entityToUse, method); + response = synchronousCall(builder, entityToUse, method, customHeaders); } return response; } @@ -210,13 +211,16 @@ private Form handleForm(Object[] args) { return form; } - private Object synchronousCall(Invocation.Builder builder, Object entity, Method method) { + private Object synchronousCall(Invocation.Builder builder, + Object entity, + Method method, + MultivaluedMap customHeaders) { Response response; if (entity != null && !httpMethod.equals(GET.class.getSimpleName()) && !httpMethod.equals(DELETE.class.getSimpleName())) { - response = builder.method(httpMethod, Entity.entity(entity, consumes[0])); + response = builder.method(httpMethod, Entity.entity(entity, getContentType(customHeaders))); } else { response = builder.method(httpMethod); } @@ -231,13 +235,16 @@ private Object synchronousCall(Invocation.Builder builder, Object entity, Method return response.readEntity(returnType); } - private CompletableFuture asynchronousCall(Invocation.Builder builder, Object entity, Method method) { + private CompletableFuture asynchronousCall(Invocation.Builder builder, + Object entity, + Method method, + MultivaluedMap customHeaders) { CompletableFuture result = new CompletableFuture<>(); Future theFuture; if (entity != null && !httpMethod.equals(GET.class.getSimpleName()) && !httpMethod.equals(DELETE.class.getSimpleName())) { - theFuture = builder.async().method(httpMethod, Entity.entity(entity, consumes[0])); + theFuture = builder.async().method(httpMethod, Entity.entity(entity, getContentType(customHeaders))); } else { theFuture = builder.async().method(httpMethod); } @@ -266,6 +273,10 @@ private CompletableFuture asynchronousCall(Invocation.Builder builder, Object en return result; } + private String getContentType(MultivaluedMap customHeaders) { + return (String) customHeaders.getFirst(HttpHeaders.CONTENT_TYPE); + } + @SuppressWarnings("unchecked") private T subResourceProxy(WebTarget webTarget, Class subResourceType) { return (T) Proxy.newProxyInstance(subResourceType.getClassLoader(), @@ -326,8 +337,8 @@ private MultivaluedMap addCustomHeaders(Object[] args) { for (String produce : produces) { result.add(HttpHeaders.ACCEPT, produce); } - result.add(HttpHeaders.CONTENT_TYPE, consumes[0]); - return result; + result.putIfAbsent(HttpHeaders.CONTENT_TYPE, Collections.singletonList(consumes[0])); + return new MultivaluedHashMap(result); } @SuppressWarnings("unchecked") //I am checking the type of parameter and I know it should handle instance I am sending diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java index 22a2af9a0d..8d5de4ca42 100644 --- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java +++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/RestClientProducer.java @@ -21,6 +21,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; @@ -336,7 +337,7 @@ private InputStream locationToStream(String location) throws IOException { } return result; } else if (location.startsWith(FILE_LOCATION)) { - return Files.newInputStream(Paths.get(location.substring(FILE_LOCATION.length()))); + return Files.newInputStream(Paths.get(URI.create(location))); } else { throw new IllegalStateException("Location of keystore must start with either classpath: or file:, but is: " + location diff --git a/pom.xml b/pom.xml index 8438b01822..297e710728 100644 --- a/pom.xml +++ b/pom.xml @@ -403,7 +403,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M3 + ${surefire.version} @@ -2059,6 +2059,7 @@ 2.3.6 1.1 3.3.2 + 1.2.1 2.16 6.8.1 3.3 @@ -2073,6 +2074,7 @@ 2.4.4 18.0 1.3 + 1.0.3 1.6 2.6.1 5.1.0 @@ -2127,16 +2129,15 @@ 3.0.1 4.0.3 6.0.1 + false 1.7.21 4.3.20.RELEASE 5.1.5.RELEASE + 3.0.0-M3 6.0.17.Final 2.2.14.Final 3.0.0.Final 2.11.0 1.0.3 - 1.0.3 - 1.2.1 - false diff --git a/tests/integration/microprofile/rest-client/pom.xml b/tests/integration/microprofile/rest-client/pom.xml index a4c5e036a1..5ad9b9ac90 100644 --- a/tests/integration/microprofile/rest-client/pom.xml +++ b/tests/integration/microprofile/rest-client/pom.xml @@ -42,6 +42,11 @@ 1.3.3 test + + junit + junit + test + org.testng testng @@ -89,7 +94,20 @@ org.apache.maven.plugins maven-surefire-plugin + + + org.apache.maven.surefire + surefire-junit47 + ${surefire.version} + + + org.apache.maven.surefire + surefire-testng + ${surefire.version} + + + 1 tck-suite.xml diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java index 0cb3ad99ef..5b8ef7c1a5 100644 --- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResource.java @@ -22,8 +22,12 @@ import javax.json.JsonValue; import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; /** @@ -36,7 +40,6 @@ public interface ApplicationResource { @GET List getValue(); - @GET @Path("map") Map getTestMap(); @@ -57,5 +60,10 @@ default String sayHi() { return "Hi"; } + @PUT + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_JSON) + @Path("methodContent") + String methodContentType(@HeaderParam(HttpHeaders.CONTENT_TYPE) MediaType contentType, String entity); } diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java index e3150a85a9..37de0dc620 100644 --- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ApplicationResourceImpl.java @@ -22,6 +22,7 @@ import java.util.Map; import javax.json.JsonValue; +import javax.ws.rs.core.MediaType; /** * Created by David Kral. @@ -55,4 +56,9 @@ public JsonValue jsonValue() { return null; } + @Override + public String methodContentType(MediaType contentType, String entity) { + return null; + } + } diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java index 7f0363f4d9..5bfe041334 100644 --- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java +++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/restclient/ConsumesAndProducesTest.java @@ -7,6 +7,7 @@ import javax.json.Json; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -43,12 +44,22 @@ public void testWithEntity() throws URISyntaxException { public void testWithoutEntity() throws URISyntaxException { ApplicationResource app = RestClientBuilder.newBuilder() .baseUri(new URI("http://localhost:9998")) - .register(new TestClientRequestFilter(MediaType.APPLICATION_JSON, MediaType.WILDCARD)) + .register(new TestClientRequestFilter(MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON)) .build(ApplicationResource.class); app.jsonValue(); } + @Test + public void testMethodContentType() throws URISyntaxException { + ApplicationResource app = RestClientBuilder.newBuilder() + .baseUri(new URI("http://localhost:9998")) + .register(new TestClientRequestFilter(MediaType.TEXT_PLAIN, MediaType.TEXT_XML)) + .build(ApplicationResource.class); + + app.methodContentType(MediaType.TEXT_XML_TYPE, "something"); + } + private class TestClientRequestFilter implements ClientRequestFilter { private final String expectedAccept; @@ -61,12 +72,12 @@ private class TestClientRequestFilter implements ClientRequestFilter { @Override public void filter(ClientRequestContext requestContext) { - assertTrue(requestContext.getHeaders().containsKey("Accept")); - List accept = requestContext.getHeaders().get("Accept"); + assertTrue(requestContext.getHeaders().containsKey(HttpHeaders.ACCEPT)); + List accept = requestContext.getHeaders().get(HttpHeaders.ACCEPT); assertTrue(accept.contains(expectedAccept) || accept.contains(MediaType.valueOf(expectedAccept))); - assertTrue(requestContext.getHeaders().containsKey("Content-Type")); - List contentType = requestContext.getHeaders().get("Content-Type"); + assertTrue(requestContext.getHeaders().containsKey(HttpHeaders.CONTENT_TYPE)); + List contentType = requestContext.getHeaders().get(HttpHeaders.CONTENT_TYPE); assertEquals(contentType.size(), 1); assertTrue(contentType.contains(expectedContentType) || contentType.contains(MediaType.valueOf(expectedContentType)));