This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch 2.8.x
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/2.8.x by this push:
new c8499efb5 [SCB-2859]able to use wrapper class to serialize requests
for primiti… (#4227)
c8499efb5 is described below
commit c8499efb5facd83ef03ba380147438b2418e87c1
Author: liubao68 <[email protected]>
AuthorDate: Sun Feb 4 10:56:30 2024 +0800
[SCB-2859]able to use wrapper class to serialize requests for primiti…
(#4227)
---
.../client/TestApiImplicitParamsSchema.java | 34 +++++++++++++++---
.../springmvc/server/ApiImplicitParamsSchema.java | 14 ++++++--
.../producer/ProducerArgumentsMapperCreator.java | 40 ++++++++++++++++++++--
3 files changed, 78 insertions(+), 10 deletions(-)
diff --git
a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestApiImplicitParamsSchema.java
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestApiImplicitParamsSchema.java
index a1ad60265..b4457b0ed 100644
---
a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestApiImplicitParamsSchema.java
+++
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestApiImplicitParamsSchema.java
@@ -17,6 +17,7 @@
package org.apache.servicecomb.demo.springmvc.client;
import java.net.URI;
+import java.net.URISyntaxException;
import org.apache.servicecomb.demo.CategorizedTestCase;
import org.apache.servicecomb.demo.TestMgr;
@@ -31,16 +32,37 @@ import org.springframework.web.client.RestOperations;
@Component
public class TestApiImplicitParamsSchema implements CategorizedTestCase {
- private RestOperations restOperations = RestTemplateBuilder.create();
+ private final RestOperations restOperations = RestTemplateBuilder.create();
@Override
public void testRestTransport() throws Exception {
+ testImplicitAndExplicitParam();
+ testIntegerTypeValidation();
+ }
+
+ private void testIntegerTypeValidation() throws URISyntaxException {
+ MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
+ headers.add("x-test-a", "a");
+ headers.add("x-test-b", "30");
+ headers.add("x-test-c", "x"); // invalid integer for object-mapper.
+ RequestEntity<?> entity = new RequestEntity<>(headers, HttpMethod.GET,
+ new URI("servicecomb://springmvc/implicit/testIntegerTypeValidation"));
+ try {
+ String result = restOperations.exchange(entity, String.class).getBody();
+ TestMgr.check(result, "do not have integer type check");
+ } catch (InvocationException e) {
+ TestMgr.check(e.getStatusCode(), 400);
+ TestMgr.check(e.getMessage().contains("x-test-c"), true);
+ }
+ }
+
+ private void testImplicitAndExplicitParam() throws URISyntaxException {
// test all parameters case
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add("x-test-a", "a");
headers.add("x-test-b", "30");
RequestEntity<?> entity = new RequestEntity<>(headers, HttpMethod.GET,
- new URI("servicecomb://springmvc/implicit/add?a=1&b=2"));
+ new
URI("servicecomb://springmvc/implicit/testImplicitAndExplicitParam?a=1&b=2"));
String result = restOperations.exchange(entity, String.class).getBody();
TestMgr.check("a,30,3", result);
@@ -48,16 +70,18 @@ public class TestApiImplicitParamsSchema implements
CategorizedTestCase {
headers = new LinkedMultiValueMap<>();
headers.add("x-test-b", "10");
entity = new RequestEntity<>(headers, HttpMethod.GET,
- new URI("servicecomb://springmvc/implicit/add?a=1&b=2"));
+ new
URI("servicecomb://springmvc/implicit/testImplicitAndExplicitParam?a=1&b=2"));
result = restOperations.exchange(entity, String.class).getBody();
TestMgr.check("test,10,3", result);
// test default required check
try {
-
restOperations.getForObject("servicecomb://springmvc/implicit/add?a=1&b=2",
String.class);
- TestMgr.fail("do not have required check");
+ result =
restOperations.getForObject("servicecomb://springmvc/implicit/testImplicitAndExplicitParam?a=1&b=2",
+ String.class);
+ TestMgr.check(result, "do not have required check");
} catch (InvocationException e) {
TestMgr.check(e.getStatusCode(), 400);
+ TestMgr.check(e.getMessage().contains("x-test-b"), true);
}
}
}
diff --git
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ApiImplicitParamsSchema.java
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ApiImplicitParamsSchema.java
index 9e7a63e40..82aef9358 100644
---
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ApiImplicitParamsSchema.java
+++
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ApiImplicitParamsSchema.java
@@ -34,9 +34,19 @@ import io.swagger.annotations.ApiImplicitParams;
@ApiImplicitParam(name = "x-test-b", paramType = "header", dataType =
"integer", defaultValue = "20", required = true)
})
public class ApiImplicitParamsSchema {
- @GetMapping(path = "/add")
- public String add(HttpServletRequest request, @RequestParam("a") int a,
@RequestParam("b") int b) {
+ @GetMapping(path = "/testImplicitAndExplicitParam")
+ public String testImplicitAndExplicitParam(HttpServletRequest request,
+ @RequestParam("a") int a, @RequestParam("b") int b) {
return request.getHeader("x-test-a") + "," + request.getHeader("x-test-b")
+ "," +
(a + b);
}
+
+ @GetMapping(path = "/testIntegerTypeValidation")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "x-test-c", paramType = "header", dataType =
"integer")
+ })
+ public String testIntegerTypeValidation(HttpServletRequest request) {
+ return request.getHeader("x-test-a") + "," + request.getHeader("x-test-b")
+ "," +
+ request.getHeader("x-test-c");
+ }
}
diff --git
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperCreator.java
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperCreator.java
index 1af538154..1aa3a2251 100644
---
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperCreator.java
+++
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperCreator.java
@@ -37,8 +37,16 @@ import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.google.common.reflect.TypeToken;
+import com.netflix.config.DynamicPropertyFactory;
+
+import io.swagger.models.parameters.SerializableParameter;
public class ProducerArgumentsMapperCreator extends
AbstractArgumentsMapperCreator {
+ // using swagger type instead of method type for primitive method types when
deserialize
+ // query/header/etc. parameters.
+ private final boolean useWrapperTypeForPrimitives =
DynamicPropertyFactory.getInstance()
+
.getBooleanProperty("servicecomb.rest.parameter.useWrapperTypeForPrimitives",
false).get();
+
// swagger parameter types relate to producer
// because features of @BeanParam/query, and rpc mode parameter wrapper
// types is not always equals to producerMethod parameter types directly
@@ -71,7 +79,7 @@ public class ProducerArgumentsMapperCreator extends
AbstractArgumentsMapperCreat
@Override
protected void
processPendingSwaggerParameter(io.swagger.models.parameters.Parameter
parameter) {
- swaggerParameterTypes.put(parameter.getName(), Object.class);
+ swaggerParameterTypes.put(parameter.getName(), swaggerTypes(parameter,
Object.class));
}
@Override
@@ -80,11 +88,37 @@ public class ProducerArgumentsMapperCreator extends
AbstractArgumentsMapperCreat
Type providerType = TypeToken.of(providerClass)
.resolveType(providerMethod.getGenericParameterTypes()[providerParamIdx])
.getType();
- swaggerParameterTypes
- .put(swaggerArgumentName, providerType);
+ if (useWrapperTypeForPrimitives && providerType instanceof Class<?> &&
((Class<?>) providerType).isPrimitive()) {
+ // add swagger type to java type
+ providerType = swaggerTypes(swaggerParameters.get(swaggerIdx),
providerType);
+ }
+ swaggerParameterTypes.put(swaggerArgumentName, providerType);
return new
ProducerArgumentSame(providerMethod.getParameters()[providerParamIdx].getName(),
swaggerArgumentName);
}
+ private Type swaggerTypes(io.swagger.models.parameters.Parameter parameter,
Type defaultType) {
+ if (!(parameter instanceof SerializableParameter)) {
+ return defaultType;
+ }
+ SerializableParameter serializableParameter = (SerializableParameter)
parameter;
+ switch (serializableParameter.getType()) {
+ case "integer":
+ if ("int64".equalsIgnoreCase(serializableParameter.getFormat())) {
+ return Long.class;
+ }
+ return Integer.class;
+ case "number":
+ if ("double".equalsIgnoreCase(serializableParameter.getFormat())) {
+ return Double.class;
+ }
+ return Float.class;
+ case "boolean":
+ return Boolean.class;
+ default:
+ return defaultType;
+ }
+ }
+
@Override
protected ArgumentMapper createSwaggerBodyFieldMapper(int producerParamIdx,
String parameterName,
int swaggerBodyIdx) {