Skip to content

Commit 02d1769

Browse files
committed
Support @produces for json() html(), plain text and custom
1 parent bab873c commit 02d1769

File tree

4 files changed

+49
-14
lines changed

4 files changed

+49
-14
lines changed

pom.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
<properties>
2222
<swagger.version>2.0.8</swagger.version>
23+
<jackson-databind.version>2.9.8</jackson-databind.version>
2324
</properties>
2425

2526
<dependencies>
@@ -33,13 +34,13 @@
3334
<dependency>
3435
<groupId>io.dinject</groupId>
3536
<artifactId>dinject-controller</artifactId>
36-
<version>1.6</version>
37+
<version>1.7-SNAPSHOT</version>
3738
</dependency>
3839

3940
<dependency>
4041
<groupId>com.fasterxml.jackson.core</groupId>
4142
<artifactId>jackson-databind</artifactId>
42-
<version>2.9.8</version>
43+
<version>${jackson-databind.version}</version>
4344
</dependency>
4445

4546
<dependency>

src/main/java/io/dinject/javalin/generator/ControllerReader.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.dinject.javalin.generator;
22

33
import io.dinject.controller.Path;
4+
import io.dinject.controller.Produces;
45
import io.swagger.v3.oas.annotations.Hidden;
56

67
import javax.lang.model.element.Element;
@@ -31,12 +32,18 @@ class ControllerReader {
3132

3233
private final Set<String> importTypes = new TreeSet<>();
3334

35+
/**
36+
* The produces media type for the controller. Null implies JSON.
37+
*/
38+
private final String produces;
39+
3440
private boolean docHidden;
3541

3642
ControllerReader(TypeElement beanType, ProcessingContext ctx) {
3743
this.beanType = beanType;
3844
this.ctx = ctx;
3945
this.roles = Util.findRoles(beanType);
46+
this.produces = produces(beanType);
4047
if (ctx.isGeneratedAvailable()) {
4148
importTypes.add(Constants.GENERATED);
4249
}
@@ -49,10 +56,19 @@ class ControllerReader {
4956
importTypes.add(beanType.getQualifiedName().toString());
5057
}
5158

59+
private String produces(TypeElement beanType) {
60+
final Produces produces = beanType.getAnnotation(Produces.class);
61+
return (produces == null) ? null : produces.value();
62+
}
63+
5264
private boolean isDocHidden(TypeElement beanType) {
5365
return beanType.getAnnotation(Hidden.class) != null;
5466
}
5567

68+
String getProduces() {
69+
return produces;
70+
}
71+
5672
TypeElement getBeanType() {
5773
return beanType;
5874
}

src/main/java/io/dinject/javalin/generator/MethodReader.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import io.dinject.controller.Delete;
44
import io.dinject.controller.Form;
55
import io.dinject.controller.Get;
6+
import io.dinject.controller.MediaType;
67
import io.dinject.controller.Patch;
78
import io.dinject.controller.Post;
9+
import io.dinject.controller.Produces;
810
import io.dinject.controller.Put;
911
import io.dinject.javalin.generator.javadoc.Javadoc;
1012
import io.swagger.v3.oas.annotations.Hidden;
@@ -45,6 +47,8 @@ class MethodReader {
4547
*/
4648
private final List<String> methodRoles;
4749

50+
private final String produces;
51+
4852
private String fullPath;
4953

5054
private PathSegments segments;
@@ -57,10 +61,16 @@ class MethodReader {
5761
this.isVoid = element.getReturnType().toString().equals("void");
5862
this.methodRoles = Util.findRoles(element);
5963
this.javadoc = Javadoc.parse(ctx.getDocComment(element));
64+
this.produces = produces(element, bean);
6065

6166
readMethodAnnotation();
6267
}
6368

69+
private String produces(ExecutableElement element, ControllerReader bean) {
70+
final Produces produces = element.getAnnotation(Produces.class);
71+
return (produces != null) ? produces.value() : bean.getProduces();
72+
}
73+
6474
void read() {
6575
if (!methodRoles.isEmpty()) {
6676
bean.addStaticImportType(JAVALIN_ROLES);
@@ -129,7 +139,8 @@ void addMeta(ProcessingContext ctx) {
129139
responses.addApiResponse("204", response);
130140
} else {
131141
responses.addApiResponse(ApiResponses.DEFAULT, response);
132-
response.setContent(ctx.createContent(returnType, "application/json"));
142+
String contentMediaType = (produces == null) ? MediaType.APPLICATION_JSON : produces;
143+
response.setContent(ctx.createContent(returnType, contentMediaType));
133144
}
134145
}
135146
}
@@ -169,8 +180,8 @@ void addRoute(Append writer) {
169180
}
170181
writer.append(" ");
171182

172-
if (isReturnJson()) {
173-
writer.append("ctx.json(");
183+
if (isReturnContent()) {
184+
writeContextReturn(writer);
174185
}
175186
writer.append("controller.");
176187
writer.append(element.getSimpleName().toString()).append("(");
@@ -181,7 +192,7 @@ void addRoute(Append writer) {
181192
params.get(i).buildParamName(writer);
182193
}
183194
writer.append(")");
184-
if (isReturnJson()) {
195+
if (isReturnContent()) {
185196
writer.append(")");
186197
}
187198
writer.append(";").eol();
@@ -203,6 +214,18 @@ void addRoute(Append writer) {
203214
}
204215
}
205216

217+
private void writeContextReturn(Append writer) {
218+
if (produces == null || produces.equalsIgnoreCase(MediaType.APPLICATION_JSON)) {
219+
writer.append("ctx.json(");
220+
} else if (produces.equalsIgnoreCase(MediaType.TEXT_HTML)) {
221+
writer.append("ctx.html(");
222+
} else if (produces.equalsIgnoreCase(MediaType.TEXT_PLAIN)) {
223+
writer.append("ctx.contentType(\"text/plain\").result(");
224+
} else {
225+
writer.append("ctx.contentType(\"%s\").result(", produces);
226+
}
227+
}
228+
206229
private List<String> roles() {
207230
return methodRoles.isEmpty() ? bean.getRoles() : methodRoles;
208231
}
@@ -211,12 +234,10 @@ private int httpStatusCode() {
211234
return webMethod.statusCode();
212235
}
213236

214-
private boolean isReturnJson() {
215-
// TODO: ... returning non-object types?
237+
private boolean isReturnContent() {
216238
return !isVoid;
217239
}
218240

219-
220241
private boolean readMethodAnnotation() {
221242

222243
Form form = element.getAnnotation(Form.class);

src/main/java/io/dinject/javalin/generator/ProcessingContext.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import javax.lang.model.element.TypeElement;
1313
import javax.lang.model.type.TypeMirror;
1414
import javax.lang.model.util.Elements;
15-
import javax.lang.model.util.Types;
1615
import javax.tools.Diagnostic;
1716
import javax.tools.FileObject;
1817
import javax.tools.JavaFileObject;
@@ -22,11 +21,10 @@
2221
import static io.dinject.javalin.generator.Constants.GENERATED;
2322
import static io.dinject.javalin.generator.Constants.OPENAPIDEFINITION;
2423

25-
public class ProcessingContext {
24+
class ProcessingContext {
2625

2726
private final Messager messager;
2827
private final Filer filer;
29-
private final Types types;
3028
private final Elements elements;
3129
private final SchemaBuilder schemaBuilder;
3230
private final boolean generatedAvailable;
@@ -38,8 +36,7 @@ public class ProcessingContext {
3836
this.messager = env.getMessager();
3937
this.filer = env.getFiler();
4038
this.elements = env.getElementUtils();
41-
this.types = env.getTypeUtils();
42-
this.schemaBuilder = new SchemaBuilder(types, elements);//, this);
39+
this.schemaBuilder = new SchemaBuilder(env.getTypeUtils(), elements);
4340
this.generatedAvailable = isTypeAvailable(GENERATED);
4441
this.openApiAvailable = isTypeAvailable(OPENAPIDEFINITION);
4542
}

0 commit comments

Comments
 (0)