You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@servicecomb.apache.org by "ASF GitHub Bot (JIRA)" <ji...@apache.org> on 2018/08/01 09:54:00 UTC

[jira] [Commented] (SCB-777) Support @BeanParam annotation in JAX-RS developing style

    [ https://issues.apache.org/jira/browse/SCB-777?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16565065#comment-16565065 ] 

ASF GitHub Bot commented on SCB-777:
------------------------------------

liubao68 closed pull request #843: [SCB-777] Support JAX-RS @BeanParam annotation
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/843
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/demo/demo-jaxrs/jaxrs-client/pom.xml b/demo/demo-jaxrs/jaxrs-client/pom.xml
index 06bb8a080..219fb3931 100644
--- a/demo/demo-jaxrs/jaxrs-client/pom.xml
+++ b/demo/demo-jaxrs/jaxrs-client/pom.xml
@@ -41,6 +41,10 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>provider-springmvc</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-pojo</artifactId>
+    </dependency>
   </dependencies>
 
   <properties>
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
index b123119ff..a2b129b0f 100644
--- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
@@ -32,6 +32,8 @@
 import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper;
 import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.demo.compute.Person;
+import org.apache.servicecomb.demo.jaxrs.client.beanParam.BeanParamPojoClient;
+import org.apache.servicecomb.demo.jaxrs.client.beanParam.BeanParamRestTemplateClient;
 import org.apache.servicecomb.demo.validator.Student;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
@@ -71,6 +73,11 @@ public static void run() throws Exception {
     testClientTimeOut(templateNew);
     testJaxRSDefaultValues(templateNew);
     MultiErrorCodeServiceClient.runTest();
+
+    BeanParamPojoClient beanParamPojoClient = new BeanParamPojoClient();
+    beanParamPojoClient.testAll();
+    BeanParamRestTemplateClient beanParamRestTemplateClient = new BeanParamRestTemplateClient();
+    beanParamRestTemplateClient.testAll();
   }
 
   private static void testCompute(RestTemplate template) throws Exception {
@@ -90,7 +97,7 @@ private static void testCompute(RestTemplate template) throws Exception {
     }
   }
 
-  private static void testValidator(RestTemplate template) throws Exception {
+  private static void testValidator(RestTemplate template) {
     String microserviceName = "jaxrs";
     for (String transport : DemoConst.transports) {
       CseContext.getInstance().getConsumerProviderManager().setTransport(microserviceName, transport);
@@ -119,8 +126,8 @@ private static void testJaxRSDefaultValues(RestTemplate template) {
       //default values
       HttpHeaders headers = new HttpHeaders();
       headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED);
-      MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
-      HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
+      MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
+      HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
       String result = template.postForObject(cseUrlPrefix + "/form", request, String.class);
       TestMgr.check("Hello 20bobo", result);
 
@@ -175,7 +182,7 @@ private static void testJaxRSDefaultValues(RestTemplate template) {
       //input values
       headers = new HttpHeaders();
       headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED);
-      Map<String, String> params = new HashMap<String, String>();
+      Map<String, String> params = new HashMap<>();
       params.put("a", "30");
       params.put("b", "sam");
       HttpEntity<Map<String, String>> requestPara = new HttpEntity<>(params, headers);
@@ -196,7 +203,6 @@ private static void testJaxRSDefaultValues(RestTemplate template) {
       result = template.getForObject(cseUrlPrefix + "/query2?a=3&b=4&c=5&d=30&e=2", String.class);
       TestMgr.check("Hello 345302", result);
     }
-
   }
 
 
@@ -361,7 +367,7 @@ private static void testValidatorExchangeSuccess(RestTemplate template, String c
     TestMgr.check("hello test 15", result);
   }
 
-  private static void testClientTimeOut(RestTemplate template) throws Exception {
+  private static void testClientTimeOut(RestTemplate template) {
     String microserviceName = "jaxrs";
     for (String transport : DemoConst.transports) {
       if (transport.equals(Const.ANY_TRANSPORT)) {
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java
new file mode 100644
index 000000000..fe15bda36
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java
@@ -0,0 +1,57 @@
+/*
+ * 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.jaxrs.client.beanParam;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.pojo.Invoker;
+
+public class BeanParamPojoClient {
+  BeanParamTestServiceIntf beanParamTestServiceIntf;
+
+  public BeanParamPojoClient() {
+    beanParamTestServiceIntf = Invoker.createProxy("jaxrs", "beanParamTest", BeanParamTestServiceIntf.class);
+  }
+
+  public void testAll() {
+    testBeanParam();
+    testUpload();
+  }
+
+  public void testBeanParam() {
+    String result = beanParamTestServiceIntf.beanParameterTest("querySwaggerValue", 10, 2, "pathSwaggerValue", "extra");
+    TestMgr.check(
+        "invocationContextConsistency=true|testBeanParameter=TestBeanParameter{queryStr='querySwaggerValue', headerInt=2, "
+            + "pathStr='pathSwaggerValue', cookieLong=10}|extraQuery=extra",
+        result);
+  }
+
+  public void testUpload() {
+    BufferedInputStream bufferedInputStream0 = new BufferedInputStream(new ByteArrayInputStream("up0".getBytes()));
+    BufferedInputStream bufferedInputStream1 = new BufferedInputStream(new ByteArrayInputStream("up1".getBytes()));
+    BufferedInputStream bufferedInputStream2 = new BufferedInputStream(new ByteArrayInputStream("up2".getBytes()));
+
+    String result = beanParamTestServiceIntf.beanParameterTestUpload(
+        bufferedInputStream0, "queryTest", bufferedInputStream1, bufferedInputStream2, "ex");
+    TestMgr.check(
+        "testBeanParameter=TestBeanParameterWithUpload{queryStr='queryTest'}|extraQuery=ex|up0=up0|up1=up1|up2=up2",
+        result);
+  }
+}
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java
new file mode 100644
index 000000000..82422d99f
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java
@@ -0,0 +1,84 @@
+/*
+ * 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.jaxrs.client.beanParam;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity;
+import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+public class BeanParamRestTemplateClient {
+  RestTemplate restTemplate;
+
+  public BeanParamRestTemplateClient() {
+    restTemplate = RestTemplateBuilder.create();
+  }
+
+
+  public void testAll() {
+    testBeanParam();
+    testUpload();
+  }
+
+  public void testBeanParam() {
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("Cookie", "cookieSwaggerLong=11");
+    headers.add("headerSwaggerInt", "2");
+    HttpEntity<Object> requestEntity1 = new CseHttpEntity<>(headers);
+    ResponseEntity<String> result = restTemplate.exchange(
+        "cse://jaxrs/beanParamTest/pathSwaggerValue/simple?querySwaggerStr=querySwaggerValue&extraQuery=extra",
+        HttpMethod.GET,
+        requestEntity1,
+        String.class);
+    TestMgr.check(
+        "invocationContextConsistency=true|testBeanParameter=TestBeanParameter{queryStr='querySwaggerValue', headerInt=2, "
+            + "pathStr='pathSwaggerValue', cookieLong=11}|extraQuery=extra",
+        result.getBody());
+  }
+
+  public void testUpload() {
+    BufferedInputStream bufferedInputStream0 = new BufferedInputStream(new ByteArrayInputStream("up0".getBytes()));
+    BufferedInputStream bufferedInputStream1 = new BufferedInputStream(new ByteArrayInputStream("up1".getBytes()));
+    BufferedInputStream bufferedInputStream2 = new BufferedInputStream(new ByteArrayInputStream("up2".getBytes()));
+
+    HashMap<String, Object> formData = new HashMap<>();
+    formData.put("up0", bufferedInputStream0);
+    formData.put("up1", bufferedInputStream1);
+    formData.put("up2", bufferedInputStream2);
+    HttpHeaders headers = new HttpHeaders();
+    headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+    HttpEntity<Map<String, Object>> entity = new HttpEntity<>(formData, headers);
+
+    String result = restTemplate.postForObject("cse://jaxrs/beanParamTest/upload?query=fromTemplate&extraQuery=ex",
+        entity,
+        String.class);
+    TestMgr.check(
+        "testBeanParameter=TestBeanParameterWithUpload{queryStr='fromTemplate'}|extraQuery=ex|up0=up0|up1=up1|up2=up2",
+        result);
+  }
+}
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamTestServiceIntf.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamTestServiceIntf.java
new file mode 100644
index 000000000..1d8c602e4
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamTestServiceIntf.java
@@ -0,0 +1,27 @@
+/*
+ * 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.jaxrs.client.beanParam;
+
+import java.io.InputStream;
+
+public interface BeanParamTestServiceIntf {
+  String beanParameterTest(String querySwaggerStr, long cookieSwaggerLong, Integer headerSwaggerInt,
+      String pathSwaggerStr, String extraQuery);
+
+  String beanParameterTestUpload(InputStream up0, String query, InputStream up1, InputStream up2, String extraQuery);
+}
diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java
new file mode 100644
index 000000000..1e2a040bc
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java
@@ -0,0 +1,73 @@
+/*
+ * 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.jaxrs.server.beanParam;
+
+import java.io.IOException;
+import java.util.Scanner;
+
+import javax.servlet.http.Part;
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
+import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
+
+@RestSchema(schemaId = "beanParamTest")
+@Path("/beanParamTest")
+public class BeanParamTestService {
+  @Path("/{pathSwaggerStr}/simple")
+  @GET
+  public String beanParameterTest(InvocationContext invocationContext, @BeanParam TestBeanParameter testBeanParameter,
+      @QueryParam("extraQuery") String extraQuery) {
+    return String.format("invocationContextConsistency=%b|testBeanParameter=%s|extraQuery=%s",
+        ContextUtils.getInvocationContext() == invocationContext,
+        testBeanParameter.toString(),
+        extraQuery);
+  }
+
+  @Path("/upload")
+  @Consumes(MediaType.MULTIPART_FORM_DATA)
+  @POST
+  public String beanParameterTestUpload(@FormParam("up0") Part up0,
+      @BeanParam TestBeanParameterWithUpload testBeanParameter,
+      @QueryParam("extraQuery") String extraQuery) throws IOException {
+    return String.format("testBeanParameter=%s|extraQuery=%s|up0=%s|up1=%s|up2=%s",
+        testBeanParameter.toString(),
+        extraQuery,
+        getUploadContent(up0),
+        getUploadContent(testBeanParameter.getUp1()),
+        getUploadContent(testBeanParameter.getUp2()));
+  }
+
+  public String getUploadContent(Part upload) throws IOException {
+    StringBuilder result = new StringBuilder();
+    try (Scanner scanner = new Scanner(upload.getInputStream())) {
+      while (scanner.hasNext()) {
+        result.append(scanner.next());
+      }
+    }
+    return result.toString();
+  }
+}
diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java
new file mode 100644
index 000000000..9e8c319be
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java
@@ -0,0 +1,87 @@
+/*
+ * 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.jaxrs.server.beanParam;
+
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+public class TestBeanParameter {
+  @DefaultValue("defaultQueryValue")
+  @QueryParam("querySwaggerStr")
+  private String queryStr;
+
+  private Integer headerInt;
+
+  private String pathStr;
+
+  @CookieParam("cookieSwaggerLong")
+  private long cookieLong;
+
+  public String getQueryStr() {
+    return queryStr;
+  }
+
+  public TestBeanParameter setQueryStr(String queryStr) {
+    this.queryStr = queryStr;
+    return this;
+  }
+
+  public Integer getHeaderInt() {
+    return headerInt;
+  }
+
+  @DefaultValue("12")
+  @HeaderParam("headerSwaggerInt")
+  public TestBeanParameter setHeaderInt(Integer headerInt) {
+    this.headerInt = headerInt;
+    return this;
+  }
+
+  public String getPathStr() {
+    return pathStr;
+  }
+
+  @PathParam("pathSwaggerStr")
+  public TestBeanParameter setPathStr(String pathStr) {
+    this.pathStr = pathStr;
+    return this;
+  }
+
+  public long getCookieLong() {
+    return cookieLong;
+  }
+
+  public TestBeanParameter setCookieLong(long cookieLong) {
+    this.cookieLong = cookieLong;
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb = new StringBuilder("TestBeanParameter{");
+    sb.append("queryStr='").append(queryStr).append('\'');
+    sb.append(", headerInt=").append(headerInt);
+    sb.append(", pathStr='").append(pathStr).append('\'');
+    sb.append(", cookieLong=").append(cookieLong);
+    sb.append('}');
+    return sb.toString();
+  }
+}
diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java
new file mode 100644
index 000000000..fdef5688a
--- /dev/null
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java
@@ -0,0 +1,68 @@
+/*
+ * 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.jaxrs.server.beanParam;
+
+import javax.servlet.http.Part;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.QueryParam;
+
+public class TestBeanParameterWithUpload {
+  @QueryParam("query")
+  private String queryStr;
+
+  @FormParam("up1")
+  private Part up1;
+
+  private Part up2;
+
+  public String getQueryStr() {
+    return queryStr;
+  }
+
+  public TestBeanParameterWithUpload setQueryStr(String queryStr) {
+    this.queryStr = queryStr;
+    return this;
+  }
+
+  public Part getUp1() {
+    return up1;
+  }
+
+  public TestBeanParameterWithUpload setUp1(Part up1) {
+    this.up1 = up1;
+    return this;
+  }
+
+  public Part getUp2() {
+    return up2;
+  }
+
+  @FormParam("up2")
+  public TestBeanParameterWithUpload setUp2(Part up2) {
+    this.up2 = up2;
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder sb = new StringBuilder("TestBeanParameterWithUpload{");
+    sb.append("queryStr='").append(queryStr).append('\'');
+    sb.append('}');
+    return sb.toString();
+  }
+}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java
index 75c7b36ef..52f9aa5b1 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java
@@ -21,14 +21,18 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import com.fasterxml.jackson.core.JsonGenerationException;
-import com.fasterxml.jackson.core.JsonParseException;
+import javax.servlet.http.Part;
+
+import org.apache.servicecomb.foundation.common.utils.json.JavaxServletPartDeserializer;
+import org.apache.servicecomb.foundation.common.utils.json.JavaxServletPartSerializer;
+
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 
 public final class JsonUtils {
   public static final ObjectMapper OBJ_MAPPER;
@@ -37,23 +41,27 @@
     OBJ_MAPPER = new ObjectMapper();
     OBJ_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
     OBJ_MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
+
+    SimpleModule partDeserializeModule = new SimpleModule("partDeserializeModule",
+        new Version(0, 0, 1, null, "javax.servlet", "javax.servlet-api")
+    );
+    partDeserializeModule.addSerializer(Part.class, new JavaxServletPartSerializer());
+    partDeserializeModule.addDeserializer(Part.class, new JavaxServletPartDeserializer());
+    OBJ_MAPPER.registerModule(partDeserializeModule);
   }
 
   private JsonUtils() {
   }
 
-  public static <T> T readValue(byte[] src,
-      Class<T> valueType) throws JsonParseException, JsonMappingException, IOException {
+  public static <T> T readValue(byte[] src, Class<T> valueType) throws IOException {
     return OBJ_MAPPER.readValue(src, valueType);
   }
 
-  public static <T> T readValue(InputStream is,
-      Class<T> valueType) throws JsonParseException, JsonMappingException, IOException {
+  public static <T> T readValue(InputStream is, Class<T> valueType) throws IOException {
     return OBJ_MAPPER.readValue(is, valueType);
   }
 
-  public static <T> T readValue(InputStream is,
-      JavaType valueType) throws JsonParseException, JsonMappingException, IOException {
+  public static <T> T readValue(InputStream is, JavaType valueType) throws IOException {
     return OBJ_MAPPER.readValue(is, valueType);
   }
 
@@ -69,8 +77,7 @@ public static String writeValueAsString(Object value) throws JsonProcessingExcep
     return OBJ_MAPPER.convertValue(fromValue, toValueType);
   }
 
-  public static void writeValue(OutputStream out,
-      Object value) throws JsonGenerationException, JsonMappingException, IOException {
+  public static void writeValue(OutputStream out, Object value) throws IOException {
     OBJ_MAPPER.writeValue(out, value);
   }
 }
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java
new file mode 100644
index 000000000..98b489f9c
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.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.foundation.common.utils.json;
+
+import java.io.IOException;
+
+import javax.servlet.http.Part;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+public class JavaxServletPartDeserializer extends JsonDeserializer<Part> {
+  @Override
+  public Part deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+    final Object currentValue = p.getEmbeddedObject();
+    return (Part) currentValue;
+  }
+}
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java
new file mode 100644
index 000000000..34d247e3e
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java
@@ -0,0 +1,50 @@
+/*
+ * 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.foundation.common.utils.json;
+
+import java.io.IOException;
+
+import javax.servlet.http.Part;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.ObjectCodec;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.fasterxml.jackson.databind.util.TokenBuffer;
+
+public class JavaxServletPartSerializer extends StdSerializer<Part> {
+  private static final long serialVersionUID = 348443113789878443L;
+
+  public JavaxServletPartSerializer() {
+    this(null);
+  }
+
+  protected JavaxServletPartSerializer(Class<Part> t) {
+    super(t);
+  }
+
+  @Override
+  public void serialize(Part value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+    final ObjectCodec preservedCodec = ((TokenBuffer) gen).asParser().getCodec();
+    // set codec as null to avoid recursive dead loop
+    // JsonGenerator is instantiated for each serialization, so there should be no thread safe issue
+    gen.setCodec(null);
+    gen.writeObject(value);
+    gen.setCodec(preservedCodec);
+  }
+}
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/AbstractParameterProcessor.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/AbstractParameterProcessor.java
index da3d14b47..04d992cb5 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/AbstractParameterProcessor.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parameter/AbstractParameterProcessor.java
@@ -69,7 +69,7 @@ protected String getAnnotationParameterDefaultValue(Object annotation) {
     return "";
   }
 
-  protected abstract T createParameter();
+  public abstract T createParameter();
 
-  protected abstract String getAnnotationParameterName(Object annotation);
+  public abstract String getAnnotationParameterName(Object annotation);
 }
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java
index db6d20130..924bc651a 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/utils/ParamUtils.java
@@ -113,7 +113,7 @@ public static void setParameterType(Swagger swagger, Method method, int paramIdx
     Property property = ModelConverters.getInstance().readAsProperty(paramType);
 
     if (isComplexProperty(property)) {
-      // 简单参数不可以是复杂类型
+      // cannot set a simple parameter(header, query, etc.) as complex type
       String msg = String.format("not allow complex type for %s parameter, method=%s:%s, paramIdx=%d, type=%s",
           parameter.getIn(),
           method.getDeclaringClass().getName(),
@@ -125,6 +125,27 @@ public static void setParameterType(Swagger swagger, Method method, int paramIdx
     parameter.setProperty(property);
   }
 
+  /**
+   * Set param type info. For {@linkplain javax.ws.rs.BeanParam BeanParam} scenario.
+   *
+   * @param paramType type of the swagger parameter
+   * @param parameter swagger parameter
+   */
+  public static void setParameterType(Type paramType, AbstractSerializableParameter<?> parameter) {
+    Property property = ModelConverters.getInstance().readAsProperty(paramType);
+
+    if (isComplexProperty(property)) {
+      // cannot set a simple parameter(header, query, etc.) as complex type
+      throw new IllegalArgumentException(
+          String.format(
+              "not allow such type of param:[%s], param name is [%s]",
+              property.getClass(),
+              parameter.getName())
+      );
+    }
+    parameter.setProperty(property);
+  }
+
   public static boolean isComplexProperty(Property property) {
     if (RefProperty.class.isInstance(property) || ObjectProperty.class.isInstance(property)
         || MapProperty.class.isInstance(property)) {
diff --git a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java
index 1343f5f7b..b1161748e 100644
--- a/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java
+++ b/swagger/swagger-generator/generator-core/src/test/java/org/apache/servicecomb/swagger/generator/core/TestParamUtils.java
@@ -19,6 +19,7 @@
 
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,7 +29,10 @@
 import org.junit.Test;
 import org.mockito.Mockito;
 
+import io.swagger.models.parameters.AbstractSerializableParameter;
+import io.swagger.models.parameters.HeaderParameter;
 import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.QueryParameter;
 import io.swagger.models.properties.ArrayProperty;
 import io.swagger.models.properties.MapProperty;
 import io.swagger.models.properties.ObjectProperty;
@@ -66,4 +70,29 @@ public void isComplexProperty() {
     property = new StringProperty();
     Assert.assertFalse(ParamUtils.isComplexProperty(property));
   }
+
+  @Test
+  public void setParameterTypeByTypeNormal() {
+    AbstractSerializableParameter<?> parameter = new QueryParameter();
+    ParamUtils.setParameterType(String.class, parameter);
+    Assert.assertEquals("string", parameter.getType());
+
+    parameter = new HeaderParameter();
+    ParamUtils.setParameterType(long.class, parameter);
+    Assert.assertEquals("integer", parameter.getType());
+    Assert.assertEquals("int64", parameter.getFormat());
+  }
+
+  @Test
+  public void setParameterTypeByTypeOnComplexType() {
+    AbstractSerializableParameter<?> parameter = new QueryParameter();
+    parameter.setName("testName");
+    try {
+      ParamUtils.setParameterType(ArrayList.class, parameter);
+      Assert.fail("an exception is expected!");
+    } catch (IllegalArgumentException e) {
+      Assert.assertEquals("not allow such type of param:[class io.swagger.models.properties.ArrayProperty], "
+          + "param name is [testName]", e.getMessage());
+    }
+  }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/JaxrsSwaggerGeneratorContext.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/JaxrsSwaggerGeneratorContext.java
index 1c707cf60..7acabe0c3 100644
--- a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/JaxrsSwaggerGeneratorContext.java
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/JaxrsSwaggerGeneratorContext.java
@@ -20,6 +20,7 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.CookieParam;
 import javax.ws.rs.DELETE;
@@ -35,6 +36,7 @@
 import javax.ws.rs.QueryParam;
 
 import org.apache.servicecomb.swagger.generator.core.utils.ClassUtils;
+import org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.BeanParamAnnotationProcessor;
 import org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.ConsumesAnnotationProcessor;
 import org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.CookieParamAnnotationProcessor;
 import org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.FormParamAnnotationProcessor;
@@ -110,5 +112,6 @@ protected void initParameterAnnotationMgr() {
 
     parameterAnnotationMgr.register(HeaderParam.class, new HeaderParamAnnotationProcessor());
     parameterAnnotationMgr.register(QueryParam.class, new QueryParamAnnotationProcessor());
+    parameterAnnotationMgr.register(BeanParam.class, new BeanParamAnnotationProcessor());
   }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/BeanParamAnnotationProcessor.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/BeanParamAnnotationProcessor.java
new file mode 100644
index 000000000..a3a8eaea1
--- /dev/null
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/BeanParamAnnotationProcessor.java
@@ -0,0 +1,169 @@
+/*
+ * 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.swagger.generator.jaxrs.processor.annotation;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
+import org.apache.servicecomb.swagger.generator.core.ParameterAnnotationProcessor;
+import org.apache.servicecomb.swagger.generator.core.SwaggerGeneratorContext;
+import org.apache.servicecomb.swagger.generator.core.processor.parameter.AbstractParameterProcessor;
+import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
+
+import io.swagger.models.parameters.AbstractSerializableParameter;
+
+/**
+ * For {@link javax.ws.rs.BeanParam}
+ */
+public class BeanParamAnnotationProcessor implements ParameterAnnotationProcessor {
+  public static final Set<Class<?>> SUPPORTED_PARAM_ANNOTATIONS = new HashSet<>();
+
+  public static final String SETTER_METHOD_PREFIX = "set";
+
+  static {
+    SUPPORTED_PARAM_ANNOTATIONS.add(PathParam.class);
+    SUPPORTED_PARAM_ANNOTATIONS.add(QueryParam.class);
+    SUPPORTED_PARAM_ANNOTATIONS.add(HeaderParam.class);
+    SUPPORTED_PARAM_ANNOTATIONS.add(CookieParam.class);
+    SUPPORTED_PARAM_ANNOTATIONS.add(FormParam.class);
+  }
+
+  @Override
+  public void process(Object annotation, OperationGenerator operationGenerator, int paramIdx) {
+    final Class<?> beanParamClazz = operationGenerator.getProviderMethod().getParameterTypes()[paramIdx];
+    try {
+      // traversal fields, get those JAX-RS params
+      processParamField(operationGenerator, beanParamClazz);
+      // traversal setter methods, some setter method may also be tagged with param annotations
+      processParamSetter(operationGenerator, beanParamClazz);
+    } catch (IllegalArgumentException e) {
+      throw new Error(String.format(
+          "Processing param failed, method=%s:%s, beanParamIdx=%d",
+          operationGenerator.getProviderMethod().getDeclaringClass().getName(),
+          operationGenerator.getProviderMethod().getName(),
+          paramIdx)
+          , e);
+    }
+  }
+
+  /**
+   * Process those setter methods tagged by JAX-RS param annotations.
+   */
+  private void processParamSetter(OperationGenerator operationGenerator, Class<?> beanParamClazz) {
+    for (Method method : beanParamClazz.getDeclaredMethods()) {
+      if (!method.getName().startsWith(SETTER_METHOD_PREFIX)) {
+        // only process setter methods
+        continue;
+      }
+      // There should be one and only one param in a setter method
+      final Type genericParamType = method.getGenericParameterTypes()[0];
+      processBeanParamMember(operationGenerator, method.getAnnotations(), genericParamType);
+    }
+  }
+
+  /**
+   * Process those fields tagged by JAX-RS param annotations.
+   */
+  private void processParamField(OperationGenerator operationGenerator, Class<?> beanParamClazz) {
+    for (Field beanParamField : beanParamClazz.getDeclaredFields()) {
+      processBeanParamMember(operationGenerator, beanParamField.getAnnotations(), beanParamField.getGenericType());
+    }
+  }
+
+  /**
+   * Process a swagger parameter defined by field or setter method in this BeanParam.
+   * After processing, a swagger parameter is generated and set into {@code operationGenerator}.
+   *
+   * @param operationGenerator operationGenerator
+   * @param annotations annotations on fields or setter methods
+   * @param genericType type of the fields, or the param type of the setter methods
+   */
+  private void processBeanParamMember(OperationGenerator operationGenerator, Annotation[] annotations,
+      Type genericType) {
+    String defaultValue = null;
+    for (Annotation fieldAnnotation : annotations) {
+      if (!SUPPORTED_PARAM_ANNOTATIONS.contains(fieldAnnotation.annotationType())) {
+        if (fieldAnnotation instanceof DefaultValue) {
+          defaultValue = ((DefaultValue) fieldAnnotation).value();
+        }
+        continue;
+      }
+
+      setUpParameter(operationGenerator, fieldAnnotation, genericType, defaultValue);
+    }
+  }
+
+  /**
+   * Generate swagger parameter, set default value, and add it into {@code operationGenerator}.
+   *
+   * @param operationGenerator operationGenerator
+   * @param fieldAnnotation JAX-RS param annotation
+   * @param genericParamType type of the parameter
+   * @param defaultValue default value, can be null
+   */
+  private void setUpParameter(
+      OperationGenerator operationGenerator,
+      Annotation fieldAnnotation,
+      Type genericParamType,
+      String defaultValue) {
+    AbstractSerializableParameter<?> parameter = generateParameter(
+        operationGenerator.getContext(),
+        fieldAnnotation,
+        genericParamType);
+
+    if (null != defaultValue) {
+      parameter.setDefaultValue(defaultValue);
+    }
+    operationGenerator.addProviderParameter(parameter);
+  }
+
+  /**
+   * Generate a swagger parameter, set up name and type info.
+   *
+   * @param swaggerGeneratorContext context data carried by {@linkplain OperationGenerator}
+   * @param fieldAnnotation JAX-RS param annotation
+   * @param genericParamType default value, can be null
+   * @return the generated swagger parameter
+   */
+  private AbstractSerializableParameter<?> generateParameter(
+      SwaggerGeneratorContext swaggerGeneratorContext,
+      Annotation fieldAnnotation,
+      Type genericParamType) {
+    // find the corresponding ParameterProcessor and process the parameter
+    final AbstractParameterProcessor<?> parameterAnnotationProcessor =
+        (AbstractParameterProcessor<?>) swaggerGeneratorContext
+            .findParameterAnnotationProcessor(fieldAnnotation.annotationType());
+    AbstractSerializableParameter<?> parameter = parameterAnnotationProcessor.createParameter();
+    String paramName = parameterAnnotationProcessor.getAnnotationParameterName(fieldAnnotation);
+    parameter.setName(paramName);
+    ParamUtils.setParameterType(genericParamType, parameter);
+    return parameter;
+  }
+}
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/CookieParamAnnotationProcessor.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/CookieParamAnnotationProcessor.java
index 34c626505..41fc842d1 100644
--- a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/CookieParamAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/CookieParamAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class CookieParamAnnotationProcessor extends AbstractParameterProcessor<CookieParameter> {
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((CookieParam) annotation).value();
   }
 
   @Override
-  protected CookieParameter createParameter() {
+  public CookieParameter createParameter() {
     return new CookieParameter();
   }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/FormParamAnnotationProcessor.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/FormParamAnnotationProcessor.java
index 9b64f4e09..c1abaf477 100644
--- a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/FormParamAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/FormParamAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class FormParamAnnotationProcessor extends AbstractParameterProcessor<FormParameter> {
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((FormParam) annotation).value();
   }
 
   @Override
-  protected FormParameter createParameter() {
+  public FormParameter createParameter() {
     return new FormParameter();
   }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/HeaderParamAnnotationProcessor.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/HeaderParamAnnotationProcessor.java
index 54066eb29..de2c7901f 100644
--- a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/HeaderParamAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/HeaderParamAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class HeaderParamAnnotationProcessor extends AbstractParameterProcessor<HeaderParameter> {
   @Override
-  protected HeaderParameter createParameter() {
+  public HeaderParameter createParameter() {
     return new HeaderParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((HeaderParam) annotation).value();
   }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/PathParamAnnotationProcessor.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/PathParamAnnotationProcessor.java
index fe7e53309..9a88543d0 100644
--- a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/PathParamAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/PathParamAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class PathParamAnnotationProcessor extends AbstractParameterProcessor<PathParameter> {
   @Override
-  protected PathParameter createParameter() {
+  public PathParameter createParameter() {
     return new PathParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((PathParam) annotation).value();
   }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/QueryParamAnnotationProcessor.java b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/QueryParamAnnotationProcessor.java
index a9365a369..98e0aa7be 100644
--- a/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/QueryParamAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-jaxrs/src/main/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/QueryParamAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class QueryParamAnnotationProcessor extends AbstractParameterProcessor<QueryParameter> {
   @Override
-  protected QueryParameter createParameter() {
+  public QueryParameter createParameter() {
     return new QueryParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((QueryParam) annotation).value();
   }
 }
diff --git a/swagger/swagger-generator/generator-jaxrs/src/test/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/BeanParamAnnotationProcessorTest.java b/swagger/swagger-generator/generator-jaxrs/src/test/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/BeanParamAnnotationProcessorTest.java
new file mode 100644
index 000000000..f81e2dda0
--- /dev/null
+++ b/swagger/swagger-generator/generator-jaxrs/src/test/java/org/apache/servicecomb/swagger/generator/jaxrs/processor/annotation/BeanParamAnnotationProcessorTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.swagger.generator.jaxrs.processor.annotation;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
+import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator;
+import org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext;
+import org.junit.Test;
+
+import io.swagger.models.parameters.AbstractSerializableParameter;
+import io.swagger.models.parameters.Parameter;
+
+public class BeanParamAnnotationProcessorTest {
+
+  @Test
+  public void processSuccess() throws NoSuchMethodException {
+    BeanParamAnnotationProcessor processor = new BeanParamAnnotationProcessor();
+    final OperationGenerator operationGenerator = mockOperationGenerator("testBeanParam", AggregatedParam.class);
+
+    processor.process(null, operationGenerator, 0);
+
+    final List<Parameter> providerParameters = operationGenerator.getProviderParameters();
+    assertEquals(5, providerParameters.size());
+    AbstractSerializableParameter<?> parameter = (AbstractSerializableParameter<?>) providerParameters.get(0);
+    assertEquals("path", parameter.getIn());
+    assertEquals("path0", parameter.getName());
+    assertEquals("pa", parameter.getDefault());
+    assertEquals("string", parameter.getType());
+    parameter = (AbstractSerializableParameter<?>) providerParameters.get(1);
+    assertEquals("query", parameter.getIn());
+    assertEquals("query1", parameter.getName());
+    assertEquals("integer", parameter.getType());
+    assertEquals("int32", parameter.getFormat());
+    parameter = (AbstractSerializableParameter<?>) providerParameters.get(2);
+    assertEquals("header", parameter.getIn());
+    assertEquals("header2", parameter.getName());
+    assertEquals("string", parameter.getType());
+    parameter = (AbstractSerializableParameter<?>) providerParameters.get(3);
+    assertEquals("formData", parameter.getIn());
+    assertEquals("form3", parameter.getName());
+    assertEquals(12L, parameter.getDefault());
+    assertEquals("integer", parameter.getType());
+    assertEquals("int64", parameter.getFormat());
+    parameter = (AbstractSerializableParameter<?>) providerParameters.get(4);
+    assertEquals("cookie", parameter.getIn());
+    assertEquals("cookie4", parameter.getName());
+    assertEquals("integer", parameter.getType());
+    assertEquals("int64", parameter.getFormat());
+  }
+
+  @Test
+  public void processOnComplexBeanParamField() throws NoSuchMethodException {
+    BeanParamAnnotationProcessor processor = new BeanParamAnnotationProcessor();
+    final OperationGenerator operationGenerator = mockOperationGenerator("testBeanParamComplexField",
+        BeanParamComplexField.class);
+
+    try {
+      processor.process(null, operationGenerator, 0);
+    } catch (Error e) {
+      assertEquals("Processing param failed, method=org.apache.servicecomb.swagger.generator.jaxrs.processor"
+              + ".annotation.BeanParamAnnotationProcessorTest$TestProvider:testBeanParamComplexField, beanParamIdx=0",
+          e.getMessage());
+      assertEquals("not allow such type of param:[class io.swagger.models.properties.RefProperty], "
+              + "param name is [q]",
+          e.getCause().getMessage());
+    }
+  }
+
+  @Test
+  public void processOnComplexBeanParamSetter() throws NoSuchMethodException {
+    BeanParamAnnotationProcessor processor = new BeanParamAnnotationProcessor();
+    final OperationGenerator operationGenerator = mockOperationGenerator("testBeanParamComplexSetter",
+        BeanParamComplexSetter.class);
+
+    try {
+      processor.process(null, operationGenerator, 0);
+    } catch (Error e) {
+      assertEquals("Processing param failed, method=org.apache.servicecomb.swagger.generator.jaxrs.processor"
+              + ".annotation.BeanParamAnnotationProcessorTest$TestProvider:testBeanParamComplexSetter, beanParamIdx=0",
+          e.getMessage());
+      assertEquals("not allow such type of param:[class io.swagger.models.properties.RefProperty], "
+              + "param name is [h]",
+          e.getCause().getMessage());
+    }
+  }
+
+  private OperationGenerator mockOperationGenerator(String methodName, Class<?>... paramTypes)
+      throws NoSuchMethodException {
+    final Method providerMethod = TestProvider.class.getDeclaredMethod(methodName, paramTypes);
+    final SwaggerGenerator swaggerGenerator = new SwaggerGenerator(new JaxrsSwaggerGeneratorContext(),
+        TestProvider.class);
+    return new OperationGenerator(swaggerGenerator, providerMethod);
+  }
+
+  static class TestProvider {
+    public String testBeanParam(@BeanParam AggregatedParam aggregatedParam) {
+      return aggregatedParam.toString();
+    }
+
+    public String testBeanParamComplexField(@BeanParam BeanParamComplexField param) {
+      return param.toString();
+    }
+
+    public String testBeanParamComplexSetter(@BeanParam BeanParamComplexSetter param) {
+      return param.toString();
+    }
+  }
+
+  static class AggregatedParam {
+    @DefaultValue("pa")
+    @PathParam("path0")
+    private String strVal;
+
+    @QueryParam("query1")
+    private int intVal;
+
+    private long longVal;
+
+    private long cookieVal;
+
+    @HeaderParam("header2")
+    private String headerVal;
+
+    public String getStrVal() {
+      return strVal;
+    }
+
+    public AggregatedParam setStrVal(String strVal) {
+      this.strVal = strVal;
+      return this;
+    }
+
+    public int getIntVal() {
+      return intVal;
+    }
+
+    public AggregatedParam setIntVal(int intVal) {
+      this.intVal = intVal;
+      return this;
+    }
+
+    public long getLongVal() {
+      return longVal;
+    }
+
+    @DefaultValue("12")
+    @FormParam("form3")
+    public AggregatedParam setLongVal(long longVal) {
+      this.longVal = longVal;
+      return this;
+    }
+
+    public long getCookieVal() {
+      return cookieVal;
+    }
+
+    @CookieParam("cookie4")
+    public AggregatedParam setCookieVal(long cookieVal) {
+      this.cookieVal = cookieVal;
+      return this;
+    }
+
+    public String getHeaderVal() {
+      return headerVal;
+    }
+
+    public AggregatedParam setHeaderVal(String headerVal) {
+      this.headerVal = headerVal;
+      return this;
+    }
+  }
+
+  static class BeanParamComplexField {
+    @QueryParam("q")
+    private AggregatedParam complex;
+
+    public AggregatedParam getComplex() {
+      return complex;
+    }
+
+    public BeanParamComplexField setComplex(
+        AggregatedParam complex) {
+      this.complex = complex;
+      return this;
+    }
+  }
+
+  static class BeanParamComplexSetter {
+    private AggregatedParam complex;
+
+    public AggregatedParam getComplex() {
+      return complex;
+    }
+
+    @HeaderParam("h")
+    public BeanParamComplexSetter setComplex(
+        AggregatedParam complex) {
+      this.complex = complex;
+      return this;
+    }
+  }
+}
\ No newline at end of file
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/CookieValueAnnotationProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/CookieValueAnnotationProcessor.java
index a6139d05c..8dc61eacd 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/CookieValueAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/CookieValueAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class CookieValueAnnotationProcessor extends AbstractParameterProcessor<CookieParameter> {
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((CookieValue) annotation).name();
   }
 
   @Override
-  protected CookieParameter createParameter() {
+  public CookieParameter createParameter() {
     return new CookieParameter();
   }
 
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/PathVariableAnnotationProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/PathVariableAnnotationProcessor.java
index c1012e7b3..e77b7785e 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/PathVariableAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/PathVariableAnnotationProcessor.java
@@ -24,12 +24,12 @@
 
 public class PathVariableAnnotationProcessor extends AbstractParameterProcessor<PathParameter> {
   @Override
-  protected PathParameter createParameter() {
+  public PathParameter createParameter() {
     return new PathParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((PathVariable) annotation).value();
   }
 }
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestAttributeAnnotationProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestAttributeAnnotationProcessor.java
index dbd5a4a77..09e5f379b 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestAttributeAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestAttributeAnnotationProcessor.java
@@ -24,12 +24,12 @@
 
 public class RequestAttributeAnnotationProcessor extends AbstractParameterProcessor<FormParameter> {
   @Override
-  protected FormParameter createParameter() {
+  public FormParameter createParameter() {
     return new FormParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((RequestAttribute) annotation).name();
   }
 }
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestHeaderAnnotationProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestHeaderAnnotationProcessor.java
index c7f55a321..d4862de33 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestHeaderAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestHeaderAnnotationProcessor.java
@@ -26,12 +26,12 @@
 
 public class RequestHeaderAnnotationProcessor extends AbstractParameterProcessor<HeaderParameter> {
   @Override
-  protected HeaderParameter createParameter() {
+  public HeaderParameter createParameter() {
     return new HeaderParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((RequestHeader) annotation).name();
   }
 
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestParamAnnotationProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestParamAnnotationProcessor.java
index e94773107..d839c1caf 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestParamAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestParamAnnotationProcessor.java
@@ -25,12 +25,12 @@
 
 public class RequestParamAnnotationProcessor extends AbstractParameterProcessor<QueryParameter> {
   @Override
-  protected QueryParameter createParameter() {
+  public QueryParameter createParameter() {
     return new QueryParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((RequestParam) annotation).name();
   }
 
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestPartAnnotationProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestPartAnnotationProcessor.java
index d1d0b4b63..39017526d 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestPartAnnotationProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/annotation/RequestPartAnnotationProcessor.java
@@ -24,12 +24,12 @@
 
 public class RequestPartAnnotationProcessor extends AbstractParameterProcessor<FormParameter> {
   @Override
-  protected FormParameter createParameter() {
+  public FormParameter createParameter() {
     return new FormParameter();
   }
 
   @Override
-  protected String getAnnotationParameterName(Object annotation) {
+  public String getAnnotationParameterName(Object annotation) {
     return ((RequestPart) annotation).name();
   }
 }
diff --git a/swagger/swagger-invocation/invocation-core/pom.xml b/swagger/swagger-invocation/invocation-core/pom.xml
index c414f455f..b9d103c73 100644
--- a/swagger/swagger-invocation/invocation-core/pom.xml
+++ b/swagger/swagger-invocation/invocation-core/pom.xml
@@ -35,7 +35,6 @@
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>swagger-generator-jaxrs</artifactId>
-      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java
index e0ba98f39..42852c17d 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerEnvironment.java
@@ -17,7 +17,9 @@
 package org.apache.servicecomb.swagger.engine;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
@@ -39,6 +41,7 @@
 import org.apache.servicecomb.swagger.invocation.response.producer.ProducerResponseMapperFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import io.swagger.annotations.ApiOperation;
@@ -51,9 +54,15 @@
   @Inject
   protected CompositeSwaggerGeneratorContext compositeSwaggerGeneratorContext;
 
+  /**
+   * default producerArgumentsFactory
+   */
   @Inject
   private ProducerArgumentsMapperFactory producerArgumentsFactory;
 
+  @Autowired
+  private List<ProducerArgumentsMapperFactory> producerArgumentsMapperFactoryList = new ArrayList<>(0);
+
   private ResponseMapperFactorys<ProducerResponseMapper> producerResponseMapperFactorys =
       new ResponseMapperFactorys<>(ProducerResponseMapperFactory.class);
 
@@ -174,7 +183,8 @@ public SwaggerProducer createProducer(Object producerInstance, Class<?> swaggerI
       config.setSwaggerOperation(swaggerOperationMap.get(methodName));
       config.setSwaggerGeneratorContext(compositeSwaggerGeneratorContext.selectContext(producerCls));
 
-      ProducerArgumentsMapper argsMapper = producerArgumentsFactory.createArgumentsMapper(config);
+      ProducerArgumentsMapperFactory argumentsMapperFactory = selectProducerArgumentsMapperFactory(config);
+      ProducerArgumentsMapper argsMapper = argumentsMapperFactory.createArgumentsMapper(config);
       ProducerResponseMapper responseMapper = producerResponseMapperFactorys.createResponseMapper(
           swaggerMethod.getGenericReturnType(),
           producerMethod.getGenericReturnType());
@@ -194,6 +204,20 @@ public SwaggerProducer createProducer(Object producerInstance, Class<?> swaggerI
     return producer;
   }
 
+  ProducerArgumentsMapperFactory selectProducerArgumentsMapperFactory(ArgumentsMapperConfig config) {
+    ProducerArgumentsMapperFactory argumentsMapperFactory = null;
+    for (ProducerArgumentsMapperFactory producerArgumentsMapperFactory : this.producerArgumentsMapperFactoryList) {
+      if (producerArgumentsMapperFactory.canProcess(config)) {
+        argumentsMapperFactory = producerArgumentsMapperFactory;
+        break;
+      }
+    }
+    if (null == argumentsMapperFactory) {
+      argumentsMapperFactory = this.producerArgumentsFactory;
+    }
+    return argumentsMapperFactory;
+  }
+
   private Map<String, Method> retrieveVisibleMethods(Class<?> clazz) {
     Map<String, Method> visibleMethods = new HashMap<>();
     for (Method method : clazz.getMethods()) {
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java
index 3d86a4962..001f80820 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ArgumentsMapperFactory.java
@@ -125,6 +125,7 @@ protected boolean isSwaggerWrapBody(ArgumentsMapperConfig config, List<ProviderP
   protected List<ProviderParameter> collectContextArgumentsMapper(ArgumentsMapperConfig config) {
     List<ProviderParameter> providerNormalParams = new ArrayList<>();
 
+    final Annotation[][] parameterAnnotations = config.getProviderMethod().getParameterAnnotations();
     Type[] providerParameterTypes = config.getProviderMethod().getGenericParameterTypes();
     for (int providerIdx = 0; providerIdx < providerParameterTypes.length; providerIdx++) {
       Type parameterType = providerParameterTypes[providerIdx];
@@ -136,7 +137,8 @@ protected boolean isSwaggerWrapBody(ArgumentsMapperConfig config, List<ProviderP
       }
 
       ProviderParameter pp = new ProviderParameter(providerIdx, parameterType,
-          retrieveVisibleParamName(config.getProviderMethod(), providerIdx));
+          retrieveVisibleParamName(config.getProviderMethod(), providerIdx))
+          .setAnnotations(parameterAnnotations[providerIdx]);
       providerNormalParams.add(pp);
     }
 
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java
index 299c02f9b..988efc15c 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/ProviderParameter.java
@@ -16,7 +16,9 @@
  */
 package org.apache.servicecomb.swagger.invocation.arguments;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
+import java.util.Arrays;
 
 public class ProviderParameter {
   private int index;
@@ -28,6 +30,8 @@
    */
   private String name;
 
+  private Annotation[] annotations;
+
   public ProviderParameter(int index, Type type, String name) {
     this.index = index;
     this.type = type;
@@ -61,12 +65,22 @@ public ProviderParameter setName(String name) {
     return this;
   }
 
+  public Annotation[] getAnnotations() {
+    return annotations;
+  }
+
+  public ProviderParameter setAnnotations(Annotation[] annotations) {
+    this.annotations = annotations;
+    return this;
+  }
+
   @Override
   public String toString() {
     final StringBuilder sb = new StringBuilder("ProviderParameter{");
     sb.append("index=").append(index);
     sb.append(", type=").append(type);
     sb.append(", name='").append(name).append('\'');
+    sb.append(", annotations=").append(Arrays.toString(annotations));
     sb.append('}');
     return sb.toString();
   }
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactory.java
new file mode 100644
index 000000000..d0b84cd21
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactory.java
@@ -0,0 +1,147 @@
+/*
+ * 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.swagger.invocation.arguments.producer;
+
+import static org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.BeanParamAnnotationProcessor.SETTER_METHOD_PREFIX;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.ws.rs.BeanParam;
+
+import org.apache.servicecomb.swagger.generator.jaxrs.processor.annotation.BeanParamAnnotationProcessor;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig;
+import org.apache.servicecomb.swagger.invocation.arguments.ProviderParameter;
+import org.springframework.stereotype.Component;
+
+import io.swagger.models.parameters.Parameter;
+
+@Component
+public class JaxRSProducerArgumentsMapperFactory extends ProducerArgumentsMapperFactory {
+  @Override
+  public boolean canProcess(ArgumentsMapperConfig config) {
+    return config.getSwaggerGeneratorContext().getClass().getCanonicalName().equals(
+        "org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext");
+  }
+
+  @Override
+  protected Set<String> findAggregatedParamNames(Map<String, ProviderParameter> providerParamMap,
+      Map<String, ParamWrapper<Parameter>> swaggerParamMap) {
+    Set<String> aggregatedParamNames = new HashSet<>();
+    for (Entry<String, ProviderParameter> providerParameterEntry : providerParamMap.entrySet()) {
+      if (null == providerParameterEntry.getValue().getAnnotations()) {
+        // request body may have no annotation
+        continue;
+      }
+      for (Annotation annotation : providerParameterEntry.getValue().getAnnotations()) {
+        if (annotation instanceof BeanParam) {
+          aggregatedParamNames.add(providerParameterEntry.getKey());
+        }
+      }
+    }
+
+    return aggregatedParamNames;
+  }
+
+  @Override
+  protected void generateAggregatedParamMapper(ArgumentsMapperConfig config,
+      Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap,
+      Set<String> aggregatedParamNames) {
+    for (String aggregatedProducerParamName : aggregatedParamNames) {
+      ProviderParameter aggregatedParam = providerParamMap.get(aggregatedProducerParamName);
+      // producer param name -> swagger param name
+      Map<String, String> producerToSwaggerParamNameMapper = getProducerToSwaggerParamNameMap(aggregatedParam);
+      // producer param name -> swagger param index
+      Map<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>(producerToSwaggerParamNameMapper.size());
+      for (Entry<String, String> producerSwaggerNameMapEntry : producerToSwaggerParamNameMapper.entrySet()) {
+        producerNameToSwaggerIndexMap.put(
+            producerSwaggerNameMapEntry.getKey(),
+            swaggerParamMap.get(producerSwaggerNameMapEntry.getValue()).getIndex());
+      }
+
+      // create&add aggregated param mapper
+      ArgumentMapper mapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap,
+          aggregatedParam.getIndex(),
+          aggregatedParam.getType());
+      config.addArgumentMapper(mapper);
+    }
+  }
+
+  /**
+   * <pre>
+   * public class AggregatedParam {
+   *   \@PathParam("pathSwaggerParam")
+   *   private String pathProducerParam;
+   *
+   *   private String queryProducerParam;
+   *
+   *   \@QueryParam(value = "querySwaggerParam")
+   *   public void setQueryProducerParam(String queryParam) {
+   *     this.queryProducerParam = queryParam;
+   *   }
+   * }
+   * </pre>
+   * Given a BeanParam like above, will return a map like below:
+   * {
+   *   "pathProducerParam" -> "pathSwaggerParam",
+   *   "queryProducerParam" -> "querySwaggerParam"
+   * }
+   */
+  private Map<String, String> getProducerToSwaggerParamNameMap(ProviderParameter aggregatedParam) {
+    Map<String, String> producerToSwaggerParamNameMapper = new HashMap<>();
+    Class<?> aggregatedParamClazz = (Class<?>) aggregatedParam.getType();
+    // map those params defined by BeanParam fields
+    for (Field field : aggregatedParamClazz.getDeclaredFields()) {
+      for (Annotation fieldAnnotation : field.getAnnotations()) {
+        if (BeanParamAnnotationProcessor.SUPPORTED_PARAM_ANNOTATIONS.contains(fieldAnnotation.annotationType())) {
+          producerToSwaggerParamNameMapper.put(
+              field.getName(),
+              retrieveVisibleParamName(fieldAnnotation));
+          break;
+        }
+      }
+    }
+    // map those params defined by setter methods
+    for (Method method : aggregatedParamClazz.getDeclaredMethods()) {
+      final String methodName = method.getName();
+      if (!methodName.startsWith(SETTER_METHOD_PREFIX)) {
+        // only process setter methods
+        continue;
+      }
+      // There should be one and only one param in a setter method
+      for (Annotation setterAnnotation : method.getAnnotations()) {
+        if (BeanParamAnnotationProcessor.SUPPORTED_PARAM_ANNOTATIONS.contains(setterAnnotation.annotationType())) {
+          producerToSwaggerParamNameMapper.put(
+              methodName.substring( // setParamName() -> "paramName"
+                  SETTER_METHOD_PREFIX.length(), SETTER_METHOD_PREFIX.length() + 1).toLowerCase()
+                  + methodName.substring(SETTER_METHOD_PREFIX.length() + 1),
+              retrieveVisibleParamName(setterAnnotation));
+          break;
+        }
+      }
+    }
+    return producerToSwaggerParamNameMapper;
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java
index 204dea9fa..4babe0051 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerArgumentsMapperFactory.java
@@ -18,8 +18,8 @@
 package org.apache.servicecomb.swagger.invocation.arguments.producer;
 
 import java.lang.reflect.Type;
+import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -27,7 +27,7 @@
 
 import javax.inject.Inject;
 
-import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
+import org.apache.servicecomb.swagger.generator.rest.RestSwaggerGeneratorContext;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper;
 import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig;
@@ -39,16 +39,15 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Component;
 
-import io.swagger.converter.ModelConverters;
 import io.swagger.models.parameters.Parameter;
-import io.swagger.models.parameters.QueryParameter;
-import io.swagger.models.properties.Property;
-import io.swagger.models.properties.RefProperty;
 
 @Component
+@Primary
 public class ProducerArgumentsMapperFactory extends ArgumentsMapperFactory<ProducerArgumentsMapper> {
+
   private static final Logger LOGGER = LoggerFactory.getLogger(ProducerArgumentsMapperFactory.class);
 
   public ProducerArgumentsMapperFactory() {
@@ -69,46 +68,50 @@ public ProducerArgumentsMapper createArgumentsMapper(ArgumentsMapperConfig confi
         config.getProviderMethod().getParameterCount());
   }
 
+  public boolean canProcess(ArgumentsMapperConfig config) {
+    return false;
+  }
+
   @Override
   protected void collectSwaggerArgumentsMapper(ArgumentsMapperConfig config,
       List<ProviderParameter> providerNormalParams) {
-    if (!config.getSwaggerGeneratorContext().getClass().getCanonicalName().equals(
-        "org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGeneratorContext")) {
-      // if this is not a SpringMVC style provider operation, there is no need to consider query object param
+    if (!RestSwaggerGeneratorContext.class.isInstance(config.getSwaggerGeneratorContext())) {
+      // POJO style provider does not support aggregated param
       super.collectSwaggerArgumentsMapper(config, providerNormalParams);
       return;
     }
 
+    // JAX-RS and SpringMVC style provider support aggregated param, i.e. @BeanParam and query object, respectively
     Map<String, ProviderParameter> providerParamMap = getProviderParamMap(providerNormalParams);
     Map<String, ParamWrapper<Parameter>> swaggerParamMap = getSwaggerParamMap(config);
 
-    Set<String> queryObjectNames = findSpringMvcQueryObject(providerParamMap, swaggerParamMap);
-    if (queryObjectNames.isEmpty()) {
-      // there is no query object param, run as 1-to-1 param mapping mode
+    Set<String> aggregatedParamNames = findAggregatedParamNames(providerParamMap, swaggerParamMap);
+    if (aggregatedParamNames.isEmpty()) {
+      // there is no aggregated param, run as 1-to-1 param mapping mode
       super.collectSwaggerArgumentsMapper(config, providerNormalParams);
       return;
     }
 
-    // There is at lease one query object param, so the param mapping mode becomes to M-to-N
+    // There is at lease one aggregated param, so the param mapping mode becomes to M-to-N
     // try to map params by name
-    generateParamMapperByName(config, providerParamMap, swaggerParamMap, queryObjectNames);
+    generateParamMapperByName(config, providerParamMap, swaggerParamMap, aggregatedParamNames);
   }
 
   private void generateParamMapperByName(ArgumentsMapperConfig config, Map<String, ProviderParameter> providerParamMap,
-      Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> queryObjectNames) {
-    LOGGER.info("mapping query object params: [{}]", queryObjectNames);
-    generateObjectQueryParamMapper(config, providerParamMap, swaggerParamMap, queryObjectNames);
-    generateDefaultParamMapper(config, providerParamMap, swaggerParamMap, queryObjectNames);
+      Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> aggregatedParamNames) {
+    LOGGER.info("mapping aggregated params: [{}]", aggregatedParamNames);
+    generateAggregatedParamMapper(config, providerParamMap, swaggerParamMap, aggregatedParamNames);
+    generateDefaultParamMapper(config, providerParamMap, swaggerParamMap, aggregatedParamNames);
   }
 
   /**
    * Generate default argument mappers. One swagger argument is mapped to one producer argument.
    */
   private void generateDefaultParamMapper(ArgumentsMapperConfig config, Map<String, ProviderParameter> providerParamMap,
-      Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> queryObjectNames) {
+      Map<String, ParamWrapper<Parameter>> swaggerParamMap, Set<String> aggregatedParamNames) {
     Type[] swaggerParamTypes = config.getSwaggerMethod().getGenericParameterTypes();
     for (Entry<String, ProviderParameter> providerParamEntry : providerParamMap.entrySet()) {
-      if (queryObjectNames.contains(providerParamEntry.getKey())) {
+      if (aggregatedParamNames.contains(providerParamEntry.getKey())) {
         continue;
       }
 
@@ -122,31 +125,21 @@ private void generateDefaultParamMapper(ArgumentsMapperConfig config, Map<String
   }
 
   /**
-   * Generate argument mappers for query object params. Collect all query params as json and map them to object param.
+   * Generate argument mappers for aggregated params.
+   * Collect related swagger params and map them to an aggregated param.
+   * It's implemented by SpringMVC and JAX-RS.
    */
-  private void generateObjectQueryParamMapper(ArgumentsMapperConfig config,
+  protected void generateAggregatedParamMapper(ArgumentsMapperConfig config,
       Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap,
-      Set<String> queryObjectNames) {
-    // collect all query params
-    Map<String, Integer> querySwaggerParamsIndex = new HashMap<>();
-    for (Entry<String, ParamWrapper<Parameter>> wrapperEntry : swaggerParamMap.entrySet()) {
-      if (wrapperEntry.getValue().getParam() instanceof QueryParameter) {
-        querySwaggerParamsIndex.put(wrapperEntry.getKey(), wrapperEntry.getValue().getIndex());
-      }
-    }
-    // create mapper for each query objects
-    for (String queryObjectName : queryObjectNames) {
-      final ProviderParameter providerParameter = providerParamMap.get(queryObjectName);
-      ArgumentMapper mapper = new ProducerSpringMVCQueryObjectMapper(querySwaggerParamsIndex,
-          providerParameter.getIndex(),
-          providerParameter.getType());
-      config.addArgumentMapper(mapper);
-    }
+      Set<String> aggregatedParamNames) {
+    // do nothing, not supported by default
   }
 
-  private Map<String, ParamWrapper<Parameter>> getSwaggerParamMap(ArgumentsMapperConfig config) {
-    Map<String, ParamWrapper<Parameter>> swaggerParamMap =
-        new HashMap<>(config.getSwaggerOperation().getParameters().size());
+  protected Map<String, ParamWrapper<Parameter>> getSwaggerParamMap(ArgumentsMapperConfig config) {
+    Map<String, ParamWrapper<Parameter>> swaggerParamMap = new HashMap<>();
+    if (null == config.getSwaggerOperation() || null == config.getSwaggerOperation().getParameters()) {
+      return swaggerParamMap;
+    }
     List<Parameter> parameters = config.getSwaggerOperation().getParameters();
     for (int i = 0; i < parameters.size(); i++) {
       Parameter parameter = parameters.get(i);
@@ -155,7 +148,7 @@ private void generateObjectQueryParamMapper(ArgumentsMapperConfig config,
     return swaggerParamMap;
   }
 
-  private Map<String, ProviderParameter> getProviderParamMap(List<ProviderParameter> providerNormalParams) {
+  protected Map<String, ProviderParameter> getProviderParamMap(List<ProviderParameter> providerNormalParams) {
     Map<String, ProviderParameter> providerParamMap = new HashMap<>(providerNormalParams.size());
     providerNormalParams.forEach(
         providerParameter -> providerParamMap.put(providerParameter.getName(), providerParameter));
@@ -163,29 +156,12 @@ private void generateObjectQueryParamMapper(ArgumentsMapperConfig config,
   }
 
   /**
-   * Find all query object params
-   * @return the names of the query object params
+   * Find all aggregated params
+   * @return the names of the aggregated params
    */
-  private Set<String> findSpringMvcQueryObject(Map<String, ProviderParameter> providerParamMap,
+  protected Set<String> findAggregatedParamNames(Map<String, ProviderParameter> providerParamMap,
       Map<String, ParamWrapper<Parameter>> swaggerParamMap) {
-    // find all reference type producer params, and exclude body param
-    Set<String> queryObjectSet = new HashSet<>();
-
-    for (Entry<String, ProviderParameter> paramEntry : providerParamMap.entrySet()) {
-      Type paramType = paramEntry.getValue().getType();
-      Property property = ModelConverters.getInstance().readAsProperty(paramType);
-      if (RefProperty.class.isInstance(property)) {
-        queryObjectSet.add(paramEntry.getKey());
-      }
-    }
-
-    for (Entry<String, ParamWrapper<Parameter>> paramEntry : swaggerParamMap.entrySet()) {
-      if (ParamUtils.isRealBodyParameter(paramEntry.getValue().getParam())) {
-        queryObjectSet.remove(paramEntry.getKey());
-      }
-    }
-
-    return queryObjectSet;
+    return Collections.emptySet();
   }
 
   @Override
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapper.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapper.java
new file mode 100644
index 000000000..b72b7c9cc
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapper.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.swagger.invocation.arguments.producer;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper;
+import org.apache.servicecomb.swagger.invocation.converter.Converter;
+import org.apache.servicecomb.swagger.invocation.converter.impl.ConverterCommon;
+
+public class ProducerBeanParamMapper implements ArgumentMapper {
+
+  private int producerIdx;
+
+  private Map<String, Integer> swaggerParamIndexMap;
+
+  private Converter converter;
+
+  /**
+   * @param producerNameToSwaggerIndexMap name of the fields & setters defined in @BeanParam parameter -> swagger param index
+   * @param producerIdx index of producer param
+   * @param producerParamType type of producer param
+   */
+  public ProducerBeanParamMapper(Map<String, Integer> producerNameToSwaggerIndexMap, int producerIdx,
+      Type producerParamType) {
+    this.producerIdx = producerIdx;
+    this.swaggerParamIndexMap = new HashMap<>();
+    this.swaggerParamIndexMap.putAll(producerNameToSwaggerIndexMap);
+    converter = new ConverterCommon(producerParamType);
+  }
+
+  @Override
+  public void mapArgument(SwaggerInvocation invocation, Object[] producerArguments) {
+    Map<String, Object> jsonMap = new HashMap<>(swaggerParamIndexMap.size());
+
+    for (Entry<String, Integer> swaggerIndexEntry : swaggerParamIndexMap.entrySet()) {
+      jsonMap.put(swaggerIndexEntry.getKey(), invocation.getSwaggerArgument(swaggerIndexEntry.getValue()));
+    }
+
+    final Object producerParam = converter.convert(jsonMap);
+    producerArguments[producerIdx] = producerParam;
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/SpringMVCProducerArgumentsMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/SpringMVCProducerArgumentsMapperFactory.java
new file mode 100644
index 000000000..f7d1edad0
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/arguments/producer/SpringMVCProducerArgumentsMapperFactory.java
@@ -0,0 +1,94 @@
+/*
+ * 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.swagger.invocation.arguments.producer;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig;
+import org.apache.servicecomb.swagger.invocation.arguments.ProviderParameter;
+import org.springframework.stereotype.Component;
+
+import io.swagger.converter.ModelConverters;
+import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.QueryParameter;
+import io.swagger.models.properties.Property;
+import io.swagger.models.properties.RefProperty;
+
+@Component
+public class SpringMVCProducerArgumentsMapperFactory extends ProducerArgumentsMapperFactory {
+
+  @Override
+  public boolean canProcess(ArgumentsMapperConfig config) {
+    return config.getSwaggerGeneratorContext().getClass().getCanonicalName().equals(
+        "org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGeneratorContext");
+  }
+
+  /**
+   * Find all query object params
+   * @return the names of the query object params
+   */
+  @Override
+  protected Set<String> findAggregatedParamNames(Map<String, ProviderParameter> providerParamMap,
+      Map<String, ParamWrapper<Parameter>> swaggerParamMap) {
+    // find all reference type producer params, and exclude body param
+    Set<String> queryObjectSet = new HashSet<>();
+
+    for (Entry<String, ProviderParameter> paramEntry : providerParamMap.entrySet()) {
+      Type paramType = paramEntry.getValue().getType();
+      Property property = ModelConverters.getInstance().readAsProperty(paramType);
+      if (RefProperty.class.isInstance(property)) {
+        queryObjectSet.add(paramEntry.getKey());
+      }
+    }
+
+    for (Entry<String, ParamWrapper<Parameter>> paramEntry : swaggerParamMap.entrySet()) {
+      if (ParamUtils.isRealBodyParameter(paramEntry.getValue().getParam())) {
+        queryObjectSet.remove(paramEntry.getKey());
+      }
+    }
+
+    return queryObjectSet;
+  }
+
+  protected void generateAggregatedParamMapper(ArgumentsMapperConfig config,
+      Map<String, ProviderParameter> providerParamMap, Map<String, ParamWrapper<Parameter>> swaggerParamMap,
+      Set<String> aggregatedParamNames) {
+    // collect all query params
+    Map<String, Integer> querySwaggerParamsIndex = new HashMap<>();
+    for (Entry<String, ParamWrapper<Parameter>> wrapperEntry : swaggerParamMap.entrySet()) {
+      if (wrapperEntry.getValue().getParam() instanceof QueryParameter) {
+        querySwaggerParamsIndex.put(wrapperEntry.getKey(), wrapperEntry.getValue().getIndex());
+      }
+    }
+    // create mapper for each query objects
+    for (String queryObjectName : aggregatedParamNames) {
+      final ProviderParameter providerParameter = providerParamMap.get(queryObjectName);
+      ArgumentMapper mapper = new ProducerSpringMVCQueryObjectMapper(querySwaggerParamsIndex,
+          providerParameter.getIndex(),
+          providerParameter.getType());
+      config.addArgumentMapper(mapper);
+    }
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/engine/TestSwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/engine/TestSwaggerEnvironment.java
deleted file mode 100644
index 82c6ad40c..000000000
--- a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/engine/TestSwaggerEnvironment.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.engine;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
-
-import org.apache.servicecomb.common.javassist.JavassistUtils;
-import org.apache.servicecomb.swagger.engine.SwaggerConsumer;
-import org.apache.servicecomb.swagger.engine.SwaggerProducer;
-import org.apache.servicecomb.swagger.invocation.models.ProducerImpl;
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestSwaggerEnvironment {
-  private static SwaggerEnvironmentForTest env = new SwaggerEnvironmentForTest();
-
-  private static SwaggerProducer producer;
-
-  @BeforeClass
-  public static void init() {
-    producer = env.createProducer(new ProducerImpl());
-  }
-
-  @AfterClass
-  public static void tearDown() {
-    JavassistUtils.clearByClassLoader(env.getClassLoader());
-  }
-
-  @Test
-  public void ableToFindVisibleMethod() {
-    assertThat(producer.findOperation("visibleMethod"), is(notNullValue()));
-  }
-
-  @Test
-  public void unableToFindHiddenMethod() {
-    assertThat(producer.findOperation("hiddenMethod"), is(nullValue()));
-  }
-
-  interface ConsumerIntf {
-    void exist();
-
-    void notExist();
-  }
-
-  interface ContractIntf {
-    void exist();
-  }
-
-  @Test
-  public void createConsumer_consumerMethodSetBigger() {
-    SwaggerConsumer swaggerConsumer = env.getSwaggerEnvironment()
-        .createConsumer(ConsumerIntf.class, ContractIntf.class);
-
-    Assert.assertNotNull(swaggerConsumer.findOperation("exist"));
-    Assert.assertNull(swaggerConsumer.findOperation("notExist"));
-  }
-}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/engine/TestSwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/engine/TestSwaggerEnvironment.java
new file mode 100644
index 000000000..0a888cce4
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/engine/TestSwaggerEnvironment.java
@@ -0,0 +1,121 @@
+/*
+ * 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.swagger.engine;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.common.javassist.JavassistUtils;
+import org.apache.servicecomb.engine.SwaggerEnvironmentForTest;
+import org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext;
+import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGeneratorContext;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.JaxRSProducerArgumentsMapperFactory;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapperFactory;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.SpringMVCProducerArgumentsMapperFactory;
+import org.apache.servicecomb.swagger.invocation.models.ProducerImpl;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import mockit.Deencapsulation;
+
+public class TestSwaggerEnvironment {
+  private static SwaggerEnvironmentForTest env = new SwaggerEnvironmentForTest();
+
+  private static SwaggerProducer producer;
+
+  private static ProducerArgumentsMapperFactory defaultProducerArgumentsMapperFactory;
+
+  @BeforeClass
+  public static void init() {
+    producer = env.createProducer(new ProducerImpl());
+    defaultProducerArgumentsMapperFactory = new ProducerArgumentsMapperFactory();
+    List<ProducerArgumentsMapperFactory> producerArgumentsMapperFactoryList = new ArrayList<>();
+    producerArgumentsMapperFactoryList.add(new JaxRSProducerArgumentsMapperFactory());
+    producerArgumentsMapperFactoryList.add(new SpringMVCProducerArgumentsMapperFactory());
+    producerArgumentsMapperFactoryList.add(new ProducerArgumentsMapperFactory());
+
+    Deencapsulation.setField(
+        env.getSwaggerEnvironment(), "producerArgumentsFactory", defaultProducerArgumentsMapperFactory);
+    Deencapsulation.setField(
+        env.getSwaggerEnvironment(), "producerArgumentsMapperFactoryList", producerArgumentsMapperFactoryList);
+  }
+
+  @AfterClass
+  public static void tearDown() {
+    JavassistUtils.clearByClassLoader(env.getClassLoader());
+  }
+
+  @Test
+  public void ableToFindVisibleMethod() {
+    assertThat(producer.findOperation("visibleMethod"), is(notNullValue()));
+  }
+
+  @Test
+  public void unableToFindHiddenMethod() {
+    assertThat(producer.findOperation("hiddenMethod"), is(nullValue()));
+  }
+
+  interface ConsumerIntf {
+    void exist();
+
+    void notExist();
+  }
+
+  interface ContractIntf {
+    void exist();
+  }
+
+  @Test
+  public void createConsumer_consumerMethodSetBigger() {
+    SwaggerConsumer swaggerConsumer = env.getSwaggerEnvironment()
+        .createConsumer(ConsumerIntf.class, ContractIntf.class);
+
+    Assert.assertNotNull(swaggerConsumer.findOperation("exist"));
+    Assert.assertNull(swaggerConsumer.findOperation("notExist"));
+  }
+
+  @Test
+  public void selectProducerArgumentsMapperFactory() {
+    final ArgumentsMapperConfig config = new ArgumentsMapperConfig();
+    config.setSwaggerGeneratorContext(new JaxrsSwaggerGeneratorContext());
+
+    final ProducerArgumentsMapperFactory producerArgumentsMapperFactory = env.getSwaggerEnvironment()
+        .selectProducerArgumentsMapperFactory(config);
+
+    Assert.assertEquals(JaxRSProducerArgumentsMapperFactory.class, producerArgumentsMapperFactory.getClass());
+  }
+
+  @Test
+  public void selectProducerArgumentsMapperFactoryOnReturnDefault() {
+    final ArgumentsMapperConfig config = new ArgumentsMapperConfig();
+    config.setSwaggerGeneratorContext(new PojoSwaggerGeneratorContext());
+
+    final ProducerArgumentsMapperFactory producerArgumentsMapperFactory = env.getSwaggerEnvironment()
+        .selectProducerArgumentsMapperFactory(config);
+
+    Assert.assertSame(defaultProducerArgumentsMapperFactory, producerArgumentsMapperFactory);
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactoryTest.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactoryTest.java
new file mode 100644
index 000000000..751920378
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/JaxRSProducerArgumentsMapperFactoryTest.java
@@ -0,0 +1,229 @@
+/*
+ * 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.swagger.invocation.arguments.producer;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.Part;
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.swagger.generator.jaxrs.JaxrsSwaggerGeneratorContext;
+import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGeneratorContext;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapperConfig;
+import org.apache.servicecomb.swagger.invocation.arguments.ProviderParameter;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapperFactory.ParamWrapper;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.swagger.models.parameters.CookieParameter;
+import io.swagger.models.parameters.FormParameter;
+import io.swagger.models.parameters.HeaderParameter;
+import io.swagger.models.parameters.Parameter;
+import io.swagger.models.parameters.PathParameter;
+import io.swagger.models.parameters.QueryParameter;
+import mockit.Deencapsulation;
+
+public class JaxRSProducerArgumentsMapperFactoryTest {
+
+  private final JaxRSProducerArgumentsMapperFactory producerArgumentsMapperFactory = new JaxRSProducerArgumentsMapperFactory();
+
+  @Test
+  public void canProcess() {
+    ArgumentsMapperConfig argumentsMapperConfig = new ArgumentsMapperConfig();
+
+    argumentsMapperConfig.setSwaggerGeneratorContext(new JaxrsSwaggerGeneratorContext());
+    Assert.assertTrue(producerArgumentsMapperFactory.canProcess(argumentsMapperConfig));
+
+    argumentsMapperConfig.setSwaggerGeneratorContext(new PojoSwaggerGeneratorContext());
+    Assert.assertFalse(producerArgumentsMapperFactory.canProcess(argumentsMapperConfig));
+  }
+
+  @Test
+  public void findAggregatedParamNames() throws NoSuchMethodException {
+    Map<String, ProviderParameter> providerParamMap = new HashMap<>();
+    providerParamMap.put("qqq", new ProviderParameter(1, String.class, "qqq"));
+    Method aggregatedTestParamMethod = AggregatedParamProvider.class
+        .getMethod("aggregatedParamTest", AggregatedTestParam.class);
+    Annotation beanParamAnnotation = aggregatedTestParamMethod.getParameterAnnotations()[0][0];
+    providerParamMap.put("aggregatedTestParam",
+        new ProviderParameter(0, AggregatedTestParam.class, "aggregatedTestParam")
+            .setAnnotations(new Annotation[] {beanParamAnnotation}));
+
+    Map<String, ParamWrapper<Parameter>> swaggerParamMap = new HashMap<>();
+    Parameter swaggerParam = new PathParameter().name("pathSwaggerParam");
+    swaggerParamMap.put("pathSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(0));
+    swaggerParam = new HeaderParameter().name("headerSwaggerParam");
+    swaggerParamMap.put("headerSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(1));
+    swaggerParam = new CookieParameter().name("intSwaggerVal");
+    swaggerParamMap.put("intSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(2));
+    swaggerParam = new FormParameter().name("longSwaggerVal");
+    swaggerParamMap.put("longSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(3));
+    swaggerParam = new QueryParameter().name("querySwaggerParam");
+    swaggerParamMap.put("querySwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(4));
+    swaggerParam = new FormParameter().name("uploadSwaggerParam");
+    swaggerParamMap.put("uploadSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(5));
+    swaggerParam = new QueryParameter().name("qqq");
+    swaggerParamMap.put("qqq", new ParamWrapper<>(swaggerParam).setIndex(6));
+
+    Set<String> aggregatedParamNames = producerArgumentsMapperFactory
+        .findAggregatedParamNames(providerParamMap, swaggerParamMap);
+    Assert.assertThat(aggregatedParamNames, Matchers.contains("aggregatedTestParam"));
+  }
+
+  @Test
+  public void generateAggregatedParamMapper() throws NoSuchMethodException {
+    Map<String, ProviderParameter> providerParamMap = new HashMap<>();
+    providerParamMap.put("qqq", new ProviderParameter(1, String.class, "qqq"));
+    Method aggregatedTestParamMethod = AggregatedParamProvider.class
+        .getMethod("aggregatedParamTest", AggregatedTestParam.class);
+    Annotation beanParamAnnotation = aggregatedTestParamMethod.getParameterAnnotations()[0][0];
+    providerParamMap.put("aggregatedTestParam",
+        new ProviderParameter(0, AggregatedTestParam.class, "aggregatedTestParam")
+            .setAnnotations(new Annotation[] {beanParamAnnotation}));
+
+    Map<String, ParamWrapper<Parameter>> swaggerParamMap = new HashMap<>();
+    Parameter swaggerParam = new PathParameter().name("pathSwaggerParam");
+    swaggerParamMap.put("pathSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(0));
+    swaggerParam = new HeaderParameter().name("headerSwaggerParam");
+    swaggerParamMap.put("headerSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(1));
+    swaggerParam = new CookieParameter().name("intSwaggerVal");
+    swaggerParamMap.put("intSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(2));
+    swaggerParam = new FormParameter().name("longSwaggerVal");
+    swaggerParamMap.put("longSwaggerVal", new ParamWrapper<>(swaggerParam).setIndex(3));
+    swaggerParam = new QueryParameter().name("querySwaggerParam");
+    swaggerParamMap.put("querySwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(4));
+    swaggerParam = new FormParameter().name("uploadSwaggerParam");
+    swaggerParamMap.put("uploadSwaggerParam", new ParamWrapper<>(swaggerParam).setIndex(5));
+    swaggerParam = new QueryParameter().name("qqq");
+    swaggerParamMap.put("qqq", new ParamWrapper<>(swaggerParam).setIndex(6));
+
+    Set<String> aggregatedParamNames = new HashSet<>();
+    aggregatedParamNames.add("aggregatedTestParam");
+    ArgumentsMapperConfig argumentsMapperConfig = new ArgumentsMapperConfig();
+    producerArgumentsMapperFactory.generateAggregatedParamMapper(
+        argumentsMapperConfig, providerParamMap, swaggerParamMap, aggregatedParamNames);
+
+    Assert.assertEquals(1, argumentsMapperConfig.getArgumentMapperList().size());
+    Assert.assertEquals(ProducerBeanParamMapper.class, argumentsMapperConfig.getArgumentMapperList().get(0).getClass());
+    ProducerBeanParamMapper producerBeanParamMapper =
+        (ProducerBeanParamMapper) argumentsMapperConfig.getArgumentMapperList().get(0);
+    Assert.assertEquals(Integer.valueOf(0), Deencapsulation.getField(producerBeanParamMapper, "producerIdx"));
+    Map<String, Integer> swaggerParamIndexMap =
+        Deencapsulation.getField(producerBeanParamMapper, "swaggerParamIndexMap");
+    Assert.assertEquals(Integer.valueOf(0), swaggerParamIndexMap.get("pathParam"));
+    Assert.assertEquals(Integer.valueOf(1), swaggerParamIndexMap.get("headerParam"));
+    Assert.assertEquals(Integer.valueOf(2), swaggerParamIndexMap.get("intVal"));
+    Assert.assertEquals(Integer.valueOf(3), swaggerParamIndexMap.get("longVal"));
+    Assert.assertEquals(Integer.valueOf(4), swaggerParamIndexMap.get("q"));
+    Assert.assertEquals(Integer.valueOf(5), swaggerParamIndexMap.get("uploaded"));
+  }
+
+  static class AggregatedParamProvider {
+    public String aggregatedParamTest(@BeanParam AggregatedTestParam aggregatedTestParam) {
+      return null;
+    }
+  }
+
+  static class AggregatedTestParam {
+    @PathParam("pathSwaggerParam")
+    private String pathParam;
+
+    private String queryParam;
+
+    @DefaultValue("defaultHeader")
+    @HeaderParam(value = "headerSwaggerParam")
+    private String headerParam;
+
+    @CookieParam("intSwaggerVal")
+    private int intVal;
+
+    @FormParam("longSwaggerVal")
+    private long longVal;
+
+    private Part uploaded;
+
+    public String getPathParam() {
+      return pathParam;
+    }
+
+    public AggregatedTestParam setPathParam(String pathParam) {
+      this.pathParam = pathParam;
+      return this;
+    }
+
+    public String getQ() {
+      return queryParam;
+    }
+
+    @DefaultValue("defaultQuery")
+    @QueryParam(value = "querySwaggerParam")
+    public AggregatedTestParam setQ(String queryParam) {
+      this.queryParam = queryParam;
+      return this;
+    }
+
+    public String getHeaderParam() {
+      return headerParam;
+    }
+
+    public AggregatedTestParam setHeaderParam(String headerParam) {
+      this.headerParam = headerParam;
+      return this;
+    }
+
+    public int getIntVal() {
+      return intVal;
+    }
+
+    public AggregatedTestParam setIntVal(int intVal) {
+      this.intVal = intVal;
+      return this;
+    }
+
+    public long getLongVal() {
+      return longVal;
+    }
+
+    public AggregatedTestParam setLongVal(long longVal) {
+      this.longVal = longVal;
+      return this;
+    }
+
+    public Part getUploaded() {
+      return uploaded;
+    }
+
+    @FormParam("uploadSwaggerParam")
+    public AggregatedTestParam setUploaded(Part uploaded) {
+      this.uploaded = uploaded;
+      return this;
+    }
+  }
+}
\ No newline at end of file
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapperTest.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapperTest.java
new file mode 100644
index 000000000..81c8d35bd
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/arguments/producer/ProducerBeanParamMapperTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.swagger.invocation.arguments.producer;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Objects;
+
+import javax.servlet.http.Part;
+
+import org.apache.servicecomb.foundation.common.part.AbstractPart;
+import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+import org.apache.servicecomb.swagger.invocation.arguments.ArgumentMapper;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerSpringMVCQueryObjectMapperTest.RecursiveParam;
+import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerSpringMVCQueryObjectMapperTest.TestParam;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ProducerBeanParamMapperTest {
+
+  @Test
+  public void mapArgument() {
+    final HashMap<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>();
+    producerNameToSwaggerIndexMap.put("name", 2);
+    producerNameToSwaggerIndexMap.put("age", 0);
+    ArgumentMapper argumentMapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, 0, TestParam.class);
+    SwaggerInvocation swaggerInvocation = new SwaggerInvocation();
+    swaggerInvocation.setSwaggerArguments(new Object[] {22, "abc", "nameTest"});
+
+    final Object[] producerArguments = new Object[1];
+    argumentMapper.mapArgument(swaggerInvocation, producerArguments);
+    Assert.assertEquals(producerArguments[0], new TestParam().setName("nameTest").setAge(22));
+  }
+
+  @Test
+  public void mapArgumentOnRecursiveParam() {
+    final HashMap<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>();
+    producerNameToSwaggerIndexMap.put("num", 0);
+    producerNameToSwaggerIndexMap.put("str", 1);
+    producerNameToSwaggerIndexMap.put("date", 2);
+    ArgumentMapper argumentMapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, 1,
+        RecursiveParam.class);
+    SwaggerInvocation swaggerInvocation = new SwaggerInvocation();
+    final Date testDate = new Date();
+    swaggerInvocation.setSwaggerArguments(new Object[] {2, "str0_0", testDate});
+
+    final Object[] producerArguments = new Object[2];
+    argumentMapper.mapArgument(swaggerInvocation, producerArguments);
+    Assert.assertNull(producerArguments[0]);
+    Assert.assertEquals(producerArguments[1], new RecursiveParam().setNum(2).setStr("str0_0").setDate(testDate));
+  }
+
+  @Test
+  public void mapArgumentWithPart() {
+    final HashMap<String, Integer> producerNameToSwaggerIndexMap = new HashMap<>();
+    producerNameToSwaggerIndexMap.put("up", 0);
+    producerNameToSwaggerIndexMap.put("str", 2);
+    producerNameToSwaggerIndexMap.put("longValue", 3);
+    ArgumentMapper argumentMapper = new ProducerBeanParamMapper(producerNameToSwaggerIndexMap, 0,
+        TestParamWithPart.class);
+    SwaggerInvocation swaggerInvocation = new SwaggerInvocation();
+    final AbstractPart uploadedFile = new AbstractPart();
+    swaggerInvocation.setSwaggerArguments(new Object[] {uploadedFile, 123L, "testString", 12L});
+
+    final Object[] producerArguments = new Object[2];
+    argumentMapper.mapArgument(swaggerInvocation, producerArguments);
+    Assert.assertEquals(producerArguments[0], new TestParamWithPart("testString", 12L, uploadedFile));
+    Assert.assertSame(((TestParamWithPart) producerArguments[0]).getUp(), uploadedFile);
+    Assert.assertNull(producerArguments[1]);
+  }
+
+  static class TestParamWithPart {
+    private String str;
+
+    private long longValue;
+
+    private Part uploaded;
+
+    public TestParamWithPart() {
+    }
+
+    public TestParamWithPart(String str, long longValue, Part uploaded) {
+      this.str = str;
+      this.longValue = longValue;
+      this.uploaded = uploaded;
+    }
+
+    public String getStr() {
+      return str;
+    }
+
+    public void setStr(String str) {
+      this.str = str;
+    }
+
+    public long getLongValue() {
+      return longValue;
+    }
+
+    public void setLongValue(long longValue) {
+      this.longValue = longValue;
+    }
+
+    public Part getUp() {
+      return uploaded;
+    }
+
+    public void setUp(Part uploaded) {
+      this.uploaded = uploaded;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+      TestParamWithPart that = (TestParamWithPart) o;
+      return longValue == that.longValue &&
+          Objects.equals(str, that.str) &&
+          Objects.equals(uploaded, that.uploaded);
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(str, longValue, uploaded);
+    }
+  }
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Support @BeanParam annotation in JAX-RS developing style
> --------------------------------------------------------
>
>                 Key: SCB-777
>                 URL: https://issues.apache.org/jira/browse/SCB-777
>             Project: Apache ServiceComb
>          Issue Type: New Feature
>            Reporter: YaoHaishi
>            Assignee: YaoHaishi
>            Priority: Minor
>             Fix For: java-chassis-1.1.0
>
>
> @BeanParam usage reference: https://docs.oracle.com/javaee/7/api/javax/ws/rs/BeanParam.html
> We need to support such kind of param annotation.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)