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) {

Reply via email to