Skip to content

Commit

Permalink
Fixes #4239 MediaType in method parameter not overridden by annotation (
Browse files Browse the repository at this point in the history
#4243)

* Fixes #4239 MediaType in method parameter not overridden by annotation

Signed-off-by: David Kral <david.k.kral@oracle.com>
  • Loading branch information
Verdent authored and senivam committed Sep 6, 2019
1 parent b99f435 commit b38e6e8
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 20 deletions.
Expand Up @@ -178,10 +178,11 @@ Object invokeMethod(WebTarget classLevelTarget, Method method, Object[] args) {
webTarget = addQueryParams(webTarget, args);
webTarget = addMatrixParams(webTarget, args);

MultivaluedMap<String, Object> 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();
Expand All @@ -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;
}
Expand All @@ -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<String, Object> 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);
}
Expand All @@ -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<String, Object> customHeaders) {
CompletableFuture<Object> result = new CompletableFuture<>();
Future<Response> 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);
}
Expand Down Expand Up @@ -266,6 +273,10 @@ private CompletableFuture asynchronousCall(Invocation.Builder builder, Object en
return result;
}

private String getContentType(MultivaluedMap<String, Object> customHeaders) {
return (String) customHeaders.getFirst(HttpHeaders.CONTENT_TYPE);
}

@SuppressWarnings("unchecked")
private <T> T subResourceProxy(WebTarget webTarget, Class<T> subResourceType) {
return (T) Proxy.newProxyInstance(subResourceType.getClassLoader(),
Expand Down Expand Up @@ -326,8 +337,8 @@ private MultivaluedMap<String, Object> 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<String, Object>(result);
}

@SuppressWarnings("unchecked") //I am checking the type of parameter and I know it should handle instance I am sending
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions pom.xml
Expand Up @@ -403,7 +403,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<version>${surefire.version}</version>
<configuration>
<!-- for convenience reasons, 'argLine' should not be overridden in child poms. if needed, a property should be declared and used here -->
<argLine>
Expand Down Expand Up @@ -2059,6 +2059,7 @@
<bnd.plugin.version>2.3.6</bnd.plugin.version>
<cdi.api.version>1.1</cdi.api.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<config.version>1.2.1</config.version>
<checkstyle.mvn.plugin.version>2.16</checkstyle.mvn.plugin.version>
<checkstyle.version>6.8.1</checkstyle.version>
<easymock.version>3.3</easymock.version>
Expand All @@ -2073,6 +2074,7 @@
<grizzly2.version>2.4.4</grizzly2.version>
<guava.version>18.0</guava.version>
<hamcrest.version>1.3</hamcrest.version>
<helidon.version>1.0.3</helidon.version>
<xmlunit.version>1.6</xmlunit.version>
<hk2.version>2.6.1</hk2.version>
<hk2.config.version>5.1.0</hk2.config.version>
Expand Down Expand Up @@ -2127,16 +2129,15 @@
<servlet3.version>3.0.1</servlet3.version>
<servlet4.version>4.0.3</servlet4.version>
<simple.version>6.0.1</simple.version>
<skip.e2e>false</skip.e2e>
<slf4j.version>1.7.21</slf4j.version>
<spring4.version>4.3.20.RELEASE</spring4.version>
<spring5.version>5.1.5.RELEASE</spring5.version>
<surefire.version>3.0.0-M3</surefire.version>
<validation.impl.version>6.0.17.Final</validation.impl.version>
<weld.version>2.2.14.Final</weld.version> <!-- 2.4.1 doesn't work - bv tests -->
<weld3.version>3.0.0.Final</weld3.version>
<xerces.version>2.11.0</xerces.version>
<yasson.version>1.0.3</yasson.version>
<helidon.version>1.0.3</helidon.version>
<config.version>1.2.1</config.version>
<skip.e2e>false</skip.e2e>
</properties>
</project>
18 changes: 18 additions & 0 deletions tests/integration/microprofile/rest-client/pom.xml
Expand Up @@ -42,6 +42,11 @@
<version>1.3.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
Expand Down Expand Up @@ -89,7 +94,20 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>${surefire.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-testng</artifactId>
<version>${surefire.version}</version>
</dependency>
</dependencies>
<configuration>
<threadCount>1</threadCount>
<suiteXmlFiles>
<suiteXmlFile>tck-suite.xml</suiteXmlFile>
</suiteXmlFiles>
Expand Down
Expand Up @@ -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;

/**
Expand All @@ -36,7 +40,6 @@ public interface ApplicationResource {
@GET
List<String> getValue();


@GET
@Path("map")
Map<String, String> getTestMap();
Expand All @@ -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);

}
Expand Up @@ -22,6 +22,7 @@
import java.util.Map;

import javax.json.JsonValue;
import javax.ws.rs.core.MediaType;

/**
* Created by David Kral.
Expand Down Expand Up @@ -55,4 +56,9 @@ public JsonValue jsonValue() {
return null;
}

@Override
public String methodContentType(MediaType contentType, String entity) {
return null;
}

}
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -61,12 +72,12 @@ private class TestClientRequestFilter implements ClientRequestFilter {

@Override
public void filter(ClientRequestContext requestContext) {
assertTrue(requestContext.getHeaders().containsKey("Accept"));
List<Object> accept = requestContext.getHeaders().get("Accept");
assertTrue(requestContext.getHeaders().containsKey(HttpHeaders.ACCEPT));
List<Object> accept = requestContext.getHeaders().get(HttpHeaders.ACCEPT);
assertTrue(accept.contains(expectedAccept) || accept.contains(MediaType.valueOf(expectedAccept)));

assertTrue(requestContext.getHeaders().containsKey("Content-Type"));
List<Object> contentType = requestContext.getHeaders().get("Content-Type");
assertTrue(requestContext.getHeaders().containsKey(HttpHeaders.CONTENT_TYPE));
List<Object> contentType = requestContext.getHeaders().get(HttpHeaders.CONTENT_TYPE);
assertEquals(contentType.size(), 1);
assertTrue(contentType.contains(expectedContentType) || contentType.contains(MediaType.valueOf(expectedContentType)));

Expand Down

0 comments on commit b38e6e8

Please sign in to comment.