Skip to content

Commit 7bccc8c

Browse files
committed
use custom annotation
1 parent 5a1d8d4 commit 7bccc8c

File tree

4 files changed

+84
-9
lines changed

4 files changed

+84
-9
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.avaje.http.api;
2+
3+
import static java.lang.annotation.ElementType.METHOD;
4+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5+
6+
import java.lang.annotation.Repeatable;
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Specify endpoint response status code/description/type.
12+
*
13+
* <p>When not specified the default 2xx openAPI generation is based on the javadoc of the method.
14+
* <p> Will not override the default 2xx generated openapi unless status code is 2xx
15+
* <pre>{@code
16+
* @Post("/post")
17+
* @OpenAPIReturns(responseCode = "200", description = "from annotaion")
18+
* @OpenAPIReturns(responseCode = "201")
19+
* @OpenAPIReturns(responseCode = "500", description = "Some other Error", type=ErrorResponse.class)
20+
* ResponseModel endpoint() {}
21+
*
22+
* }</pre>
23+
*/
24+
@Target(value = METHOD)
25+
@Retention(value = RUNTIME)
26+
@Repeatable(OpenAPIReturnsContainer.class)
27+
public @interface OpenAPIReturns {
28+
29+
/** the http status code of this response */
30+
String responseCode();
31+
32+
/**
33+
* The description of the return value. By default uses the @return javadoc of the method as the
34+
* description
35+
*/
36+
String description() default "";
37+
38+
/**
39+
* The concrete type that that this endpoint returns. If status code is a 2xx code it will default
40+
* to the return type of the method
41+
*/
42+
Class<?> type() default Void.class;
43+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.avaje.http.api;
2+
3+
import static java.lang.annotation.ElementType.METHOD;
4+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5+
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.Target;
8+
9+
@Target(value = METHOD)
10+
@Retention(value = RUNTIME)
11+
public @interface OpenAPIReturnsContainer {
12+
OpenAPIReturns[] value();
13+
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.avaje.http.api.Delete;
1616
import io.avaje.http.api.Form;
1717
import io.avaje.http.api.Get;
18+
import io.avaje.http.api.OpenAPIReturns;
1819
import io.avaje.http.api.Patch;
1920
import io.avaje.http.api.Post;
2021
import io.avaje.http.api.Produces;
@@ -48,7 +49,7 @@ public class MethodReader {
4849

4950
private final String produces;
5051

51-
private final ApiResponse[] apiResponses;
52+
private final OpenAPIReturns[] apiResponses;
5253

5354
private final ExecutableType actualExecutable;
5455
private final List<? extends TypeMirror> actualParams;
@@ -131,8 +132,8 @@ private String produces(ControllerReader bean) {
131132
return (produces != null) ? produces.value() : bean.produces();
132133
}
133134

134-
private ApiResponse[] getApiResponses() {
135-
return element.getAnnotationsByType(ApiResponse.class);
135+
private OpenAPIReturns[] getApiResponses() {
136+
return element.getAnnotationsByType(OpenAPIReturns.class);
136137
}
137138

138139
public <A extends Annotation> A findAnnotation(Class<A> type) {
@@ -229,7 +230,7 @@ public String produces() {
229230
return produces;
230231
}
231232

232-
public ApiResponse[] apiResponses() {
233+
public OpenAPIReturns[] apiResponses() {
233234
return apiResponses;
234235
}
235236

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

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.avaje.http.generator.core.openapi;
22

3+
import javax.lang.model.type.MirroredTypeException;
4+
import javax.lang.model.type.TypeMirror;
5+
36
import io.avaje.http.api.MediaType;
47
import io.avaje.http.generator.core.MethodParam;
58
import io.avaje.http.generator.core.MethodReader;
@@ -73,28 +76,43 @@ public void build() {
7376
ApiResponse response = new ApiResponse();
7477
response.setDescription(javadoc.getReturnDescription());
7578

79+
final var produces = methodReader.produces();
80+
final var contentMediaType = (produces == null) ? MediaType.APPLICATION_JSON : produces;
81+
7682
if (methodReader.isVoid()) {
7783
if (isEmpty(response.getDescription())) {
7884
response.setDescription("No content");
7985
}
8086
} else {
81-
final String produces = methodReader.produces();
82-
String contentMediaType = (produces == null) ? MediaType.APPLICATION_JSON : produces;
83-
response.setContent(ctx.createContent(methodReader.returnType(), contentMediaType));
87+
response.setContent(ctx.createContent(methodReader.returnType(), contentMediaType));
8488
}
8589
var override2xx = false;
8690
for (final var responseAnnotation : methodReader.apiResponses()) {
8791
final var newResponse = new ApiResponse();
8892

89-
if (responseAnnotation.description().isEmpty())
93+
if (responseAnnotation.description().isEmpty()) {
9094
newResponse.setDescription(response.getDescription());
91-
else newResponse.setDescription(responseAnnotation.description());
95+
} else {
96+
newResponse.setDescription(responseAnnotation.description());
97+
}
9298

9399
// if user wants to define their own 2xx status code
94100
if (responseAnnotation.responseCode().startsWith("2")) {
95101
newResponse.setContent(response.getContent());
96102
override2xx = true;
97103
}
104+
TypeMirror returnType = null;
105+
try {
106+
// this will always throw
107+
responseAnnotation.type();
108+
} catch (final MirroredTypeException mte) {
109+
returnType = mte.getTypeMirror();
110+
}
111+
112+
if (!"java.lang.Void".equals(returnType.toString())) {
113+
newResponse.setContent(ctx.createContent(returnType, contentMediaType));
114+
}
115+
98116
responses.addApiResponse(responseAnnotation.responseCode(), newResponse);
99117
}
100118
if (!override2xx) responses.addApiResponse(methodReader.statusCode(), response);

0 commit comments

Comments
 (0)