Skip to content

Commit 3fecb6c

Browse files
authored
Merge pull request #150 from SentryMan/status
Now can override default status code with @produces
2 parents 5b8566e + a4381dd commit 3fecb6c

File tree

5 files changed

+81
-15
lines changed

5 files changed

+81
-15
lines changed

http-api/src/main/java/io/avaje/http/api/Produces.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,26 @@
2424
*
2525
* }</pre>
2626
*/
27-
@Target(value={TYPE, METHOD})
28-
@Retention(value=RUNTIME)
27+
@Target(value = {TYPE, METHOD})
28+
@Retention(value = RUNTIME)
2929
public @interface Produces {
3030

31-
String value();
31+
/**
32+
* Specify response media type.
33+
*
34+
* <p>When not specified the default MediaType is APPLICATION_JSON
35+
*/
36+
String value() default MediaType.APPLICATION_JSON;
37+
38+
/**
39+
* The default status code of the generated route.
40+
*
41+
* <p>When not specified, the default status are as follows: <br>
42+
* GET(200) <br>
43+
* POST(201) <br>
44+
* PUT(200, void methods 204) <br>
45+
* PATCH(200, void methods 204) <br>
46+
* DELETE(200, void methods 204)
47+
*/
48+
int defaultStatus() default 0;
3249
}

http-generator-core/src/main/java/io/avaje/http/generator/core/MethodReader.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class MethodReader {
3434
* Holds enum Roles that are required for the method.
3535
*/
3636
private final List<String> methodRoles;
37-
private final String produces;
37+
private final Optional<Produces> producesAnnotation;
3838
private final List<OpenAPIResponse> apiResponses;
3939
private final ExecutableType actualExecutable;
4040
private final List<? extends TypeMirror> actualParams;
@@ -54,7 +54,7 @@ public class MethodReader {
5454
this.actualParams = (actualExecutable == null) ? null : actualExecutable.getParameterTypes();
5555
this.isVoid = element.getReturnType().getKind() == TypeKind.VOID;
5656
this.methodRoles = Util.findRoles(element);
57-
this.produces = produces(bean);
57+
this.producesAnnotation = Optional.ofNullable(findAnnotation(Produces.class));
5858
initWebMethodViaAnnotation();
5959

6060
this.superMethods = ctx.superMethods(element.getEnclosingElement(), element.getSimpleName().toString());
@@ -151,11 +151,6 @@ public Javadoc javadoc() {
151151
return javadoc;
152152
}
153153

154-
private String produces(ControllerReader bean) {
155-
final var produces = findAnnotation(Produces.class);
156-
return (produces != null) ? produces.value() : bean.produces();
157-
}
158-
159154
private List<OpenAPIResponse> buildApiResponses() {
160155
final var container =
161156
Optional.ofNullable(findAnnotation(OpenAPIResponses.class)).stream()
@@ -275,8 +270,12 @@ public boolean isVoid() {
275270
return isVoid;
276271
}
277272

273+
public boolean hasProducesStatus() {
274+
return producesAnnotation.map(Produces::defaultStatus).filter(s -> s > 0).isPresent();
275+
}
276+
278277
public String produces() {
279-
return produces;
278+
return producesAnnotation.map(Produces::value).orElseGet(bean::produces);
280279
}
281280

282281
public List<OpenAPIResponse> apiResponses() {
@@ -291,7 +290,11 @@ public TypeMirror returnType() {
291290
}
292291

293292
public String statusCode() {
294-
return Integer.toString(webMethod.statusCode(isVoid));
293+
294+
return producesAnnotation
295+
.map(Produces::defaultStatus)
296+
.filter(s -> s > 0)
297+
.orElseGet(() -> webMethod.statusCode(isVoid)).toString();
295298
}
296299

297300
public PathSegments pathSegments() {

http-generator-core/src/main/java/io/avaje/http/generator/core/openapi/MethodDocBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public void build() {
7777
response.setDescription(javadoc.getReturnDescription());
7878

7979
final var produces = methodReader.produces();
80+
final var hasProducesStatus = methodReader.hasProducesStatus();
8081
final var contentMediaType = (produces == null) ? MediaType.APPLICATION_JSON : produces;
8182

8283
if (methodReader.isVoid()) {
@@ -99,7 +100,7 @@ public void build() {
99100
// if user wants to define their own 2xx status code
100101
if (responseAnnotation.responseCode().startsWith("2")) {
101102
newResponse.setContent(response.getContent());
102-
override2xx = true;
103+
override2xx = !hasProducesStatus;
103104
}
104105
TypeMirror returnType = null;
105106
try {

tests/test-javalin-jsonb/src/main/java/org/example/myapp/web/test/OpenAPIController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.avaje.http.api.Path;
1111
import io.avaje.http.api.Post;
1212
import io.avaje.http.api.Produces;
13+
import io.avaje.http.api.Put;
1314
import io.javalin.http.Context;
1415
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
1516
import io.swagger.v3.oas.annotations.info.Info;
@@ -78,4 +79,17 @@ Person testPostl(List<Person> m) {
7879

7980
return new Person(0, "baby");
8081
}
82+
83+
@Put("/put")
84+
@Produces(value = MediaType.TEXT_PLAIN, defaultStatus = 203)
85+
@OpenAPIResponse(responseCode = "204", type = String.class)
86+
String testDefaultStatus(Context ctx) {
87+
88+
if (ctx.contentType().equals(MediaType.APPLICATION_PDF)) {
89+
ctx.status(204);
90+
return "";
91+
}
92+
93+
return "only partial info";
94+
}
8195
}

tests/test-javalin-jsonb/src/test/resources/expectedOpenApi.json

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,39 @@
132132
},
133133
"deprecated": true
134134
}
135-
}
136-
},
135+
},
136+
"/openapi/put" : {
137+
"put" : {
138+
"tags" : [
139+
140+
],
141+
"summary" : "",
142+
"description" : "",
143+
"responses" : {
144+
"204" : {
145+
"description" : "",
146+
"content" : {
147+
"text/plain" : {
148+
"schema" : {
149+
"type" : "string"
150+
}
151+
}
152+
}
153+
},
154+
"203" : {
155+
"description" : "",
156+
"content" : {
157+
"text/plain" : {
158+
"schema" : {
159+
"type" : "string"
160+
}
161+
}
162+
}
163+
}
164+
}
165+
}
166+
}
167+
},
137168
"components": {
138169
"schemas": {
139170
"ErrorResponse": {

0 commit comments

Comments
 (0)