Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit eebc7c3

Browse files
committed
JERSEY-2635: "Jersey does not produce first media type when accepts header is "*/*""
Change inspired by github pull request #102 by @mads-b. Thanks. Change-Id: Ib09187cfdfb6e118409554833197e31dbe1081db
1 parent ea4d4ce commit eebc7c3

File tree

3 files changed

+77
-41
lines changed

3 files changed

+77
-41
lines changed

core-server/src/main/java/org/glassfish/jersey/server/internal/routing/MethodSelectingRouter.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2012-2014 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -602,16 +602,15 @@ private MediaType determineResponseMediaType(final Class<?> entityClass,
602602
CombinedClientServerMediaType selected = null;
603603

604604
for (final MediaType acceptableMediaType : acceptableMediaTypes) {
605-
// Use writers suitable for entity class to determine the media type.
606-
for (final MessageBodyWriter<?> writer : workers.getMessageBodyWritersForType(responseEntityClass)) {
607-
for (final MediaType writerProduces : MediaTypes.createFrom(writer.getClass().getAnnotation(Produces.class))) {
608-
609-
if (writerProduces.isCompatible(acceptableMediaType)) {
610-
// Media types producible by method.
611-
final List<MediaType> methodProducesTypes = !resourceMethod.getProducedTypes().isEmpty() ?
612-
resourceMethod.getProducedTypes() : Lists.newArrayList(MediaType.WILDCARD_TYPE);
613-
614-
for (final MediaType methodProducesType : methodProducesTypes) {
605+
// Media types producible by method.
606+
final List<MediaType> methodProducesTypes = !resourceMethod.getProducedTypes().isEmpty() ?
607+
resourceMethod.getProducedTypes() : Lists.newArrayList(MediaType.WILDCARD_TYPE);
608+
609+
for (final MediaType methodProducesType : methodProducesTypes) {
610+
// Use writers suitable for entity class to determine the media type.
611+
for (final MessageBodyWriter<?> writer : workers.getMessageBodyWritersForType(responseEntityClass)) {
612+
for (final MediaType writerProduces : MediaTypes.createFrom(writer.getClass().getAnnotation(Produces.class))) {
613+
if (writerProduces.isCompatible(acceptableMediaType)) {
615614
if (methodProducesType.isCompatible(writerProduces)) {
616615

617616
final CombinedClientServerMediaType.EffectiveMediaType effectiveProduces = new
@@ -627,7 +626,6 @@ private MediaType determineResponseMediaType(final Class<?> entityClass,
627626
|| CombinedClientServerMediaType.COMPARATOR.compare(candidate, selected) > 0) {
628627
if (writer.isWriteable(responseEntityClass, entityType,
629628
handlingMethod.getDeclaredAnnotations(), candidate.getCombinedMediaType())) {
630-
631629
selected = candidate;
632630
}
633631
}

core-server/src/main/java/org/glassfish/jersey/server/model/Resource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2010-2014 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2010-2015 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -219,8 +219,8 @@ public static final class Builder {
219219

220220

221221
private Builder(final Resource.Builder parentResource) {
222-
this.methodBuilders = Sets.newIdentityHashSet();
223-
this.childResourceBuilders = Sets.newIdentityHashSet();
222+
this.methodBuilders = Sets.newLinkedHashSet();
223+
this.childResourceBuilders = Sets.newLinkedHashSet();
224224
this.childResources = Lists.newLinkedList();
225225
this.resourceMethods = Lists.newLinkedList();
226226
this.handlerClasses = Sets.newIdentityHashSet();

tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/server/ContentNegotiationTest.java

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -67,52 +67,66 @@ public class ContentNegotiationTest extends JerseyTest {
6767

6868
@Path("persons")
6969
public static class MyResource {
70+
private static final Person[] LIST = new Person[] {
71+
new Person("Penny", 1),
72+
new Person("Howard", 2),
73+
new Person("Sheldon", 3)
74+
};
75+
7076
@GET
7177
@Produces({"application/xml;qs=0.75", "application/json;qs=1.0"})
7278
public Person[] getList() {
73-
Person[] list = new Person[3];
74-
list[0] = new Person("Penny", 1);
75-
list[1] = new Person("Howard", 2);
76-
list[2] = new Person("Sheldon", 3);
77-
78-
return list;
79+
return LIST;
7980
}
8081

8182
@GET
8283
@Produces({"application/json;qs=1", "application/xml;qs=0.75"})
8384
@Path("reordered")
8485
public Person[] getListReordered() {
85-
Person[] list = new Person[3];
86-
list[0] = new Person("Penny", 1);
87-
list[1] = new Person("Howard", 2);
88-
list[2] = new Person("Sheldon", 3);
89-
90-
return list;
86+
return LIST;
9187
}
9288

9389
@GET
9490
@Produces({"application/json;qs=0.75", "application/xml;qs=1"})
9591
@Path("inverted")
9692
public Person[] getListInverted() {
97-
Person[] list = new Person[3];
98-
list[0] = new Person("Penny", 1);
99-
list[1] = new Person("Howard", 2);
100-
list[2] = new Person("Sheldon", 3);
101-
102-
return list;
93+
return LIST;
10394
}
10495

10596

10697
@GET
10798
@Produces({"application/xml;qs=0.75", "application/json;qs=0.9", "unknown/hello;qs=1.0"})
10899
@Path("unkownMT")
109100
public Person[] getListWithUnkownType() {
110-
Person[] list = new Person[3];
111-
list[0] = new Person("Penny", 1);
112-
list[1] = new Person("Howard", 2);
113-
list[2] = new Person("Sheldon", 3);
101+
return LIST;
102+
}
103+
104+
@GET
105+
@Produces({"application/json", "application/xml", "text/plain"})
106+
@Path("shouldPickFirstJson")
107+
public Person[] getJsonArrayUnlessOtherwiseSpecified() {
108+
return LIST;
109+
}
114110

115-
return list;
111+
@GET
112+
@Produces({"application/xml", "text/plain", "application/json"})
113+
@Path("shouldPickFirstXml")
114+
public Person[] getXmlUnlessOtherwiseSpecified() {
115+
return LIST;
116+
}
117+
118+
@GET
119+
@Produces("application/json;qs=0.75")
120+
@Path("twoMethodsOneEndpoint")
121+
public Person[] getJsonArray() {
122+
return LIST;
123+
}
124+
125+
@GET
126+
@Produces("application/xml;qs=1")
127+
@Path("twoMethodsOneEndpoint")
128+
public Person[] getXml() {
129+
return LIST;
116130
}
117131
}
118132

@@ -173,6 +187,30 @@ public void testWithoutDefinedRequestedMediaType() {
173187
Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
174188
}
175189

190+
@Test
191+
public void testWithoutDefinedRequestedMediaTypeAndTwoMethods() {
192+
//We can not rely on method declaration ordering:
193+
//From Class javadoc: "The elements in the returned array are not sorted and are not in any particular order."
194+
//If there are same endpoints it is necessary to use quality parameter to ensure ordering.
195+
Response response = target().path("/persons/twoMethodsOneEndpoint").request().get();
196+
Assert.assertEquals(200, response.getStatus());
197+
Assert.assertEquals(MediaType.APPLICATION_XML_TYPE, response.getMediaType());
198+
}
199+
200+
@Test
201+
public void testWithoutDefinedRequestedMediaTypeOrQualityModifiersJson() {
202+
Response response = target().path("/persons/shouldPickFirstJson").request().get();
203+
Assert.assertEquals(200, response.getStatus());
204+
Assert.assertEquals(MediaType.APPLICATION_JSON_TYPE, response.getMediaType());
205+
}
206+
207+
@Test
208+
public void testWithoutDefinedRequestedMediaTypeOrQualityModifiersXml() {
209+
Response response = target().path("/persons/shouldPickFirstXml").request().get();
210+
Assert.assertEquals(200, response.getStatus());
211+
Assert.assertEquals(MediaType.APPLICATION_XML_TYPE, response.getMediaType());
212+
}
213+
176214
@Test
177215
public void test() {
178216
WebTarget target = target().path("/persons");
@@ -190,7 +228,7 @@ public void testInverted() {
190228
}
191229

192230
@Test
193-
public void testInvertedWithJSONPrefferedByClient() {
231+
public void testInvertedWithJSONPreferredByClient() {
194232
WebTarget target = target().path("/persons/inverted");
195233
Response response = target.request("application/json;q=1.0", "application/xml;q=0.8").get();
196234
Assert.assertEquals(200, response.getStatus());
@@ -210,7 +248,7 @@ public void testReordered() {
210248
* this type is ignored and "application/xml" is chosen (because it is the second preferred type by the client).
211249
*/
212250
@Test
213-
public void testWithUnkownTypePreferedByClient() {
251+
public void testWithUnknownTypePreferredByClient() {
214252
WebTarget target = target().path("/persons/reordered");
215253
Response response = target.request("application/json;q=0.8", "application/xml;q=0.9",
216254
"unknown/hello;qs=1.0").get();

0 commit comments

Comments
 (0)