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 34cda7ab8 [SCB-2856]ApiImplicitParams works in class annotation (#4208)
34cda7ab8 is described below

commit 34cda7ab8fdbee9e505acc3195ed7388d09a20bd
Author: liubao68 <[email protected]>
AuthorDate: Mon Jan 29 14:27:38 2024 +0800

    [SCB-2856]ApiImplicitParams works in class annotation (#4208)
---
 .../client/TestApiImplicitParamsSchema.java        |  63 +++++++++++++
 .../springmvc/server/ApiImplicitParamsSchema.java  |  42 +++++++++
 .../springmvc/server/ProducerTestsAfterBootup.java |   6 +-
 .../generator/core/AbstractOperationGenerator.java | 105 ++++++++++++---------
 4 files changed, 167 insertions(+), 49 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
new file mode 100644
index 000000000..a1ad60265
--- /dev/null
+++ 
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestApiImplicitParamsSchema.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.demo.springmvc.client;
+
+import java.net.URI;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.RequestEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestOperations;
+
+@Component
+public class TestApiImplicitParamsSchema implements CategorizedTestCase {
+  private RestOperations restOperations = RestTemplateBuilder.create();
+
+  @Override
+  public void testRestTransport() throws Exception {
+    // 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"));
+    String result = restOperations.exchange(entity, String.class).getBody();
+    TestMgr.check("a,30,3", result);
+
+    // test default value
+    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"));
+    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");
+    } catch (InvocationException e) {
+      TestMgr.check(e.getStatusCode(), 400);
+    }
+  }
+}
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
new file mode 100644
index 000000000..9e7a63e40
--- /dev/null
+++ 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ApiImplicitParamsSchema.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.demo.springmvc.server;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+
+@RestSchema(schemaId = "ApiImplicitParamsSchema")
+@RequestMapping(path = "/implicit", produces = 
MediaType.APPLICATION_JSON_VALUE)
+@ApiImplicitParams({
+    @ApiImplicitParam(name = "x-test-a", paramType = "header", dataType = 
"string", defaultValue = "test"),
+    @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) {
+    return request.getHeader("x-test-a") + "," + request.getHeader("x-test-b") 
+ "," +
+        (a + b);
+  }
+}
diff --git 
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
index 172817164..a23cad0ff 100644
--- 
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
+++ 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
@@ -26,9 +26,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
-import com.netflix.config.DynamicPropertyFactory;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectWriter;
+import com.netflix.config.DynamicPropertyFactory;
 
 import io.swagger.models.Swagger;
 import io.swagger.util.Yaml;
@@ -91,9 +91,9 @@ public class ProducerTestsAfterBootup implements BootListener 
{
 
   public void testRegisteredBasePath() {
     if 
(DynamicPropertyFactory.getInstance().getBooleanProperty("servicecomb.test.vert.transport",
 true).get()) {
-      TestMgr.check(23, 
RegistrationManager.INSTANCE.getMicroservice().getPaths().size());
+      
TestMgr.check(RegistrationManager.INSTANCE.getMicroservice().getPaths().size() 
>= 23, true);
     } else {
-      TestMgr.check(25, 
RegistrationManager.INSTANCE.getMicroservice().getPaths().size());
+      
TestMgr.check(RegistrationManager.INSTANCE.getMicroservice().getPaths().size() 
>= 25, true);
     }
   }
 
diff --git 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/AbstractOperationGenerator.java
 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/AbstractOperationGenerator.java
index 302482b30..b31c91154 100644
--- 
a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/AbstractOperationGenerator.java
+++ 
b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/AbstractOperationGenerator.java
@@ -16,11 +16,50 @@
  */
 package org.apache.servicecomb.swagger.generator.core;
 
+import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.collectAnnotations;
+import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.findMethodAnnotationProcessor;
+import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.findParameterProcessors;
+import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.findResponseTypeProcessor;
+import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.isContextParameter;
+import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.postProcessOperation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.config.inject.PlaceholderResolver;
+import org.apache.servicecomb.swagger.SwaggerUtils;
+import org.apache.servicecomb.swagger.generator.MethodAnnotationProcessor;
+import org.apache.servicecomb.swagger.generator.OperationGenerator;
+import org.apache.servicecomb.swagger.generator.ParameterGenerator;
+import org.apache.servicecomb.swagger.generator.ParameterProcessor;
+import org.apache.servicecomb.swagger.generator.ResponseTypeProcessor;
+import org.apache.servicecomb.swagger.generator.SwaggerConst;
+import org.apache.servicecomb.swagger.generator.core.model.HttpParameterType;
+import org.apache.servicecomb.swagger.generator.core.utils.MethodUtils;
+
 import com.fasterxml.jackson.databind.BeanDescription;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.google.common.reflect.TypeToken;
+
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiParam;
@@ -44,42 +83,6 @@ import io.swagger.models.properties.Property;
 import io.swagger.models.properties.StringProperty;
 import io.swagger.util.Json;
 import io.swagger.util.ReflectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.servicecomb.config.inject.PlaceholderResolver;
-import org.apache.servicecomb.swagger.SwaggerUtils;
-import org.apache.servicecomb.swagger.generator.MethodAnnotationProcessor;
-import org.apache.servicecomb.swagger.generator.OperationGenerator;
-import org.apache.servicecomb.swagger.generator.ParameterGenerator;
-import org.apache.servicecomb.swagger.generator.ParameterProcessor;
-import org.apache.servicecomb.swagger.generator.ResponseTypeProcessor;
-import org.apache.servicecomb.swagger.generator.SwaggerConst;
-import org.apache.servicecomb.swagger.generator.core.model.HttpParameterType;
-import org.apache.servicecomb.swagger.generator.core.utils.MethodUtils;
-
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.MediaType;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.Comparator;
-import java.util.stream.Collectors;
-
-import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.collectAnnotations;
-import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.findMethodAnnotationProcessor;
-import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.findParameterProcessors;
-import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.findResponseTypeProcessor;
-import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.isContextParameter;
-import static 
org.apache.servicecomb.swagger.generator.SwaggerGeneratorUtils.postProcessOperation;
 
 public abstract class AbstractOperationGenerator implements OperationGenerator 
{
   protected AbstractSwaggerGenerator swaggerGenerator;
@@ -169,8 +172,8 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
 
   protected void scanMethodAnnotation() {
     for (Annotation annotation : Arrays.stream(method.getAnnotations())
-            .sorted(Comparator.comparing(a -> a.annotationType().getName()))
-            .collect(Collectors.toList())
+        .sorted(Comparator.comparing(a -> a.annotationType().getName()))
+        .collect(Collectors.toList())
     ) {
       MethodAnnotationProcessor<Annotation> processor = 
findMethodAnnotationProcessor(annotation.annotationType());
       if (processor == null) {
@@ -261,12 +264,12 @@ public abstract class AbstractOperationGenerator 
implements OperationGenerator {
   }
 
   protected boolean isAggregatedParameter(ParameterGenerator 
parameterGenerator,
-                                          java.lang.reflect.Parameter 
methodParameter) {
+      java.lang.reflect.Parameter methodParameter) {
     return false;
   }
 
   protected void extractAggregatedParameterGenerators(Map<String, 
List<Annotation>> methodAnnotationMap,
-                                                      
java.lang.reflect.Parameter methodParameter) {
+      java.lang.reflect.Parameter methodParameter) {
     JavaType javaType = 
TypeFactory.defaultInstance().constructType(methodParameter.getParameterizedType());
     BeanDescription beanDescription = 
Json.mapper().getSerializationConfig().introspect(javaType);
     for (BeanPropertyDefinition propertyDefinition : 
beanDescription.findProperties()) {
@@ -293,6 +296,16 @@ public abstract class AbstractOperationGenerator 
implements OperationGenerator {
 
   private Map<String, List<Annotation>> initMethodAnnotationByParameterName() {
     Map<String, List<Annotation>> methodAnnotations = new LinkedHashMap<>();
+
+    for (Annotation annotation : clazz.getAnnotations()) {
+      if (annotation instanceof ApiImplicitParams) {
+        for (ApiImplicitParam apiImplicitParam : ((ApiImplicitParams) 
annotation).value()) {
+          addMethodAnnotationByParameterName(methodAnnotations, 
apiImplicitParam.name(), apiImplicitParam);
+        }
+        continue;
+      }
+    }
+
     for (Annotation annotation : method.getAnnotations()) {
       if (annotation instanceof ApiImplicitParams) {
         for (ApiImplicitParam apiImplicitParam : ((ApiImplicitParams) 
annotation).value()) {
@@ -309,7 +322,7 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
   }
 
   private void addMethodAnnotationByParameterName(Map<String, 
List<Annotation>> methodAnnotations, String name,
-                                                  Annotation annotation) {
+      Annotation annotation) {
     if (StringUtils.isEmpty(name)) {
       throw new IllegalStateException(String.format("%s.name should not be 
empty. method=%s:%s",
           annotation.annotationType().getSimpleName(),
@@ -375,7 +388,7 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
   }
 
   protected void fillParameter(Swagger swagger, Parameter parameter, String 
parameterName, JavaType type,
-                               List<Annotation> annotations) {
+      List<Annotation> annotations) {
     for (Annotation annotation : annotations) {
       ParameterProcessor<Parameter, Annotation> processor = 
findParameterProcessors(annotation.annotationType());
       if (processor != null) {
@@ -395,7 +408,7 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
     if (parameter instanceof AbstractSerializableParameter) {
       io.swagger.util.ParameterProcessor.applyAnnotations(swagger, parameter, 
type, annotations);
       annotations.stream().forEach(annotation -> {
-        if 
(NOT_NULL_ANNOTATIONS.contains(annotation.annotationType().getSimpleName())){
+        if 
(NOT_NULL_ANNOTATIONS.contains(annotation.annotationType().getSimpleName())) {
           parameter.setRequired(true);
         }
       });
@@ -426,7 +439,7 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
       convertAnnotationProperty(((JavaType) type).getRawClass());
     } else {
       ((JavaType) type).getBindings().getTypeParameters().
-              forEach(javaType -> 
convertAnnotationProperty(javaType.getRawClass()));
+          forEach(javaType -> 
convertAnnotationProperty(javaType.getRawClass()));
     }
 
     mergeBodyParameter((BodyParameter) parameter, newBodyParameter);
@@ -434,7 +447,7 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
 
   private void convertAnnotationProperty(Class<?> beanClass) {
     Map<String, Model> definitions = swagger.getDefinitions();
-    if (definitions == null){
+    if (definitions == null) {
       return;
     }
     Field[] fields = beanClass.getDeclaredFields();
@@ -446,7 +459,7 @@ public abstract class AbstractOperationGenerator implements 
OperationGenerator {
     if (properties != null) {
       Arrays.stream(fields).forEach(field -> {
         boolean requireItem = Arrays.stream(field.getAnnotations()).
-                anyMatch(annotation -> 
NOT_NULL_ANNOTATIONS.contains(annotation.annotationType().getSimpleName()));
+            anyMatch(annotation -> 
NOT_NULL_ANNOTATIONS.contains(annotation.annotationType().getSimpleName()));
         if (requireItem) {
           Property property = properties.get(field.getName());
           if (property != null) {

Reply via email to