Skip to content

Commit 6ce3b5a

Browse files
committed
Missing Request Body for Write Operation Actuator Endpoints. Fixes #1565.
1 parent b7721b6 commit 6ce3b5a

File tree

7 files changed

+154
-1
lines changed

7 files changed

+154
-1
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/core/customizers/ActuatorOperationCustomizer.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,27 @@
2323

2424
package org.springdoc.core.customizers;
2525

26+
import java.lang.reflect.Field;
27+
import java.lang.reflect.Parameter;
2628
import java.util.HashMap;
2729
import java.util.regex.Matcher;
2830
import java.util.regex.Pattern;
2931

32+
import io.swagger.v3.core.util.AnnotationsUtils;
3033
import io.swagger.v3.oas.models.Operation;
34+
import io.swagger.v3.oas.models.media.Content;
35+
import io.swagger.v3.oas.models.media.MediaType;
36+
import io.swagger.v3.oas.models.media.Schema;
37+
import io.swagger.v3.oas.models.parameters.RequestBody;
38+
import org.apache.commons.lang3.reflect.FieldUtils;
39+
import org.slf4j.Logger;
40+
import org.slf4j.LoggerFactory;
3141

42+
import org.springframework.boot.actuate.endpoint.OperationType;
43+
import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation;
44+
import org.springframework.boot.actuate.endpoint.annotation.Selector;
45+
import org.springframework.boot.actuate.endpoint.invoke.OperationParameter;
46+
import org.springframework.boot.actuate.endpoint.invoke.reflect.OperationMethod;
3247
import org.springframework.web.method.HandlerMethod;
3348

3449
import static org.apache.commons.lang3.math.NumberUtils.INTEGER_ONE;
@@ -45,6 +60,11 @@ public class ActuatorOperationCustomizer implements OperationCustomizer {
4560
*/
4661
private HashMap<String, Integer> methodCountMap = new HashMap<>();
4762

63+
private static final String OPERATION = "operation";
64+
65+
private static final String PARAMETER = "parameter";
66+
67+
private static final Logger LOGGER = LoggerFactory.getLogger(ActuatorOperationCustomizer.class);
4868

4969
/**
5070
* The regex pattern for operationId lookup.
@@ -54,14 +74,39 @@ public class ActuatorOperationCustomizer implements OperationCustomizer {
5474
@Override
5575
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
5676
if (operation.getTags() != null && operation.getTags().contains(getTag().getName())) {
77+
Field operationFiled = FieldUtils.getDeclaredField(handlerMethod.getBean().getClass(), OPERATION, true);
78+
Object actuatorOperation;
79+
if (operationFiled != null) {
80+
try {
81+
actuatorOperation = operationFiled.get(handlerMethod.getBean());
82+
operationFiled = FieldUtils.getDeclaredField(actuatorOperation.getClass(), OPERATION, true);
83+
AbstractDiscoveredOperation discoveredOperation = (AbstractDiscoveredOperation) operationFiled.get(actuatorOperation);
84+
OperationMethod operationMethod = discoveredOperation.getOperationMethod();
85+
if (OperationType.WRITE.equals(operationMethod.getOperationType())) {
86+
for (OperationParameter operationParameter : operationMethod.getParameters()) {
87+
Field parameterField = FieldUtils.getDeclaredField(operationParameter.getClass(), PARAMETER, true);
88+
Parameter parameter = (Parameter) parameterField.get(operationParameter);
89+
Schema<?> schema = AnnotationsUtils.resolveSchemaFromType(parameter.getType(), null, null);
90+
if (parameter.getAnnotation(Selector.class) == null) {
91+
operation.setRequestBody(new RequestBody()
92+
.content(new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, new MediaType().schema(schema))));
93+
}
94+
}
95+
}
96+
}
97+
catch (IllegalAccessException e) {
98+
LOGGER.warn(e.getMessage());
99+
}
100+
}
101+
57102
String summary = handlerMethod.toString();
58103
Matcher matcher = pattern.matcher(summary);
59104
String operationId = operation.getOperationId();
60105
while (matcher.find()) {
61106
operationId = matcher.group(1);
62107
}
63108
if (methodCountMap.containsKey(operationId)) {
64-
Integer methodCount = methodCountMap.get(operationId)+1;
109+
Integer methodCount = methodCountMap.get(operationId) + 1;
65110
methodCountMap.put(operationId, methodCount);
66111
operationId = operationId + "_" + methodCount;
67112
}

springdoc-openapi-webflux-core/src/test/resources/results/app146-1.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@
7575
}
7676
}
7777
],
78+
"requestBody": {
79+
"content": {
80+
"application/json": {
81+
"schema": {
82+
"type": "string",
83+
"enum": [
84+
"TRACE",
85+
"DEBUG",
86+
"INFO",
87+
"WARN",
88+
"ERROR",
89+
"FATAL",
90+
"OFF"
91+
]
92+
}
93+
}
94+
}
95+
},
7896
"responses": {
7997
"200": {
8098
"description": "OK",

springdoc-openapi-webflux-core/src/test/resources/results/app147-1.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@
7575
}
7676
}
7777
],
78+
"requestBody": {
79+
"content": {
80+
"application/json": {
81+
"schema": {
82+
"type": "string",
83+
"enum": [
84+
"TRACE",
85+
"DEBUG",
86+
"INFO",
87+
"WARN",
88+
"ERROR",
89+
"FATAL",
90+
"OFF"
91+
]
92+
}
93+
}
94+
}
95+
},
7896
"responses": {
7997
"200": {
8098
"description": "OK",

springdoc-openapi-webflux-core/src/test/resources/results/app148-2.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@
7575
}
7676
}
7777
],
78+
"requestBody": {
79+
"content": {
80+
"application/json": {
81+
"schema": {
82+
"type": "string",
83+
"enum": [
84+
"TRACE",
85+
"DEBUG",
86+
"INFO",
87+
"WARN",
88+
"ERROR",
89+
"FATAL",
90+
"OFF"
91+
]
92+
}
93+
}
94+
}
95+
},
7896
"responses": {
7997
"200": {
8098
"description": "OK",

springdoc-openapi-webmvc-core/src/test/resources/results/app146-1.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@
7777
}
7878
}
7979
],
80+
"requestBody": {
81+
"content": {
82+
"application/json": {
83+
"schema": {
84+
"type": "string",
85+
"enum": [
86+
"TRACE",
87+
"DEBUG",
88+
"INFO",
89+
"WARN",
90+
"ERROR",
91+
"FATAL",
92+
"OFF"
93+
]
94+
}
95+
}
96+
}
97+
},
8098
"responses": {
8199
"200": {
82100
"description": "OK",

springdoc-openapi-webmvc-core/src/test/resources/results/app147-1.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@
7777
}
7878
}
7979
],
80+
"requestBody": {
81+
"content": {
82+
"application/json": {
83+
"schema": {
84+
"type": "string",
85+
"enum": [
86+
"TRACE",
87+
"DEBUG",
88+
"INFO",
89+
"WARN",
90+
"ERROR",
91+
"FATAL",
92+
"OFF"
93+
]
94+
}
95+
}
96+
}
97+
},
8098
"responses": {
8199
"200": {
82100
"description": "OK",

springdoc-openapi-webmvc-core/src/test/resources/results/app148-2.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@
7777
}
7878
}
7979
],
80+
"requestBody": {
81+
"content": {
82+
"application/json": {
83+
"schema": {
84+
"type": "string",
85+
"enum": [
86+
"TRACE",
87+
"DEBUG",
88+
"INFO",
89+
"WARN",
90+
"ERROR",
91+
"FATAL",
92+
"OFF"
93+
]
94+
}
95+
}
96+
}
97+
},
8098
"responses": {
8199
"200": {
82100
"description": "OK",

0 commit comments

Comments
 (0)