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

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

liubao68 closed pull request #837: [SCB-775]support invoke service using raw 
type like JsonObject & String
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/837
 
 
   

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/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/AbstractRestObjectMapper.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/AbstractRestObjectMapper.java
new file mode 100644
index 000000000..8a7ab0e1d
--- /dev/null
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/AbstractRestObjectMapper.java
@@ -0,0 +1,24 @@
+/*
+ * 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.common.rest.codec;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public abstract class AbstractRestObjectMapper extends ObjectMapper {
+  abstract public String convertToString(Object value) throws Exception;
+}
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
index b0679f4a0..617e86be7 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java
@@ -17,25 +17,37 @@
 
 package org.apache.servicecomb.common.rest.codec;
 
+import java.io.IOException;
 import java.text.FieldPosition;
 import java.util.Date;
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonParser.Feature;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
-public final class RestObjectMapper extends ObjectMapper {
-  public static final RestObjectMapper INSTANCE = new RestObjectMapper();
+import io.vertx.core.json.JsonObject;
+
+public class RestObjectMapper extends AbstractRestObjectMapper {
+  private static class JsonObjectSerializer extends JsonSerializer<JsonObject> 
{
+    @Override
+    public void serialize(JsonObject value, JsonGenerator jgen, 
SerializerProvider provider) throws IOException {
+      jgen.writeObject(value.getMap());
+    }
+  }
 
   private static final long serialVersionUID = -8158869347066287575L;
 
   private static final JavaType STRING_JAVA_TYPE = 
TypeFactory.defaultInstance().constructType(String.class);
 
   @SuppressWarnings("deprecation")
-  private RestObjectMapper() {
+  public RestObjectMapper() {
     // swagger中要求date使用ISO8601格式传递,这里与之做了功能绑定,这在cse中是没有问题的
     setDateFormat(new com.fasterxml.jackson.databind.util.ISO8601DateFormat() {
       private static final long serialVersionUID = 7798938088541203312L;
@@ -54,9 +66,20 @@ public StringBuffer format(Date date, StringBuffer 
toAppendTo, FieldPosition fie
     disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
     enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
     enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
+
+    SimpleModule module = new SimpleModule();
+    // custom types
+    module.addSerializer(JsonObject.class, new JsonObjectSerializer());
+    registerModule(module);
   }
 
+  @Override
   public String convertToString(Object value) throws Exception {
     return convertValue(value, STRING_JAVA_TYPE);
   }
+
+  @Override
+  public <T> T convertValue(Object fromValue, JavaType toValueType) throws 
IllegalArgumentException {
+    return super.convertValue(fromValue, toValueType);
+  }
 }
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java
new file mode 100644
index 000000000..188d9dec3
--- /dev/null
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.common.rest.codec;
+
+/**
+ * Manage RestObjectMapper instances. Give users an option to specify custom 
mappers.
+ */
+public class RestObjectMapperFactory {
+  private static AbstractRestObjectMapper defaultMapper = new 
RestObjectMapper();
+
+  public static AbstractRestObjectMapper getRestObjectMapper() {
+    return defaultMapper;
+  }
+
+  public static void setDefaultRestObjectMapper(AbstractRestObjectMapper 
customMapper) {
+    defaultMapper = customMapper;
+  }
+}
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
index e550eea6d..c21f527d9 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
@@ -28,7 +28,7 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.servicecomb.common.rest.RestConst;
 import org.apache.servicecomb.common.rest.codec.RestClientRequest;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream;
 import org.apache.servicecomb.swagger.generator.core.utils.ClassUtils;
 
@@ -64,7 +64,7 @@ public Object getValue(HttpServletRequest request) throws 
Exception {
       contentType = contentType == null ? "" : 
contentType.toLowerCase(Locale.US);
       if (contentType.startsWith(MediaType.MULTIPART_FORM_DATA)
           || contentType.startsWith(MediaType.APPLICATION_FORM_URLENCODED)) {
-        return 
RestObjectMapper.INSTANCE.convertValue(request.getParameterMap(), targetType);
+        return 
RestObjectMapperFactory.getRestObjectMapper().convertValue(request.getParameterMap(),
 targetType);
       }
 
       // for standard HttpServletRequest, getInputStream will never return null
@@ -83,14 +83,14 @@ public Object getValue(HttpServletRequest request) throws 
Exception {
         // TODO: we should consider body encoding
         return IOUtils.toString(inputStream, "UTF-8");
       }
-      return RestObjectMapper.INSTANCE.readValue(inputStream, targetType);
+      return 
RestObjectMapperFactory.getRestObjectMapper().readValue(inputStream, 
targetType);
     }
 
     @Override
     public void setValue(RestClientRequest clientRequest, Object arg) throws 
Exception {
       try (BufferOutputStream output = new BufferOutputStream()) {
         clientRequest.putHeader(HttpHeaders.CONTENT_TYPE, 
MediaType.APPLICATION_JSON);
-        RestObjectMapper.INSTANCE.writeValue(output, arg);
+        RestObjectMapperFactory.getRestObjectMapper().writeValue(output, arg);
         if (arg != null) {
           clientRequest.write(output.getBuffer());
         }
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java
index 3ad7903fb..7f8a7761a 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java
@@ -23,7 +23,7 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.servicecomb.common.rest.codec.RestClientRequest;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
@@ -64,7 +64,7 @@ public Object getValue(HttpServletRequest request) throws 
Exception {
 
     @Override
     public void setValue(RestClientRequest clientRequest, Object arg) throws 
Exception {
-      clientRequest.addCookie(paramPath, 
RestObjectMapper.INSTANCE.convertToString(arg));
+      clientRequest.addCookie(paramPath, 
RestObjectMapperFactory.getRestObjectMapper().convertToString(arg));
     }
 
     @Override
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java
index 52ea2b2b3..43b458282 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java
@@ -24,7 +24,7 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.servicecomb.common.rest.codec.RestClientRequest;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -74,7 +74,7 @@ public void setValue(RestClientRequest clientRequest, Object 
arg) throws Excepti
         LOGGER.debug("Header arg is null, will not be set into clientRequest. 
paramPath = [{}]", paramPath);
         return;
       }
-      clientRequest.putHeader(paramPath, 
RestObjectMapper.INSTANCE.convertToString(arg));
+      clientRequest.putHeader(paramPath, 
RestObjectMapperFactory.getRestObjectMapper().convertToString(arg));
     }
 
     @Override
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java
index 4b9bd08cc..e38f7dc25 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java
@@ -20,7 +20,7 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.servicecomb.common.rest.codec.RestClientRequest;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 
 import com.fasterxml.jackson.databind.JavaType;
 
@@ -30,7 +30,7 @@
   void setValue(RestClientRequest clientRequest, Object arg) throws Exception;
 
   default Object convertValue(Object value, JavaType targetType) {
-    return RestObjectMapper.INSTANCE.convertValue(value, targetType);
+    return RestObjectMapperFactory.getRestObjectMapper().convertValue(value, 
targetType);
   }
 
   String getParameterPath();
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
index 073032bfc..9116d3fff 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
@@ -32,7 +32,7 @@
 import javax.ws.rs.core.MediaType;
 
 import org.apache.servicecomb.common.rest.codec.RestClientRequest;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream;
 import org.apache.servicecomb.foundation.vertx.stream.PumpFromPart;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
@@ -122,7 +122,7 @@ private void genBodyForm(String boundary) {
           output.write(bytesOf("--" + boundary + "\r\n"));
           output.write(bytesOf("Content-Disposition: form-data; name=\"" + 
entry.getKey() + "\"\r\n\r\n"));
           if (entry.getValue() != null) {
-            String value = 
RestObjectMapper.INSTANCE.convertToString(entry.getValue());
+            String value = 
RestObjectMapperFactory.getRestObjectMapper().convertToString(entry.getValue());
             output.write(value.getBytes(StandardCharsets.UTF_8));
           }
         }
@@ -223,7 +223,7 @@ private void genBodyBuffer() throws Exception {
         output.write(entry.getKey().getBytes(StandardCharsets.UTF_8));
         output.write('=');
         if (entry.getValue() != null) {
-          String value = 
RestObjectMapper.INSTANCE.convertToString(entry.getValue());
+          String value = 
RestObjectMapperFactory.getRestObjectMapper().convertToString(entry.getValue());
           value = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
           output.write(value.getBytes(StandardCharsets.UTF_8));
         }
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
index 73cbf6296..817aef0e6 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
@@ -22,7 +22,7 @@
 
 import javax.ws.rs.core.MediaType;
 
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 
 import com.fasterxml.jackson.databind.JavaType;
 
@@ -35,12 +35,12 @@ public String getName() {
 
   @Override
   public void doEncodeResponse(OutputStream output, Object result) throws 
Exception {
-    RestObjectMapper.INSTANCE.writeValue(output, result);
+    RestObjectMapperFactory.getRestObjectMapper().writeValue(output, result);
   }
 
   @Override
   public Object doDecodeResponse(InputStream input, JavaType type) throws 
Exception {
-    return RestObjectMapper.INSTANCE.readValue(input, type);
+    return RestObjectMapperFactory.getRestObjectMapper().readValue(input, 
type);
   }
 
   @Override
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriter.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriter.java
index e725f2987..e07742952 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriter.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriter.java
@@ -21,7 +21,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.common.rest.definition.RestParam;
 
 public class QueryVarParamWriter extends AbstractUrlParamWriter {
@@ -99,7 +99,7 @@ private void writeItem(StringBuilder builder, Object item) 
throws Exception {
   }
 
   private String encodeNotNullValue(Object value) throws Exception {
-    String strValue = RestObjectMapper.INSTANCE.convertToString(value);
+    String strValue = 
RestObjectMapperFactory.getRestObjectMapper().convertToString(value);
     return URLEncoder.encode(strValue, StandardCharsets.UTF_8.name());
   }
 }
diff --git 
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/PojoModel.java
 
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/PojoModel.java
new file mode 100644
index 000000000..982e6314a
--- /dev/null
+++ 
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/PojoModel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.common.rest.codec;
+
+public class PojoModel {
+  private String name;
+
+  private String desc;
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getDesc() {
+    return desc;
+  }
+
+  public void setDesc(String desc) {
+    this.desc = desc;
+  }
+}
diff --git 
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java
 
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java
index 1dd335e71..1a9980ecf 100644
--- 
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java
+++ 
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java
@@ -22,16 +22,37 @@
 
 import com.fasterxml.jackson.core.JsonParser.Feature;
 import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+import io.vertx.core.json.JsonObject;
 
 public class TestRestObjectMapper {
 
   @Test
   public void testAutoCloseSource() {
-    
Assert.assertFalse(RestObjectMapper.INSTANCE.getFactory().isEnabled(Feature.AUTO_CLOSE_SOURCE));
+    
Assert.assertFalse(RestObjectMapperFactory.getRestObjectMapper().getFactory().isEnabled(Feature.AUTO_CLOSE_SOURCE));
   }
 
   @Test
   public void testDeserializationFeature() {
-    
Assert.assertFalse(RestObjectMapper.INSTANCE.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
+    Assert.assertFalse(
+        
RestObjectMapperFactory.getRestObjectMapper().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
+  }
+
+  @Test
+  public void testJsonObjectWork() {
+    JsonObject obj = new JsonObject();
+    obj.put("name", "a");
+    obj.put("desc", "b");
+    PojoModel model = RestObjectMapperFactory.getRestObjectMapper()
+        .convertValue(obj, 
TypeFactory.defaultInstance().constructType(PojoModel.class));
+    Assert.assertEquals("a", model.getName());
+    Assert.assertEquals("b", model.getDesc());
+
+    RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapper());
+    model = RestObjectMapperFactory.getRestObjectMapper()
+        .convertValue(obj, 
TypeFactory.defaultInstance().constructType(PojoModel.class));
+    Assert.assertEquals("a", model.getName());
+    Assert.assertEquals("b", model.getDesc());
   }
 }
diff --git 
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
 
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
index d376ebc06..34621d6e2 100644
--- 
a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
+++ 
b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
@@ -57,8 +57,6 @@
 
   private final OperationMeta meta = mock(OperationMeta.class);
 
-  private final RestOperationMeta operationMeta = new RestOperationMeta();
-
   @Before
   public void setUp() throws Exception {
     when(meta.getSchemaMeta()).thenReturn(schemaMeta);
@@ -70,6 +68,7 @@ public void setUp() throws Exception {
 
   @Test
   public void testCreateProduceProcessorsNull() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.createProduceProcessors();
 
     Assert.assertSame(ProduceProcessorManager.DEFAULT_PROCESSOR,
@@ -85,6 +84,7 @@ public void testCreateProduceProcessorsNull() {
 
   @Test
   public void testCreateProduceProcessorsEmpty() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList();
     operationMeta.createProduceProcessors();
 
@@ -101,6 +101,7 @@ public void testCreateProduceProcessorsEmpty() {
 
   @Test
   public void testCreateProduceProcessorsNormal() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList(MediaType.APPLICATION_JSON);
     operationMeta.createProduceProcessors();
 
@@ -116,6 +117,7 @@ public void testCreateProduceProcessorsNormal() {
 
   @Test
   public void testCreateProduceProcessorsNotSupported() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList("notSupport");
     operationMeta.createProduceProcessors();
 
@@ -131,6 +133,7 @@ public void testCreateProduceProcessorsNotSupported() {
 
   @Test
   public void testCreateProduceProcessorsTextAndWildcard() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList(MediaType.TEXT_PLAIN);
     operationMeta.createProduceProcessors();
 
@@ -146,6 +149,7 @@ public void testCreateProduceProcessorsTextAndWildcard() {
 
   @Test
   public void testEnsureFindProduceProcessorRequest(@Mocked 
HttpServletRequestEx requestEx) {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     new Expectations() {
       {
         requestEx.getHeader(HttpHeaders.ACCEPT);
@@ -159,6 +163,7 @@ public void testEnsureFindProduceProcessorRequest(@Mocked 
HttpServletRequestEx r
 
   @Test
   public void testEnsureFindProduceProcessorAcceptFound() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList(MediaType.APPLICATION_JSON, 
MediaType.TEXT_PLAIN);
     operationMeta.createProduceProcessors();
 
@@ -168,6 +173,7 @@ public void testEnsureFindProduceProcessorAcceptFound() {
 
   @Test
   public void testEnsureFindProduceProcessorAcceptNotFound() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList(MediaType.APPLICATION_JSON, 
MediaType.TEXT_PLAIN);
     operationMeta.createProduceProcessors();
 
@@ -176,6 +182,7 @@ public void testEnsureFindProduceProcessorAcceptNotFound() {
 
   @Test
   public void generatesAbsolutePathWithRootBasePath() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     when(swagger.getBasePath()).thenReturn("/");
     when(meta.getOperationPath()).thenReturn("/sayHi/");
 
@@ -186,6 +193,7 @@ public void generatesAbsolutePathWithRootBasePath() {
 
   @Test
   public void generatesAbsolutePathWithNonRootBasePath() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     when(swagger.getBasePath()).thenReturn("/rest");
     when(meta.getOperationPath()).thenReturn("/sayHi");
 
@@ -196,6 +204,7 @@ public void generatesAbsolutePathWithNonRootBasePath() {
 
   @Test
   public void generatesAbsolutePathWithNullPath() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     when(swagger.getBasePath()).thenReturn(null);
     when(meta.getOperationPath()).thenReturn(null);
 
@@ -206,6 +215,7 @@ public void generatesAbsolutePathWithNullPath() {
 
   @Test
   public void generatesAbsolutePathWithEmptyPath() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     when(swagger.getBasePath()).thenReturn("");
     when(meta.getOperationPath()).thenReturn("");
 
@@ -216,6 +226,7 @@ public void generatesAbsolutePathWithEmptyPath() {
 
   @Test
   public void consecutiveSlashesAreRemoved() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     when(swagger.getBasePath()).thenReturn("//rest//");
     when(meta.getOperationPath()).thenReturn("//sayHi//");
 
@@ -226,6 +237,7 @@ public void consecutiveSlashesAreRemoved() {
 
   @Test
   public void testFormDataFlagTrue() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     
when(meta.getMethod()).thenReturn(ReflectUtils.findMethod(SomeRestController.class,
 "form"));
     when(meta.getSwaggerOperation()).thenReturn(operation);
     List<Parameter> params = Arrays.asList(new FormParameter());
@@ -238,6 +250,7 @@ public void testFormDataFlagTrue() {
 
   @Test
   public void testFormDataFlagFalse() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
     
when(meta.getMethod()).thenReturn(ReflectUtils.findMethod(SomeRestController.class,
 "form"));
     when(meta.getSwaggerOperation()).thenReturn(operation);
     List<Parameter> params = Arrays.asList(new QueryParameter());
diff --git 
a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java
 
b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java
index 572ed61c0..73c533e67 100644
--- 
a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java
+++ 
b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java
@@ -18,7 +18,7 @@
 
 import java.util.Map;
 
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.demo.edge.authentication.encrypt.Hcr;
@@ -54,7 +54,8 @@ public Response afterReceiveRequest(Invocation invocation, 
HttpServletRequestEx
     encodedBody = encodedBody.substring(hcr.getBodyKey().length());
 
     try {
-      Map<String, String[]> decodedBody = 
RestObjectMapper.INSTANCE.readValue(encodedBody, bodyType);
+      Map<String, String[]> decodedBody = 
RestObjectMapperFactory.getRestObjectMapper()
+          .readValue(encodedBody, bodyType);
       requestEx.getParameterMap().putAll(decodedBody);
     } catch (Throwable e) {
       // should be a meaning exception response
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 add91b435..b123119ff 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
@@ -24,11 +24,12 @@
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.http.HttpStatus;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.demo.CodeFirstRestTemplate;
 import org.apache.servicecomb.demo.DemoConst;
+import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper;
 import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.validator.Student;
@@ -59,6 +60,7 @@ public static void main(String[] args) throws Exception {
   public static void init() throws Exception {
     Log4jUtils.init();
     BeanUtils.init();
+    RestObjectMapperFactory.setDefaultRestObjectMapper(new 
RestObjectMapperWithStringMapper());
   }
 
   public static void run() throws Exception {
@@ -265,7 +267,7 @@ private static void testExchange(RestTemplate template, 
String cseUrlPrefix) {
   private static void testRawJsonParam(RestTemplate template, String 
cseUrlPrefix) throws Exception {
     Map<String, String> person = new HashMap<>();
     person.put("name", "Tom");
-    String jsonPerson = RestObjectMapper.INSTANCE.writeValueAsString(person);
+    String jsonPerson = 
RestObjectMapperFactory.getRestObjectMapper().writeValueAsString(person);
     TestMgr.check("hello Tom",
         template.postForObject(cseUrlPrefix + "/compute/testrawjson", 
jsonPerson, String.class));
   }
diff --git 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java
 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java
index fb4851c10..4c249b8ee 100644
--- 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java
+++ 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java
@@ -30,6 +30,9 @@
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.RestTemplate;
 
+import io.vertx.core.json.Json;
+import io.vertx.core.json.JsonObject;
+
 public class MultiErrorCodeServiceClient {
   private static final String SERVER = "cse://jaxrs";
 
@@ -42,6 +45,7 @@ public static void runTest() {
       testErrorCode();
       testErrorCodeWithHeader();
       testErrorCodeWithHeaderJAXRS();
+      testErrorCodeWithHeaderJAXRSUsingRowType();
     }
   }
 
@@ -113,6 +117,7 @@ private static void testErrorCodeWithHeaderJAXRS() {
     MultiRequest request = new MultiRequest();
 
     request.setCode(200);
+    request.setMessage("success result");
     ResponseEntity<MultiResponse200> result = template
         .postForEntity(SERVER + 
"/MultiErrorCodeService/errorCodeWithHeaderJAXRS", request, 
MultiResponse200.class);
     TestMgr.check(result.getStatusCode(), 200);
@@ -121,6 +126,7 @@ private static void testErrorCodeWithHeaderJAXRS() {
     TestMgr.check(result.getHeaders().getFirst("x-code"), 200);
 
     request.setCode(400);
+    request.setMessage("bad request");
     MultiResponse400 t400 = null;
     try {
       template
@@ -133,6 +139,7 @@ private static void testErrorCodeWithHeaderJAXRS() {
     TestMgr.check(t400.getMessage(), "bad request");
 
     request.setCode(500);
+    request.setMessage("internal error");
     MultiResponse500 t500 = null;
     try {
       template
@@ -144,4 +151,39 @@ private static void testErrorCodeWithHeaderJAXRS() {
     TestMgr.check(t500.getCode(), 500);
     TestMgr.check(t500.getMessage(), "internal error");
   }
+
+  private static void testErrorCodeWithHeaderJAXRSUsingRowType() {
+    JsonObject requestJson = new JsonObject();
+    requestJson.put("code", 200);
+    requestJson.put("message", "test message");
+
+    ResponseEntity<MultiResponse200> result = template
+        .postForEntity(SERVER + 
"/MultiErrorCodeService/errorCodeWithHeaderJAXRS", requestJson, 
MultiResponse200.class);
+    TestMgr.check(result.getStatusCode(), 200);
+    TestMgr.check(result.getBody().getMessage(), "test message");
+    TestMgr.check(result.getBody().getCode(), 200);
+    TestMgr.check(result.getHeaders().getFirst("x-code"), 200);
+
+    MultiRequest request = new MultiRequest();
+    request.setCode(200);
+    request.setMessage("test message");
+    String stringRequest = Json.encode(request);
+    // wrap request to JsonObject
+    result = template
+        .postForEntity(SERVER + 
"/MultiErrorCodeService/errorCodeWithHeaderJAXRS", new 
JsonObject(stringRequest),
+            MultiResponse200.class);
+    TestMgr.check(result.getStatusCode(), 200);
+    TestMgr.check(result.getBody().getMessage(), "test message");
+    TestMgr.check(result.getBody().getCode(), 200);
+    TestMgr.check(result.getHeaders().getFirst("x-code"), 200);
+
+    // using string
+    result = template
+        .postForEntity(SERVER + 
"/MultiErrorCodeService/errorCodeWithHeaderJAXRS", stringRequest,
+            MultiResponse200.class);
+    TestMgr.check(result.getStatusCode(), 200);
+    TestMgr.check(result.getBody().getMessage(), "test message");
+    TestMgr.check(result.getBody().getCode(), 200);
+    TestMgr.check(result.getHeaders().getFirst("x-code"), 200);
+  }
 }
diff --git 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
index 8d12fc394..63fc02488 100644
--- 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
+++ 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
@@ -41,7 +41,7 @@
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore;
@@ -55,6 +55,7 @@
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
 import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
 import org.apache.servicecomb.swagger.invocation.response.Headers;
+
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiResponse;
@@ -150,7 +151,7 @@ public Person sayHello(Person user) {
   public String testRawJsonString(String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;
@@ -200,7 +201,7 @@ public OutputModelForTestIgnore 
testModelWithIgnoreField(InputModelForTestIgnore
     return new OutputModelForTestIgnore("output_id", input.getInputId(), 
input.getContent(), input.getInputObject(),
         input.getInputJsonObject(), input.getInputIgnoreInterface(),
         new Person("outputSomeone"), new JsonObject("{\"OutputJsonKey\" : 
\"OutputJsonValue\"}"), () -> {
-        });
+    });
   }
 
   @SuppressWarnings("unchecked")
@@ -209,7 +210,7 @@ public OutputModelForTestIgnore 
testModelWithIgnoreField(InputModelForTestIgnore
   public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;
diff --git 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java
 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java
index 8b33f92a2..9797901b0 100644
--- 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java
+++ 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java
@@ -33,7 +33,7 @@
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
@@ -73,7 +73,7 @@ public Person sayHello(Person user) {
   public String testRawJsonString(String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;
diff --git 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
index b31a2bd57..bf5eba5fd 100644
--- 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
+++ 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.demo.jaxrs.server;
 
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
+import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
 
@@ -24,5 +26,6 @@
   public static void main(String[] args) throws Exception {
     Log4jUtils.init();
     BeanUtils.init();
+    RestObjectMapperFactory.setDefaultRestObjectMapper(new 
RestObjectMapperWithStringMapper());
   }
 }
diff --git 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java
 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java
index e99b75fa7..5004e958e 100644
--- 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java
+++ 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java
@@ -111,8 +111,8 @@ public Response errorCodeWithHeader(MultiRequest request) {
     javax.ws.rs.core.Response response;
     if (request.getCode() == 400) {
       MultiResponse400 r = new MultiResponse400();
-      r.setCode(400);
-      r.setMessage("bad request");
+      r.setCode(request.getCode());
+      r.setMessage(request.getMessage());
       // If got many types for different status code, we can only using 
InvocationException for failed error code like 400-500.
       // The result for Failed Family(e.g. 400-500), can not set return value 
as target type directly or will give exception.
       response = javax.ws.rs.core.Response.status(Status.BAD_REQUEST)
@@ -121,16 +121,16 @@ public Response errorCodeWithHeader(MultiRequest request) 
{
           .build();
     } else if (request.getCode() == 500) {
       MultiResponse500 r = new MultiResponse500();
-      r.setCode(500);
-      r.setMessage("internal error");
+      r.setCode(request.getCode());
+      r.setMessage(request.getMessage());
       response = javax.ws.rs.core.Response.status(Status.INTERNAL_SERVER_ERROR)
           .entity(new InvocationException(Status.INTERNAL_SERVER_ERROR, r))
           .header("x-code", "500")
           .build();
     } else {
       MultiResponse200 r = new MultiResponse200();
-      r.setCode(200);
-      r.setMessage("success result");
+      r.setCode(request.getCode());
+      r.setMessage(request.getMessage());
       // If error code is OK family(like 200), we can use the target type.
       response = javax.ws.rs.core.Response.status(Status.OK)
           .entity(r)
diff --git 
a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/RestObjectMapperWithStringMapper.java
 
b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/RestObjectMapperWithStringMapper.java
new file mode 100644
index 000000000..49a247f87
--- /dev/null
+++ 
b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/RestObjectMapperWithStringMapper.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import java.io.IOException;
+
+import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+
+import com.fasterxml.jackson.databind.JavaType;
+
+/**
+ *  Demonstrate how to using String as raw type when using RestTemplate to 
invoke a service that use POJO. e.g.
+ *  <p/>
+ *  Provider: <p/>
+ *  <code>
+ *    public Response errorCodeWithHeader(MultiRequest request)
+ *  </code>
+ *   <p/>
+ *  Consumer: <p/>
+ *  <code>
+ *    String stringRequest = "{\"key\":\"testValue\"}";
+ *    template.postForEntity(url, stringRequest, MultiResponse200.class);
+ *  </code>
+ * <p/>
+ *  <b>Caution:</b> json will convert String to object based on String 
constructor, using this feature will make default
+ *  conversion change. You must write  convertValue to check possible types 
using.
+ */
+public class RestObjectMapperWithStringMapper extends RestObjectMapper {
+  private static Logger LOGGER = 
LoggerFactory.getLogger(RestObjectMapperWithStringMapper.class);
+
+  @SuppressWarnings("deprecation")
+  public RestObjectMapperWithStringMapper() {
+    super();
+  }
+
+  @Override
+  public <T> T convertValue(Object fromValue, JavaType toValueType) throws 
IllegalArgumentException {
+    if (String.class.isInstance(fromValue)
+        && !BeanUtils.isSimpleValueType(toValueType.getRawClass())) {
+      try {
+        return super.readValue((String) fromValue, toValueType);
+      } catch (IOException e) {
+        LOGGER.error("Failed to convert value for {}.", e.getMessage());
+      }
+    }
+    return super.convertValue(fromValue, toValueType);
+  }
+}
diff --git 
a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java
 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java
index 227245c9e..2bd333013 100644
--- 
a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java
+++ 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.springboot.jaxrs.client;
 
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
+import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper;
 import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
 import org.apache.servicecomb.springboot.starter.provider.EnableServiceComb;
@@ -31,6 +33,7 @@ public static void main(String[] args) throws Exception {
     Log4jUtils.init();
     SpringApplication.run(JaxrsClient.class, args);
 
+    RestObjectMapperFactory.setDefaultRestObjectMapper(new 
RestObjectMapperWithStringMapper());
     org.apache.servicecomb.demo.jaxrs.client.JaxrsClient.run();
     TestMgr.summary();
   }
diff --git 
a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java
 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java
index 6cf98285d..5b4add3f3 100644
--- 
a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java
+++ 
b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.springboot.jaxrs.server;
 
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
+import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper;
 import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
 import org.apache.servicecomb.springboot.starter.provider.EnableServiceComb;
 import org.springframework.boot.SpringApplication;
@@ -28,5 +30,6 @@
   public static void main(final String[] args) throws Exception {
     Log4jUtils.init();
     SpringApplication.run(JaxrsServer.class, args);
+    RestObjectMapperFactory.setDefaultRestObjectMapper(new 
RestObjectMapperWithStringMapper());
   }
 }
diff --git 
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 53b323009..01a21587f 100644
--- 
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -30,7 +30,7 @@
 import javax.xml.ws.Holder;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.demo.EmptyObject;
 import org.apache.servicecomb.demo.Generic;
@@ -207,7 +207,7 @@ public Person sayHello(@RequestBody Person user) {
   public String testRawJsonString(String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;
@@ -325,7 +325,7 @@ public OutputModelForTestIgnore 
testModelWithIgnoreField(@RequestBody InputModel
   public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;
diff --git 
a/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/JaxrsIntegrationTestBase.java
 
b/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/JaxrsIntegrationTestBase.java
index 4a53aa2b3..485ea6791 100644
--- 
a/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/JaxrsIntegrationTestBase.java
+++ 
b/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/JaxrsIntegrationTestBase.java
@@ -37,7 +37,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.server.User;
 import org.junit.Ignore;
@@ -131,10 +131,10 @@ public void ableToPostBytes() throws IOException {
     for (String url : urls) {
       byte[] result = restTemplate.postForObject(
           url + "bytes",
-          jsonRequest(RestObjectMapper.INSTANCE.writeValueAsBytes(body)),
+          
jsonRequest(RestObjectMapperFactory.getRestObjectMapper().writeValueAsBytes(body)),
           byte[].class);
 
-      result = RestObjectMapper.INSTANCE.readValue(result, byte[].class);
+      result = RestObjectMapperFactory.getRestObjectMapper().readValue(result, 
byte[].class);
 
       assertEquals(1, result[0]);
       assertEquals(1, result[1]);
@@ -161,7 +161,7 @@ public void getsJaxrsResponse() {
   public void ableToPostDate() throws Exception {
     ZonedDateTime date = ZonedDateTime.now().truncatedTo(SECONDS);
     MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
-    body.add("date", 
RestObjectMapper.INSTANCE.convertToString(Date.from(date.toInstant())));
+    body.add("date", 
RestObjectMapperFactory.getRestObjectMapper().convertToString(Date.from(date.toInstant())));
 
     HttpHeaders headers = new HttpHeaders();
     headers.add(CONTENT_TYPE, APPLICATION_FORM_URLENCODED_VALUE);
@@ -338,7 +338,7 @@ public void ableToGetAtDefaultPath() {
 
   private <T> T jsonBodyOf(ResponseEntity<String> entity, Class<T> aClass) {
     try {
-      return RestObjectMapper.INSTANCE.readValue(entity.getBody(), aClass);
+      return 
RestObjectMapperFactory.getRestObjectMapper().readValue(entity.getBody(), 
aClass);
     } catch (IOException e) {
       throw new IllegalStateException("Failed to read JSON from response " + 
entity.getBody(), e);
     }
diff --git 
a/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/endpoints/SomeAbstractJaxrsRestEndpoint.java
 
b/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/endpoints/SomeAbstractJaxrsRestEndpoint.java
index b0fc4efe6..54948a60a 100644
--- 
a/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/endpoints/SomeAbstractJaxrsRestEndpoint.java
+++ 
b/integration-tests/jaxrs-tests/src/test/java/org/apache/servicecomb/demo/jaxrs/tests/endpoints/SomeAbstractJaxrsRestEndpoint.java
@@ -34,7 +34,7 @@
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
@@ -92,7 +92,7 @@ public Person sayHello(Person user) {
   public String testRawJsonString(String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
index 33cc718a7..c153a5ac5 100644
--- 
a/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java
@@ -43,7 +43,7 @@
 import java.util.Map;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
@@ -203,10 +203,10 @@ public void ableToPostBytes() throws Exception {
 
     byte[] result = restTemplate.postForObject(
         codeFirstUrl + "bytes",
-        jsonRequest(RestObjectMapper.INSTANCE.writeValueAsBytes(body)),
+        
jsonRequest(RestObjectMapperFactory.getRestObjectMapper().writeValueAsBytes(body)),
         byte[].class);
 
-    result = RestObjectMapper.INSTANCE.readValue(result, byte[].class);
+    result = RestObjectMapperFactory.getRestObjectMapper().readValue(result, 
byte[].class);
 
     assertEquals(1, result[0]);
     assertEquals(1, result[1]);
@@ -215,10 +215,10 @@ public void ableToPostBytes() throws Exception {
 
     ListenableFuture<ResponseEntity<byte[]>> listenableFuture = 
asyncRestTemplate
         .postForEntity(codeFirstUrl + "bytes",
-            jsonRequest(RestObjectMapper.INSTANCE.writeValueAsBytes(body)),
+            
jsonRequest(RestObjectMapperFactory.getRestObjectMapper().writeValueAsBytes(body)),
             byte[].class);
     ResponseEntity<byte[]> responseEntity = listenableFuture.get();
-    result = RestObjectMapper.INSTANCE.readValue(responseEntity.getBody(), 
byte[].class);
+    result = 
RestObjectMapperFactory.getRestObjectMapper().readValue(responseEntity.getBody(),
 byte[].class);
     assertEquals(1, result[0]);
     assertEquals(1, result[1]);
     assertEquals(2, result[2]);
@@ -331,7 +331,7 @@ public void blowsUpWhenFileNameDoesNotMatch() throws 
Exception {
   public void ableToPostDate() throws Exception {
     ZonedDateTime date = ZonedDateTime.now().truncatedTo(SECONDS);
     MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
-    body.add("date", 
RestObjectMapper.INSTANCE.convertToString(Date.from(date.toInstant())));
+    body.add("date", 
RestObjectMapperFactory.getRestObjectMapper().convertToString(Date.from(date.toInstant())));
 
     HttpHeaders headers = new HttpHeaders();
     headers.add(CONTENT_TYPE, APPLICATION_FORM_URLENCODED_VALUE);
@@ -671,7 +671,7 @@ public void onSuccess(ResponseEntity<String> result) {
 
   private <T> T jsonOf(String json, Class<T> aClass) {
     try {
-      return RestObjectMapper.INSTANCE.readValue(json, aClass);
+      return RestObjectMapperFactory.getRestObjectMapper().readValue(json, 
aClass);
     } catch (IOException e) {
       throw new IllegalStateException(
           "Failed to read JSON from " + json + ", Exception is: " + e);
diff --git 
a/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
index 123404ee3..912da180d 100644
--- 
a/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
+++ 
b/integration-tests/springmvc-tests/springmvc-tests-common/src/test/java/org/apache/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
@@ -27,7 +27,7 @@
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
 import org.apache.servicecomb.demo.controller.Person;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.swagger.invocation.Response;
@@ -110,7 +110,7 @@ public Person sayHello(Person user) {
   public String testRawJsonString(String jsonInput) {
     Map<String, String> person;
     try {
-      person = RestObjectMapper.INSTANCE.readValue(jsonInput.getBytes(), 
Map.class);
+      person = 
RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), 
Map.class);
     } catch (Exception e) {
       e.printStackTrace();
       return null;


 

----------------------------------------------------------------
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:
[email protected]


> support invoke service using raw type like JsonObject
> -----------------------------------------------------
>
>                 Key: SCB-775
>                 URL: https://issues.apache.org/jira/browse/SCB-775
>             Project: Apache ServiceComb
>          Issue Type: New Feature
>          Components: Java-Chassis
>            Reporter: liubao
>            Assignee: liubao
>            Priority: Major
>
> When using RestTemplate, can use JsonObject or String as request body 



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

Reply via email to