You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/07/28 01:35:42 UTC

[incubator-servicecomb-java-chassis] 01/05: [SCB-775]support invoke service using raw type like JsonObject & String

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

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

commit 93bc5b19cb602fd5af87c9f4839a8e06c29ec3bd
Author: liubao <ba...@huawei.com>
AuthorDate: Wed Jul 25 18:25:04 2018 +0800

    [SCB-775]support invoke service using raw type like JsonObject & String
---
 .../rest/codec/AbstractRestObjectMapper.java       | 12 ++--
 .../common/rest/codec/RestObjectMapper.java        | 29 +++++++++-
 .../rest/codec/RestObjectMapperFactory.java}       | 22 +++-----
 .../rest/codec/param/BodyProcessorCreator.java     |  8 +--
 .../rest/codec/param/CookieProcessorCreator.java   |  4 +-
 .../rest/codec/param/HeaderProcessorCreator.java   |  4 +-
 .../rest/codec/param/ParamValueProcessor.java      |  4 +-
 .../rest/codec/param/RestClientRequestImpl.java    |  6 +-
 .../rest/codec/produce/ProduceJsonProcessor.java   |  6 +-
 .../rest/definition/path/QueryVarParamWriter.java  |  4 +-
 .../servicecomb/common/rest/codec/PojoModel.java   | 26 ++++++---
 .../common/rest/codec/TestRestObjectMapper.java    | 25 ++++++++-
 .../service/encrypt/filter/DecodeBodyFilter.java   |  5 +-
 .../servicecomb/demo/jaxrs/client/JaxrsClient.java |  6 +-
 .../jaxrs/client/MultiErrorCodeServiceClient.java  | 42 ++++++++++++++
 .../demo/jaxrs/server/CodeFirstJaxrs.java          |  9 +--
 .../servicecomb/demo/jaxrs/server/ComputeImpl.java |  4 +-
 .../servicecomb/demo/jaxrs/server/JaxrsServer.java |  3 +
 .../multiErrorCode/MultiErrorCodeService.java      | 12 ++--
 .../demo/RestObjectMapperWithStringMapper.java     | 65 ++++++++++++++++++++++
 .../demo/springmvc/server/CodeFirstSpringmvc.java  |  6 +-
 .../demo/jaxrs/tests/JaxrsIntegrationTestBase.java | 10 ++--
 .../endpoints/SomeAbstractJaxrsRestEndpoint.java   |  4 +-
 .../tests/SpringMvcIntegrationTestBase.java        | 14 ++---
 .../tests/endpoints/CodeFirstSpringmvcBase.java    |  4 +-
 25 files changed, 248 insertions(+), 86 deletions(-)

diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/AbstractRestObjectMapper.java
similarity index 71%
copy from demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
copy to common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/AbstractRestObjectMapper.java
index b31a2bd..8a7ab0e 100644
--- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/AbstractRestObjectMapper.java
@@ -15,14 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.demo.jaxrs.server;
+package org.apache.servicecomb.common.rest.codec;
 
-import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+import com.fasterxml.jackson.databind.ObjectMapper;
 
-public class JaxrsServer {
-  public static void main(String[] args) throws Exception {
-    Log4jUtils.init();
-    BeanUtils.init();
-  }
+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 b0679f4..617e86b 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 final class RestObjectMapper extends ObjectMapper {
     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/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java
similarity index 62%
copy from common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java
copy to common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java
index 1dd335e..188d9de 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java
@@ -17,21 +17,17 @@
 
 package org.apache.servicecomb.common.rest.codec;
 
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.fasterxml.jackson.core.JsonParser.Feature;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-
-public class TestRestObjectMapper {
+/**
+ * Manage RestObjectMapper instances. Give users an option to specify custom mappers.
+ */
+public class RestObjectMapperFactory {
+  private static AbstractRestObjectMapper defaultMapper = new RestObjectMapper();
 
-  @Test
-  public void testAutoCloseSource() {
-    Assert.assertFalse(RestObjectMapper.INSTANCE.getFactory().isEnabled(Feature.AUTO_CLOSE_SOURCE));
+  public static AbstractRestObjectMapper getRestObjectMapper() {
+    return defaultMapper;
   }
 
-  @Test
-  public void testDeserializationFeature() {
-    Assert.assertFalse(RestObjectMapper.INSTANCE.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
+  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 e550eea..c21f527 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 javax.ws.rs.core.MediaType;
 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 class BodyProcessorCreator implements ParamValueProcessorCreator {
       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 class BodyProcessorCreator implements ParamValueProcessorCreator {
         // 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 3ad7903..7f8a776 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.Cookie;
 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 class CookieProcessorCreator implements ParamValueProcessorCreator {
 
     @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 52ea2b2..43b4582 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 java.util.Enumeration;
 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 class HeaderProcessorCreator implements ParamValueProcessorCreator {
         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 4b9bd08..e38f7dc 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 @@ package org.apache.servicecomb.common.rest.codec.param;
 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 @@ public interface ParamValueProcessor {
   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 073032b..9116d3f 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.servlet.http.Part;
 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 @@ public class RestClientRequestImpl implements RestClientRequest {
           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 @@ public class RestClientRequestImpl implements RestClientRequest {
         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 73cbf62..817aef0 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 java.io.OutputStream;
 
 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 class ProduceJsonProcessor implements ProduceProcessor {
 
   @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 e725f29..e077429 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.net.URLEncoder;
 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 @@ public class QueryVarParamWriter extends AbstractUrlParamWriter {
   }
 
   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/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/PojoModel.java
similarity index 70%
copy from demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
copy to common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/PojoModel.java
index b31a2bd..982e631 100644
--- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/PojoModel.java
@@ -15,14 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.demo.jaxrs.server;
+package org.apache.servicecomb.common.rest.codec;
 
-import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+public class PojoModel {
+  private String name;
 
-public class JaxrsServer {
-  public static void main(String[] args) throws Exception {
-    Log4jUtils.init();
-    BeanUtils.init();
+  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 1dd335e..1a9980e 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 org.junit.Test;
 
 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/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 572ed61..73c533e 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 @@ package org.apache.servicecomb.demo.edge.service.encrypt.filter;
 
 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 class DecodeBodyFilter implements HttpServerFilter {
     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 add91b4..b123119 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.MediaType;
 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 class JaxrsClient {
   public static void init() throws Exception {
     Log4jUtils.init();
     BeanUtils.init();
+    RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper());
   }
 
   public static void run() throws Exception {
@@ -265,7 +267,7 @@ public class JaxrsClient {
   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 fb4851c..4c249b8 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.apache.servicecomb.swagger.invocation.exception.InvocationException;
 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 class MultiErrorCodeServiceClient {
       testErrorCode();
       testErrorCodeWithHeader();
       testErrorCodeWithHeaderJAXRS();
+      testErrorCodeWithHeaderJAXRSUsingRowType();
     }
   }
 
@@ -113,6 +117,7 @@ public class MultiErrorCodeServiceClient {
     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 @@ public class MultiErrorCodeServiceClient {
     TestMgr.check(result.getHeaders().getFirst("x-code"), 200);
 
     request.setCode(400);
+    request.setMessage("bad request");
     MultiResponse400 t400 = null;
     try {
       template
@@ -133,6 +139,7 @@ public class MultiErrorCodeServiceClient {
     TestMgr.check(t400.getMessage(), "bad request");
 
     request.setCode(500);
+    request.setMessage("internal error");
     MultiResponse500 t500 = null;
     try {
       template
@@ -144,4 +151,39 @@ public class MultiErrorCodeServiceClient {
     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 8d12fc3..63fc024 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.MediaType;
 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.Response;
 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 class CodeFirstJaxrs {
   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 class CodeFirstJaxrs {
     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 class CodeFirstJaxrs {
   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 8b33f92..9797901 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.QueryParam;
 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 class ComputeImpl {
   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 b31a2bd..bf5eba5 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 class JaxrsServer {
   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 e99b75f..5004e95 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 class MultiErrorCodeService {
     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 class MultiErrorCodeService {
           .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 0000000..454e909
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/RestObjectMapperWithStringMapper.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.commons.lang3.ClassUtils;
+import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+import io.vertx.core.json.JsonObject;
+
+/**
+ *  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 final long serialVersionUID = -8158869347066287575L;
+
+  private static final JavaType STRING_JAVA_TYPE = TypeFactory.defaultInstance().constructType(String.class);
+
+  @SuppressWarnings("deprecation")
+  public RestObjectMapperWithStringMapper() {
+    super();
+  }
+
+  @Override
+  public <T> T convertValue(Object fromValue, JavaType toValueType) throws IllegalArgumentException {
+    if (String.class.isInstance(fromValue)
+        && !String.class.equals(toValueType.getRawClass())
+        && !java.util.Date.class.equals(toValueType.getRawClass())
+        && !ClassUtils.isPrimitiveOrWrapper(toValueType.getRawClass())) {
+      return super.convertValue(new JsonObject((String) fromValue), toValueType);
+    }
+    return super.convertValue(fromValue, toValueType);
+  }
+}
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 53b3230..01a2158 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.ws.rs.core.Response.Status;
 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 class CodeFirstSpringmvc {
   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 class CodeFirstSpringmvc {
   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 4a53aa2..485ea67 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.Date;
 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 class JaxrsIntegrationTestBase {
     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 class JaxrsIntegrationTestBase {
   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 class JaxrsIntegrationTestBase {
 
   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 b0fc4ef..54948a6 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.Produces;
 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 class SomeAbstractJaxrsRestEndpoint {
   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 33cc718..c153a5a 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.List;
 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 class SpringMvcIntegrationTestBase {
 
     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 class SpringMvcIntegrationTestBase {
 
     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 class SpringMvcIntegrationTestBase {
   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 class SpringMvcIntegrationTestBase {
 
   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 123404e..912da18 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.servlet.http.HttpServletRequest;
 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 class CodeFirstSpringmvcBase {
   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;