Skip to content

Commit bbc37c4

Browse files
author
Rudolf Grauberger
committed
Improves the @ResponseStatus handling
1 parent 940f8e5 commit bbc37c4

File tree

6 files changed

+487
-10
lines changed

6 files changed

+487
-10
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/GenericResponseService.java

+16-10
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,11 @@ private void buildGenericApiResponses(Components components, MethodParameter met
356356
// Use response parameters with no description filled - No documentation
357357
// available
358358
String httpCode = evaluateResponseStatus(methodParameter.getMethod(), Objects.requireNonNull(methodParameter.getMethod()).getClass(), true);
359-
ApiResponse apiResponse = methodAttributes.getGenericMapResponse().containsKey(httpCode) ? methodAttributes.getGenericMapResponse().get(httpCode)
360-
: new ApiResponse();
361-
if (httpCode != null)
359+
if (Objects.nonNull(httpCode)) {
360+
ApiResponse apiResponse = methodAttributes.getGenericMapResponse().containsKey(httpCode) ? methodAttributes.getGenericMapResponse().get(httpCode)
361+
: new ApiResponse();
362362
buildApiResponses(components, methodParameter, apiResponsesOp, methodAttributes, httpCode, apiResponse, true);
363+
}
363364
}
364365
}
365366

@@ -384,14 +385,19 @@ private void buildApiResponses(Components components, MethodParameter methodPara
384385
buildApiResponses(components, methodParameter, apiResponsesOp, methodAttributes, httpCode, apiResponse, false);
385386
}
386387
}
387-
}
388-
else {
389-
// Use response parameters with no description filled - No documentation
390-
// available
388+
389+
if (AnnotatedElementUtils.hasAnnotation(methodParameter.getMethod(), ResponseStatus.class)) {
390+
// Handles the case with @ResponseStatus, if the specified response is not already handled explicitly
391+
String httpCode = evaluateResponseStatus(methodParameter.getMethod(), Objects.requireNonNull(methodParameter.getMethod()).getClass(), false);
392+
if (Objects.nonNull(httpCode) && !apiResponsesOp.containsKey(httpCode) && !apiResponsesOp.containsKey(ApiResponses.DEFAULT)) {
393+
buildApiResponses(components, methodParameter, apiResponsesOp, methodAttributes, httpCode, new ApiResponse(), false);
394+
}
395+
}
396+
397+
} else {
391398
String httpCode = evaluateResponseStatus(methodParameter.getMethod(), Objects.requireNonNull(methodParameter.getMethod()).getClass(), false);
392-
ApiResponse apiResponse = new ApiResponse();
393-
if (httpCode != null)
394-
buildApiResponses(components, methodParameter, apiResponsesOp, methodAttributes, httpCode, apiResponse, false);
399+
if (Objects.nonNull(httpCode))
400+
buildApiResponses(components, methodParameter, apiResponsesOp, methodAttributes, httpCode, new ApiResponse(), false);
395401
}
396402
}
397403

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v30.app192;
24+
25+
public class ErrorResponse {
26+
Object data = null;
27+
String message;
28+
Object pageable = null;
29+
30+
public ErrorResponse(String message) {
31+
this.message = message;
32+
}
33+
34+
public Object getData() {
35+
return data;
36+
}
37+
38+
public String getMessage() {
39+
return message;
40+
}
41+
42+
public Object getPageable() {
43+
return pageable;
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v30.app192;
24+
25+
import io.swagger.v3.oas.annotations.Operation;
26+
import io.swagger.v3.oas.annotations.media.Content;
27+
import io.swagger.v3.oas.annotations.media.Schema;
28+
import io.swagger.v3.oas.annotations.parameters.RequestBody;
29+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
30+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
31+
import org.springframework.http.HttpStatus;
32+
import org.springframework.http.MediaType;
33+
import org.springframework.http.ResponseEntity;
34+
import org.springframework.web.bind.annotation.GetMapping;
35+
import org.springframework.web.bind.annotation.PostMapping;
36+
import org.springframework.web.bind.annotation.ResponseStatus;
37+
import org.springframework.web.bind.annotation.RestController;
38+
39+
@RestController
40+
public class HelloController {
41+
@Operation(description = "Adds 200 as api response, because there are nothing defined to get another response")
42+
@RequestBody(description = "test value", required = true, content = @Content(schema = @Schema(implementation = String.class)))
43+
@PostMapping(value = "/postWithoutAnyResponse", produces = MediaType.APPLICATION_JSON_VALUE)
44+
public void postWithoutAnyResponse(String test) {}
45+
46+
@Operation(description = "Adds 201 as api response, because it defined by @ResponseStatus")
47+
@PostMapping(value = "/postWithResponseStatusOnly", produces = MediaType.APPLICATION_JSON_VALUE)
48+
@ResponseStatus(value = HttpStatus.CREATED)
49+
public ResponseEntity<String> postWithResponseStatusOnly() {
50+
return ResponseEntity.ok("hello");
51+
}
52+
53+
@Operation(description = "Adds 200 as additional api response, because it defined by @ResponseStatus",
54+
responses = {
55+
@ApiResponse(responseCode = "422", description = "Test")
56+
})
57+
@ApiResponses({
58+
@ApiResponse(responseCode = "409", description = "Test 2")
59+
})
60+
@GetMapping(value = "/withResponseStatus", produces = MediaType.APPLICATION_JSON_VALUE)
61+
@ResponseStatus(value = HttpStatus.OK)
62+
public ResponseEntity<String> withResponseStatus() {
63+
return ResponseEntity.ok("hello");
64+
}
65+
66+
@Operation(description = "Adds 200 as api response, because it defined by @ResponseStatus")
67+
@GetMapping(value = "/withResponseStatusOnly", produces = MediaType.APPLICATION_JSON_VALUE)
68+
@ResponseStatus(value = HttpStatus.OK)
69+
public ResponseEntity<String> withResponseStatusOnly() {
70+
return ResponseEntity.ok("hello");
71+
}
72+
73+
@Operation(description = "Doesn't creates the default 200 Response, because there are explicit declared api responses." +
74+
"This test ensures that the current default handling is not changed, because otherwise very many tests will fail.",
75+
responses = {
76+
@ApiResponse(responseCode = "422", description = "Test")
77+
})
78+
@ApiResponses({
79+
@ApiResponse(responseCode = "409", description = "Test 2") })
80+
@GetMapping(value = "/withoutResponseStatus", produces = MediaType.APPLICATION_JSON_VALUE)
81+
public ResponseEntity<String> withoutResponseStatus() {
82+
return ResponseEntity.ok("hello");
83+
}
84+
85+
86+
@Operation(description = "Results in the default handling like before")
87+
@GetMapping(value = "/withoutAnyResponseInformation", produces = MediaType.APPLICATION_JSON_VALUE)
88+
public ResponseEntity<String> withoutAnyResponseInformation() {
89+
return ResponseEntity.ok("hello");
90+
}
91+
92+
@Operation(description = "Overwrites the 200 @ResponseStatus-Information by the explicit declared @ApiResponse",
93+
responses = {
94+
@ApiResponse(responseCode = "200", description = "Test2", content = @Content),
95+
@ApiResponse(responseCode = "422", description = "Test")
96+
})
97+
@ApiResponses({
98+
@ApiResponse(responseCode = "409", description = "Test 2")
99+
})
100+
@GetMapping(value = "/overwrite200InOperation", produces = MediaType.APPLICATION_JSON_VALUE)
101+
@ResponseStatus(value = HttpStatus.OK)
102+
public ResponseEntity<String> overwrite200InOperation() {
103+
return ResponseEntity.ok("hello");
104+
}
105+
106+
@Operation(description = "Overwrites the 200 @ResponseStatus-Information by the explicit declared @ApiResponse",
107+
responses = {
108+
@ApiResponse(responseCode = "422", description = "Test")
109+
})
110+
@ApiResponses({
111+
@ApiResponse(responseCode = "200", description = "Test2", content = @Content),
112+
@ApiResponse(responseCode = "409", description = "Test 2")
113+
})
114+
@GetMapping(value = "/overwrite200InDoc", produces = MediaType.APPLICATION_JSON_VALUE)
115+
@ResponseStatus(value = HttpStatus.OK)
116+
public ResponseEntity<String> overwrite200InDoc() {
117+
return ResponseEntity.ok("hello");
118+
}
119+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v30.app192;
24+
25+
26+
import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
27+
28+
29+
public class SpringDocApp192Test extends AbstractSpringDocV30Test { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v30.app192;
24+
25+
import org.springframework.boot.SpringApplication;
26+
import org.springframework.boot.autoconfigure.SpringBootApplication;
27+
28+
@SpringBootApplication
29+
public class SpringDocTestApp {
30+
31+
public static void main(String[] args) {
32+
SpringApplication.run(SpringDocTestApp.class, args);
33+
}
34+
}

0 commit comments

Comments
 (0)