You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/09/19 06:43:39 UTC

[incubator-servicecomb-java-chassis] branch master updated (4dbc83a -> c019638)

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git.


    from 4dbc83a  [SCB-905] GlobalRestFailureHandler handle InvocationException properly
     new 6cd13bb  [SCB-215] process parameter level @ApiParam
     new c019638  [SCB-215] add IT for ApiParam

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/servicecomb/it/schema/CommonModel.java  |  15 ++-
 .../org/apache/servicecomb/it/ConsumerMain.java    |   2 +
 .../it/schema/ApiParamJaxrsSchema.java}            |  51 +++++----
 .../servicecomb/it/schema/ApiParamPojoSchema.java} |  19 ++--
 .../it/schema/ApiParamSpringmvcSchema.java         |  69 ++++++++++++
 .../servicecomb/it/testcase/TestApiParam.java      | 118 +++++++++++++++++++++
 .../swagger/generator/core/OperationGenerator.java |   6 ++
 .../core/processor/annotation/AnnotationUtils.java |  96 ++++++++++++++++-
 .../extend/parameter/PendingBodyParameter.java     |  19 +++-
 9 files changed, 351 insertions(+), 44 deletions(-)
 copy core/src/test/java/org/apache/servicecomb/core/provider/Person.java => integration-tests/it-common/src/main/java/org/apache/servicecomb/it/schema/CommonModel.java (80%)
 copy integration-tests/{it-producer/src/main/java/org/apache/servicecomb/it/schema/DefaultJsonValueJaxrsSchema.java => it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamJaxrsSchema.java} (54%)
 copy integration-tests/{it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojoSchema.java => it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamPojoSchema.java} (71%)
 create mode 100644 integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
 create mode 100644 integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java


[incubator-servicecomb-java-chassis] 01/02: [SCB-215] process parameter level @ApiParam

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git

commit 6cd13bbb280c04b7724fc09d46430ae8390c21b2
Author: wujimin <wu...@huawei.com>
AuthorDate: Mon Sep 17 17:10:56 2018 +0800

    [SCB-215] process parameter level @ApiParam
---
 .../swagger/generator/core/OperationGenerator.java |  6 ++
 .../core/processor/annotation/AnnotationUtils.java | 96 +++++++++++++++++++++-
 .../extend/parameter/PendingBodyParameter.java     | 19 ++++-
 3 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java
index 560e3aa..8c9a834 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java
@@ -31,6 +31,7 @@ import javax.ws.rs.DefaultValue;
 
 import org.apache.servicecomb.swagger.SwaggerUtils;
 import org.apache.servicecomb.swagger.extend.parameter.ContextParameter;
+import org.apache.servicecomb.swagger.generator.core.processor.annotation.AnnotationUtils;
 import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -292,6 +293,11 @@ public class OperationGenerator {
         // 没有用于描述契约的标注,根据函数原型来反射生成
         context.getDefaultParamProcessor().process(this, paramIdx);
       }
+
+      if (!isArgumentNotProcessed(swaggerParamCount)) {
+        Parameter parameter = providerParameters.get(this.providerParameters.size() - 1);
+        AnnotationUtils.processApiParam(paramAnnotations, parameter);
+      }
     }
   }
 
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/annotation/AnnotationUtils.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/annotation/AnnotationUtils.java
index def34bf..aebca2b 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/annotation/AnnotationUtils.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/annotation/AnnotationUtils.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.swagger.generator.core.processor.annotation;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -24,21 +25,25 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.servicecomb.swagger.generator.core.processor.annotation.models.ResponseConfig;
 import org.apache.servicecomb.swagger.generator.core.processor.annotation.models.ResponseConfigBase;
 import org.apache.servicecomb.swagger.generator.core.processor.annotation.models.ResponseHeaderConfig;
 import org.springframework.util.ClassUtils;
-import org.springframework.util.StringUtils;
 
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.Example;
+import io.swagger.annotations.ExampleProperty;
 import io.swagger.annotations.ResponseHeader;
 import io.swagger.converter.ModelConverters;
 import io.swagger.models.Model;
 import io.swagger.models.Operation;
 import io.swagger.models.Response;
 import io.swagger.models.Swagger;
+import io.swagger.models.parameters.AbstractSerializableParameter;
 import io.swagger.models.parameters.BodyParameter;
 import io.swagger.models.parameters.CookieParameter;
 import io.swagger.models.parameters.FormParameter;
@@ -47,6 +52,8 @@ import io.swagger.models.parameters.Parameter;
 import io.swagger.models.parameters.PathParameter;
 import io.swagger.models.parameters.QueryParameter;
 import io.swagger.models.properties.ArrayProperty;
+import io.swagger.models.properties.FileProperty;
+import io.swagger.models.properties.LongProperty;
 import io.swagger.models.properties.MapProperty;
 import io.swagger.models.properties.Property;
 import io.swagger.util.ParameterProcessor;
@@ -218,4 +225,91 @@ public final class AnnotationUtils {
         throw new Error("not support paramType " + paramAnnotation.paramType());
     }
   }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T findAnnotation(Annotation[] annotations, Class<T> annotationType) {
+    for (Annotation annotation : annotations) {
+      if (annotation.annotationType().equals(annotationType)) {
+        return (T) annotation;
+      }
+    }
+
+    return null;
+  }
+
+  public static void processApiParam(Annotation[] paramAnnotations, Parameter parameter) {
+    ApiParam param = findAnnotation(paramAnnotations, ApiParam.class);
+    if (param == null) {
+      return;
+    }
+
+    if (parameter instanceof AbstractSerializableParameter) {
+      processApiParam(param, (AbstractSerializableParameter<?>) parameter);
+      return;
+    }
+
+    processApiParam(param, (BodyParameter) parameter);
+  }
+
+  protected static void processApiParam(ApiParam param, BodyParameter p) {
+    if (param.required()) {
+      p.setRequired(true);
+    }
+    if (StringUtils.isNotEmpty(param.name())) {
+      p.setName(param.name());
+    }
+    if (StringUtils.isNotEmpty(param.value())) {
+      p.setDescription(param.value());
+    }
+    if (StringUtils.isNotEmpty(param.access())) {
+      p.setAccess(param.access());
+    }
+
+    Example example = param.examples();
+    if (example != null && example.value() != null) {
+      for (ExampleProperty ex : example.value()) {
+        String mediaType = ex.mediaType();
+        String value = ex.value();
+        if (!mediaType.isEmpty() && !value.isEmpty()) {
+          p.example(mediaType.trim(), value.trim());
+        }
+      }
+    }
+  }
+
+  protected static void processApiParam(ApiParam param, AbstractSerializableParameter<?> p) {
+    if (param.required()) {
+      p.setRequired(true);
+    }
+    if (param.readOnly()) {
+      p.setReadOnly(true);
+    }
+    if (param.allowEmptyValue()) {
+      p.setAllowEmptyValue(true);
+    }
+    if (StringUtils.isNotEmpty(param.name())) {
+      p.setName(param.name());
+    }
+    if (StringUtils.isNotEmpty(param.value())) {
+      p.setDescription(param.value());
+    }
+    if (StringUtils.isNotEmpty(param.example())) {
+      p.setExample(param.example());
+    }
+    if (StringUtils.isNotEmpty(param.access())) {
+      p.setAccess(param.access());
+    }
+    if (StringUtils.isNoneEmpty(param.collectionFormat())) {
+      p.setCollectionFormat(param.collectionFormat());
+    }
+    if (StringUtils.isNotEmpty(param.type())) {
+      if ("java.io.File".equalsIgnoreCase(param.type())) {
+        p.setProperty(new FileProperty());
+      } else if ("long".equalsIgnoreCase(param.type())) {
+        p.setProperty(new LongProperty());
+      } else {
+        p.setType(param.type());
+      }
+    }
+  }
 }
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/pojo/extend/parameter/PendingBodyParameter.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/pojo/extend/parameter/PendingBodyParameter.java
index 487b574..065b612 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/pojo/extend/parameter/PendingBodyParameter.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/pojo/extend/parameter/PendingBodyParameter.java
@@ -17,18 +17,22 @@
 
 package org.apache.servicecomb.swagger.generator.pojo.extend.parameter;
 
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 
 import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
 import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import io.swagger.models.ModelImpl;
 import io.swagger.models.RefModel;
 import io.swagger.models.parameters.BodyParameter;
 import io.swagger.models.properties.Property;
 import io.swagger.models.properties.PropertyBuilder;
 import io.swagger.models.properties.RefProperty;
+import io.swagger.util.Json;
 
 //
 // 备选body
@@ -39,10 +43,13 @@ import io.swagger.models.properties.RefProperty;
 // jaxrs、springmvc这种模式,要求符合模式本身的定义场景,不允许随意组合
 //
 public class PendingBodyParameter extends BodyParameter {
+  @JsonIgnore
   private OperationGenerator operationGenerator;
 
+  @JsonIgnore
   private Property property;
 
+  @JsonIgnore
   private Type type;
 
   public void setOperationGenerator(OperationGenerator operationGenerator) {
@@ -65,6 +72,7 @@ public class PendingBodyParameter extends BodyParameter {
     this.type = type;
   }
 
+  @JsonIgnore
   public Method getMethod() {
     return operationGenerator.getProviderMethod();
   }
@@ -73,11 +81,14 @@ public class PendingBodyParameter extends BodyParameter {
     String modelType = ParamUtils.generateBodyParameterName(operationGenerator.getProviderMethod());
     RefModel model = toRefModel(modelType);
 
-    BodyParameter bodyParameter = new BodyParameter();
-    bodyParameter.setName(paramName);
-    bodyParameter.setSchema(model);
+    setName(paramName);
+    setSchema(model);
 
-    return bodyParameter;
+    try {
+      return Json.mapper().readValue(Json.mapper().writeValueAsString(this), BodyParameter.class);
+    } catch (IOException e) {
+      throw new IllegalStateException("failed to createBodyParameter.", e);
+    }
   }
 
   // swagger中的body只能是ref,不能是简单类型


[incubator-servicecomb-java-chassis] 02/02: [SCB-215] add IT for ApiParam

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git

commit c019638318ba2556e53e55c26d51b4bb607d9600
Author: wujimin <wu...@huawei.com>
AuthorDate: Mon Sep 17 22:03:03 2018 +0800

    [SCB-215] add IT for ApiParam
---
 .../apache/servicecomb/it/schema/CommonModel.java  |  29 +++++
 .../org/apache/servicecomb/it/ConsumerMain.java    |   2 +
 .../servicecomb/it/schema/ApiParamJaxrsSchema.java |  62 +++++++++++
 .../servicecomb/it/schema/ApiParamPojoSchema.java  |  34 ++++++
 .../it/schema/ApiParamSpringmvcSchema.java         |  69 ++++++++++++
 .../servicecomb/it/testcase/TestApiParam.java      | 118 +++++++++++++++++++++
 6 files changed, 314 insertions(+)

diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/schema/CommonModel.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/schema/CommonModel.java
new file mode 100644
index 0000000..1dcebb0
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/schema/CommonModel.java
@@ -0,0 +1,29 @@
+/*
+ * 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.it.schema;
+
+public class CommonModel {
+  private int iValue;
+
+  public int getiValue() {
+    return iValue;
+  }
+
+  public void setiValue(int iValue) {
+    this.iValue = iValue;
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
index 22113d4..23ede5f 100644
--- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
@@ -21,6 +21,7 @@ import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.it.deploy.Deploys;
 import org.apache.servicecomb.it.junit.ITJUnitUtils;
 import org.apache.servicecomb.it.testcase.TestAnnotatedAttribute;
+import org.apache.servicecomb.it.testcase.TestApiParam;
 import org.apache.servicecomb.it.testcase.TestChangeTransport;
 import org.apache.servicecomb.it.testcase.TestDataTypePrimitive;
 import org.apache.servicecomb.it.testcase.TestDefaultJsonValueJaxrsSchema;
@@ -66,6 +67,7 @@ public class ConsumerMain {
     // deploys.getZuul().ensureReady(zuul);
 
     ITJUnitUtils.run(TestIgnoreMethod.class);
+    ITJUnitUtils.run(TestApiParam.class);
 
     // 1.base test case
     //   include all extension point abnormal scenes test case
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamJaxrsSchema.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamJaxrsSchema.java
new file mode 100644
index 0000000..f5b8143
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamJaxrsSchema.java
@@ -0,0 +1,62 @@
+/*
+ * 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.it.schema;
+
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+import io.swagger.annotations.ApiParam;
+
+@RestSchema(schemaId = "apiParamJaxrs")
+@Path("/apiParamJaxrs")
+public class ApiParamJaxrsSchema {
+  @POST
+  @Path("/body")
+  public void body(@ApiParam(value = "desc of body param") CommonModel model) {
+
+  }
+
+  @POST
+  @Path("/query")
+  public void query(@ApiParam(value = "desc of query param") @QueryParam("input") int input) {
+
+  }
+
+  @POST
+  @Path("/header")
+  public void header(@ApiParam(value = "desc of header param") @HeaderParam("input") int input) {
+
+  }
+
+  @POST
+  @Path("/cookie")
+  public void cookie(@ApiParam(value = "desc of cookie param") @CookieParam("input") int input) {
+
+  }
+
+  @POST
+  @Path("/form")
+  public void form(@ApiParam(value = "desc of form param") @FormParam("input") int input) {
+
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamPojoSchema.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamPojoSchema.java
new file mode 100644
index 0000000..1673ba8
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamPojoSchema.java
@@ -0,0 +1,34 @@
+/*
+ * 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.it.schema;
+
+import org.apache.servicecomb.provider.pojo.RpcSchema;
+
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.SwaggerDefinition;
+
+@RpcSchema(schemaId = "apiParamPojo")
+@SwaggerDefinition(basePath = "/apiParamPojo")
+public class ApiParamPojoSchema {
+  public void model(@ApiParam(value = "desc of model param") CommonModel model) {
+
+  }
+
+  public void simple(@ApiParam(value = "desc of simple param") int input) {
+
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
new file mode 100644
index 0000000..b291692
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java
@@ -0,0 +1,69 @@
+/*
+ * 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.it.schema;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.Example;
+import io.swagger.annotations.ExampleProperty;
+
+@RestSchema(schemaId = "apiParamSpringmvc")
+@RequestMapping(path = "/apiParamSpringmvc")
+public class ApiParamSpringmvcSchema {
+  @PostMapping(path = "/body")
+  public void body(@ApiParam(value = "desc of body param",
+      required = true,
+      name = "modelEx",
+      examples = @Example(value = {
+          @ExampleProperty(mediaType = "k1", value = "v1"),
+          @ExampleProperty(mediaType = "k2", value = "v2")})) @RequestBody CommonModel model) {
+
+  }
+
+  @PostMapping(path = "/query")
+  public void query(@ApiParam(value = "desc of query param",
+      required = true,
+      readOnly = true,
+      allowEmptyValue = true,
+      name = "inputEx",
+      example = "example",
+      collectionFormat = "fmt") int input) {
+
+  }
+
+  @PostMapping(path = "/header")
+  public void header(@ApiParam(value = "desc of header param") @RequestHeader("input") int input) {
+
+  }
+
+  @PostMapping(path = "/cookie")
+  public void cookie(@ApiParam(value = "desc of cookie param") @CookieValue("input") int input) {
+
+  }
+
+  @PostMapping(path = "/form")
+  public void form(@ApiParam(value = "desc of form param") @RequestAttribute("input") int input) {
+
+  }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java
new file mode 100644
index 0000000..3178742
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java
@@ -0,0 +1,118 @@
+/*
+ * 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.it.testcase;
+
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.definition.MicroserviceMeta;
+import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.swagger.models.parameters.BodyParameter;
+import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.QueryParameter;
+
+public class TestApiParam {
+  MicroserviceMeta microserviceMeta = SCBEngine.getInstance().getProducerMicroserviceMeta();
+
+  Parameter parameter;
+
+  protected void check(String schemaId, String opName) {
+    check(schemaId, opName, opName);
+  }
+
+  protected void check(String schemaId, String opName, String paramType) {
+    SchemaMeta schemaMeta = microserviceMeta.findSchemaMeta(schemaId);
+    OperationMeta operationMeta = schemaMeta.findOperation(opName);
+    parameter = operationMeta.getSwaggerOperation().getParameters().get(0);
+    Assert.assertEquals("desc of " + opName + " param", parameter.getDescription());
+    Assert.assertEquals(paramType, parameter.getIn());
+  }
+
+  @Test
+  public void pojoModel() {
+    check("apiParamPojo", "model", "body");
+  }
+
+  @Test
+  public void pojoSimple() {
+    check("apiParamPojo", "simple", "body");
+  }
+
+  @Test
+  public void jaxrsBody() {
+    check("apiParamJaxrs", "body");
+  }
+
+  @Test
+  public void jaxrsQuery() {
+    check("apiParamJaxrs", "query");
+  }
+
+  @Test
+  public void jaxrsHeader() {
+    check("apiParamJaxrs", "header");
+  }
+
+  @Test
+  public void jaxrsCookie() {
+    check("apiParamJaxrs", "cookie");
+  }
+
+  @Test
+  public void jaxrsForm() {
+    check("apiParamJaxrs", "form", "formData");
+  }
+
+  @Test
+  public void springmvcBody() {
+    check("apiParamSpringmvc", "body");
+
+    Assert.assertTrue(parameter.getRequired());
+    Assert.assertEquals("modelEx", parameter.getName());
+    Assert.assertEquals("v1", ((BodyParameter) parameter).getExamples().get("k1"));
+    Assert.assertEquals("v2", ((BodyParameter) parameter).getExamples().get("k2"));
+  }
+
+  @Test
+  public void springmvcQuery() {
+    check("apiParamSpringmvc", "query");
+
+    Assert.assertTrue(parameter.getRequired());
+    Assert.assertTrue(parameter.isReadOnly());
+    Assert.assertTrue(parameter.getAllowEmptyValue());
+    Assert.assertEquals("inputEx", parameter.getName());
+    Assert.assertEquals("example", ((QueryParameter) parameter).getExample());
+    Assert.assertEquals("fmt", ((QueryParameter) parameter).getCollectionFormat());
+  }
+
+  @Test
+  public void springmvcHeader() {
+    check("apiParamSpringmvc", "header");
+  }
+
+  @Test
+  public void springmvcCookie() {
+    check("apiParamSpringmvc", "cookie");
+  }
+
+  @Test
+  public void springmvcForm() {
+    check("apiParamSpringmvc", "form", "formData");
+  }
+}