Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit c8c7bed

Browse files
committed
ApiTool raml gives error "invalid media type" with mediaType "x-www-form-urlencoded" fix jooby-project#1050
1 parent ac60a15 commit c8c7bed

File tree

5 files changed

+102
-40
lines changed

5 files changed

+102
-40
lines changed

modules/jooby-apitool/src/main/java/org/jooby/apitool/raml/Raml.java

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,21 @@ public static Raml build(Raml base, List<RouteMethod> routes) {
558558
p.setDefault(parameter.defaultValue());
559559
};
560560

561+
/** Default consumes/produces: */
562+
Set<String> alltypes = new LinkedHashSet<>();
563+
Consumer<Function<RouteMethod, List<String>>> mediaTypes = types ->
564+
routes.stream().forEach(r -> types.apply(r).forEach(alltypes::add));
565+
mediaTypes.accept(RouteMethod::consumes);
566+
mediaTypes.accept(RouteMethod::produces);
567+
boolean defaultMediaType = false;
568+
if (alltypes.size() == 0) {
569+
raml.setMediaType(ImmutableList.of(MediaType.json.name()));
570+
defaultMediaType = true;
571+
} else if (alltypes.size() == 1) {
572+
raml.setMediaType(ImmutableList.of(alltypes.iterator().next()));
573+
defaultMediaType = true;
574+
}
575+
561576
for (RouteMethod route : routes) {
562577
List<String> segments = Splitter.on("/")
563578
.trimResults()
@@ -602,6 +617,13 @@ public static Raml build(Raml base, List<RouteMethod> routes) {
602617
.filter(it -> it.kind() == RouteParameter.Kind.QUERY)
603618
.forEach(it -> parameterFactory.accept(method::queryParameter, it));
604619
}
620+
/** Consumes: */
621+
List<String> consumes = route.consumes();
622+
if (consumes.size() == 0 && !defaultMediaType) {
623+
consumes = ImmutableList.of(MediaType.json.name());
624+
}
625+
method.setMediaType(consumes);
626+
605627
/** Headers: */
606628
route.parameters().stream()
607629
.filter(it -> it.kind() == RouteParameter.Kind.HEADER)
@@ -615,33 +637,21 @@ public static Raml build(Raml base, List<RouteMethod> routes) {
615637
method.setBody(raml.define(it.type()));
616638
});
617639
/** Response: */
640+
List<String> produces = route.produces();
641+
if (produces.size() == 0) {
642+
produces = ImmutableList.of(MediaType.json.name());
643+
}
618644
RouteResponse returns = route.response();
619645
Map<Integer, String> status = returns.status();
620646
Integer statusCode = returns.statusCode();
621647
RamlResponse response = method.response(statusCode);
622648
response.setDescription(yamlText(returns.description().orElse(status.get(statusCode))));
623-
if (route.produces().size() > 0) {
624-
route.produces().forEach(type -> response.setMediaType(type, raml.define(returns.type())));
625-
} else {
626-
response.setMediaType(null, raml.define(returns.type()));
627-
}
649+
produces.forEach(type -> response.setMediaType(type, raml.define(returns.type())));
628650
status.entrySet().stream()
629651
.filter(it -> !statusCode.equals(it.getKey()))
630652
.forEach(it -> method.response(it.getKey()).setDescription(it.getValue()));
631653
}
632654

633-
/** Default consumes/produces: */
634-
Set<String> alltypes = new LinkedHashSet<>();
635-
Consumer<Function<RouteMethod, List<String>>> mediaTypes = types ->
636-
routes.stream().forEach(r -> types.apply(r).forEach(alltypes::add));
637-
mediaTypes.accept(RouteMethod::consumes);
638-
mediaTypes.accept(RouteMethod::produces);
639-
if (alltypes.size() == 0) {
640-
raml.setMediaType(ImmutableList.of(MediaType.json.name()));
641-
} else if (alltypes.size() == 1) {
642-
raml.setMediaType(ImmutableList.of(alltypes.iterator().next()));
643-
}
644-
645655
return raml;
646656
}
647657

modules/jooby-apitool/src/main/java/org/jooby/apitool/raml/RamlMethod.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@
211211
import java.util.LinkedHashMap;
212212
import java.util.List;
213213
import java.util.Map;
214-
import java.util.Optional;
215214
import java.util.function.Function;
216215
import java.util.stream.Collectors;
217216

@@ -466,18 +465,21 @@ public RamlResponse response(Integer status) {
466465
@JsonAnyGetter
467466
Map<String, Object> attributes() {
468467
Map<String, Object> attributes = new LinkedHashMap<>();
469-
Optional.ofNullable(formParameters).ifPresent(form -> {
468+
if (formParameters != null) {
470469
attributes.put("body",
471-
ImmutableMap.of(MediaType.multipart.name(), ImmutableMap.of("properties", form)));
472-
});
473-
Optional.ofNullable(body).ifPresent(body -> {
470+
ImmutableMap
471+
.of(MediaType.multipart.name(), ImmutableMap.of("properties", formParameters)));
472+
} else if (body != null) {
474473
if (mediaType != null) {
475474
attributes.put("body", mediaType.stream()
476475
.collect(Collectors.toMap(Function.identity(), it -> body.getRef())));
477476
} else {
478477
attributes.put("body", body.getRef());
479478
}
480-
});
479+
} else if (mediaType != null) {
480+
attributes.put("body", mediaType.stream()
481+
.collect(Collectors.toMap(Function.identity(), it -> ImmutableMap.of())));
482+
}
481483
return attributes;
482484
}
483485
}

modules/jooby-apitool/src/main/java/org/jooby/apitool/raml/RamlResponse.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,9 @@ public void setDescription(final String description) {
241241
Map<String, Object> attributes() {
242242
Map<String, Object> attributes = new LinkedHashMap<>();
243243
if (mediaType != null) {
244-
if (mediaType.size() == 1) {
245-
Map.Entry<String, RamlType> e = mediaType.entrySet().iterator().next();
246-
if (e.getKey() == null) {
247-
attributes.put("body", e.getValue().getRef());
248-
}
249-
} else {
250-
Map<String, Object> body = new LinkedHashMap<>();
251-
mediaType.forEach((type, bodyType) -> body.put(type, bodyType.getRef()));
252-
attributes.put("body", body);
253-
}
244+
Map<String, Object> body = new LinkedHashMap<>();
245+
mediaType.forEach((type, bodyType) -> body.put(type, bodyType.getRef()));
246+
attributes.put("body", body);
254247
}
255248
return attributes.size() == 0 ? null : attributes;
256249
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package issues;
2+
3+
import com.google.common.collect.ImmutableList;
4+
import org.jooby.apitool.RouteMethod;
5+
import org.jooby.apitool.RouteResponse;
6+
import org.jooby.apitool.raml.Raml;
7+
import static org.junit.Assert.assertEquals;
8+
import org.junit.Test;
9+
10+
import java.io.IOException;
11+
import java.util.Arrays;
12+
import java.util.List;
13+
14+
public class Issue1050 {
15+
16+
@Test
17+
public void mediaTypeOnControllers() throws IOException {
18+
RouteMethod home = new RouteMethod("get", "/", new RouteResponse(String.class));
19+
20+
RouteMethod controller = new RouteMethod("get", "/controller/controller", new RouteResponse(String.class));
21+
controller.consumes(ImmutableList.of("application/x-www-form-urlencoded"));
22+
controller.produces(ImmutableList.of("application/json"));
23+
24+
List<RouteMethod> methods = Arrays.asList(home, controller);
25+
String yaml = Raml.build(null, methods)
26+
.toYaml();
27+
assertEquals("#%RAML 1.0\n"
28+
+ "---\n"
29+
+ "types: {}\n"
30+
+ "/:\n"
31+
+ " get:\n"
32+
+ " responses:\n"
33+
+ " 200:\n"
34+
+ " body:\n"
35+
+ " application/json:\n"
36+
+ " type: string\n"
37+
+ " body:\n"
38+
+ " application/json: {}\n"
39+
+ "/controller:\n"
40+
+ " /controller:\n"
41+
+ " get:\n"
42+
+ " responses:\n"
43+
+ " 200:\n"
44+
+ " body:\n"
45+
+ " application/json:\n"
46+
+ " type: string\n"
47+
+ " body:\n"
48+
+ " application/x-www-form-urlencoded: {}\n", yaml);
49+
}
50+
}

modules/jooby-apitool/src/test/java/org/jooby/apitool/RamlTest.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public void shouldWorkWithUUID() throws Exception {
7171
+ " responses:\n"
7272
+ " 200:\n"
7373
+ " body:\n"
74-
+ " type: Client\n", yaml);
74+
+ " application/json:\n"
75+
+ " type: Client\n", yaml);
7576
}
7677

7778
@Test
@@ -112,7 +113,8 @@ public void shouldUseCustomType() throws Exception {
112113
+ " responses:\n"
113114
+ " 200:\n"
114115
+ " body:\n"
115-
+ " type: Foo\n", yaml);
116+
+ " application/json:\n"
117+
+ " type: Foo\n", yaml);
116118
}
117119

118120
@Test
@@ -166,7 +168,8 @@ public void shouldExportToRaml() throws Exception {
166168
+ " responses:\n"
167169
+ " 200:\n"
168170
+ " body:\n"
169-
+ " type: string\n"
171+
+ " application/json:\n"
172+
+ " type: string\n"
170173
+ "/api:\n"
171174
+ " /pets:\n"
172175
+ " description: Everything about your Pets.\n"
@@ -187,14 +190,16 @@ public void shouldExportToRaml() throws Exception {
187190
+ " 200:\n"
188191
+ " description: Pets ordered by name.\n"
189192
+ " body:\n"
190-
+ " type: Pet[]\n"
193+
+ " application/json:\n"
194+
+ " type: Pet[]\n"
191195
+ " post:\n"
192196
+ " description: Add a new pet to the store.\n"
193197
+ " responses:\n"
194198
+ " 200:\n"
195199
+ " description: Returns a saved pet.\n"
196200
+ " body:\n"
197-
+ " type: Pet\n"
201+
+ " application/json:\n"
202+
+ " type: Pet\n"
198203
+ " body:\n"
199204
+ " type: Pet\n"
200205
+ " /{id}:\n"
@@ -210,7 +215,8 @@ public void shouldExportToRaml() throws Exception {
210215
+ " 200:\n"
211216
+ " description: Returns <code>200</code> with a single pet or <code>404</code>\n"
212217
+ " body:\n"
213-
+ " type: Pet\n"
218+
+ " application/json:\n"
219+
+ " type: Pet\n"
214220
+ " 404:\n"
215221
+ " description: Not Found\n"
216222
+ " delete:\n"
@@ -219,7 +225,8 @@ public void shouldExportToRaml() throws Exception {
219225
+ " 204:\n"
220226
+ " description: A <code>204</code>\n"
221227
+ " body:\n"
222-
+ " type: Pet\n", yaml);
228+
+ " application/json:\n"
229+
+ " type: Pet\n", yaml);
223230
}
224231

225232
private Path dir() {

0 commit comments

Comments
 (0)