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 2020/04/21 03:05:00 UTC

[servicecomb-java-chassis] branch master updated: [SCB-1869] highway should use consumer type to avoid deserialization convertion

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/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new abcae31  [SCB-1869] highway should use consumer type to avoid deserialization convertion
abcae31 is described below

commit abcae3142c69b54cf8d2ce9235ea51f49959bf23
Author: liubao <bi...@qq.com>
AuthorDate: Mon Apr 20 15:36:22 2020 +0800

    [SCB-1869] highway should use consumer type to avoid deserialization convertion
---
 .../protobuf/definition/OperationProtobuf.java     | 159 +++++++++++----------
 .../codec/protobuf/definition/ProtobufManager.java |  79 +++++++++-
 .../internal/converter/TestSchemaMetaCodec.java    |  99 +++++++++----
 .../converter/TestSchemaMetaCodecRestTemplate.java |  60 +++++++-
 .../org/apache/servicecomb/core/Invocation.java    |   4 +
 .../foundation/common/utils/RestObjectMapper.java  |   2 +-
 .../foundation/common/utils/TypesUtil.java         | 130 +++++++++++++++++
 .../foundation/common/utils/TestTypesUtil.java     |  32 +++++
 .../deserializer/DeserializerSchemaManager.java    |  10 +-
 .../transport/highway/HighwayClient.java           |   2 +-
 .../transport/highway/HighwayCodec.java            |  12 +-
 .../transport/highway/HighwayServerInvoke.java     |  17 ++-
 .../transport/highway/TestHighwayClient.java       |   2 +-
 .../transport/highway/TestHighwayCodec.java        |   2 +-
 14 files changed, 477 insertions(+), 133 deletions(-)

diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java
index 9d12a9b..2f0579f 100644
--- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java
+++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java
@@ -25,7 +25,7 @@ import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.Response.Status.Family;
 
 import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager;
-import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.foundation.protobuf.ProtoMapper;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils;
@@ -36,8 +36,6 @@ import io.protostuff.compiler.model.Message;
 
 @SuppressWarnings("rawtypes")
 public class OperationProtobuf {
-  private OperationMeta operationMeta;
-
   private RequestRootSerializer requestRootSerializer;
 
   private RequestRootDeserializer<Object> requestRootDeserializer;
@@ -50,10 +48,9 @@ public class OperationProtobuf {
 
   private ResponseRootDeserializer<Object> anyResponseRootDeserializer;
 
-  public OperationProtobuf(ScopedProtobufSchemaManager scopedProtobufSchemaManager, OperationMeta operationMeta) {
-    this.operationMeta = operationMeta;
-    initRequestCodec(scopedProtobufSchemaManager, operationMeta);
-    initResponseCodec(scopedProtobufSchemaManager, operationMeta);
+  public OperationProtobuf(ScopedProtobufSchemaManager scopedProtobufSchemaManager, Invocation invocation) {
+    initRequestCodec(scopedProtobufSchemaManager, invocation);
+    initResponseCodec(scopedProtobufSchemaManager, invocation);
   }
 
   public RequestRootSerializer getRequestRootSerializer() {
@@ -78,90 +75,104 @@ public class OperationProtobuf {
     return anyResponseRootDeserializer;
   }
 
-  public OperationMeta getOperationMeta() {
-    return operationMeta;
-  }
-
-  private void initRequestCodec(ScopedProtobufSchemaManager scopedProtobufSchemaManager, OperationMeta operationMeta) {
-    ProtoMapper mapper = scopedProtobufSchemaManager.getOrCreateProtoMapper(operationMeta.getSchemaMeta());
-    Message requestMessage = mapper.getRequestMessage(operationMeta.getOperationId());
-
-    if (operationMeta.getSwaggerProducerOperation() != null) {
-      Map<String, Type> swaggerParameterTypes = operationMeta.getSwaggerProducerOperation()
-          .getSwaggerParameterTypes();
-      if (ProtoUtils.isWrapArguments(requestMessage)) {
+  private void initProducerRequestCodec(Invocation invocation, Message requestMessage, ProtoMapper mapper) {
+    Map<String, Type> swaggerParameterTypes = invocation.getOperationMeta().getSwaggerProducerOperation()
+        .getSwaggerParameterTypes();
+    if (ProtoUtils.isWrapArguments(requestMessage)) {
+      requestRootDeserializer = new RequestRootDeserializer<>(
+          mapper.createRootDeserializer(requestMessage, swaggerParameterTypes), true, null);
+    } else {
+      if (swaggerParameterTypes.isEmpty()) {
         requestRootDeserializer = new RequestRootDeserializer<>(
-            mapper.createRootDeserializer(requestMessage, swaggerParameterTypes), true, null);
+            mapper.createRootDeserializer(requestMessage, Object.class), false, null);
+      } else if (swaggerParameterTypes.size() == 1) {
+        Entry<String, Type> entry = swaggerParameterTypes.entrySet().iterator().next();
+        requestRootDeserializer = new RequestRootDeserializer<>(mapper.createRootDeserializer(requestMessage,
+            entry.getValue()), false, entry.getKey());
       } else {
-        if (swaggerParameterTypes.isEmpty()) {
-          requestRootDeserializer = new RequestRootDeserializer<>(
-              mapper.createRootDeserializer(requestMessage, Object.class), false, null);
-        } else if (swaggerParameterTypes.size() == 1) {
-          Entry<String, Type> entry = swaggerParameterTypes.entrySet().iterator().next();
-          requestRootDeserializer = new RequestRootDeserializer<>(mapper.createRootDeserializer(requestMessage,
-              entry.getValue()), false, entry.getKey());
-        } else {
-          throw new IllegalStateException(
-              "unexpected operation definition " + operationMeta.getMicroserviceQualifiedName());
-        }
+        throw new IllegalStateException(
+            "unexpected operation definition " + invocation.getOperationMeta().getMicroserviceQualifiedName());
       }
+    }
+  }
+
+  private void initConsumerRequestCodec(Invocation invocation, Message requestMessage, ProtoMapper mapper) {
+    if (ProtoUtils.isWrapArguments(requestMessage)) {
+      requestRootSerializer = new RequestRootSerializer(
+          mapper.createRootSerializer(requestMessage, Object.class), true, false);
     } else {
-      if (ProtoUtils.isWrapArguments(requestMessage)) {
-        requestRootSerializer = new RequestRootSerializer(
-            mapper.createRootSerializer(requestMessage, Object.class), true, false);
+      if (invocation.getOperationMeta().getSwaggerOperation().getParameters().isEmpty()) {
+        requestRootSerializer = new RequestRootSerializer(mapper.createRootSerializer(requestMessage, Object.class),
+            false, false);
+      } else if (invocation.getOperationMeta().getSwaggerOperation().getParameters().size() == 1) {
+        requestRootSerializer = new RequestRootSerializer(mapper.createRootSerializer(requestMessage,
+            Object.class), false, true);
       } else {
-        if (operationMeta.getSwaggerOperation().getParameters().isEmpty()) {
-          requestRootSerializer = new RequestRootSerializer(mapper.createRootSerializer(requestMessage, Object.class),
-              false, false);
-        } else if (operationMeta.getSwaggerOperation().getParameters().size() == 1) {
-          requestRootSerializer = new RequestRootSerializer(mapper.createRootSerializer(requestMessage,
-              Object.class), false, true);
-        } else {
-          throw new IllegalStateException(
-              "unexpected operation definition " + operationMeta.getMicroserviceQualifiedName());
-        }
+        throw new IllegalStateException(
+            "unexpected operation definition " + invocation.getOperationMeta().getMicroserviceQualifiedName());
       }
     }
   }
 
-  private void initResponseCodec(ScopedProtobufSchemaManager scopedProtobufSchemaManager, OperationMeta operationMeta) {
-    ProtoMapper mapper = scopedProtobufSchemaManager.getOrCreateProtoMapper(operationMeta.getSchemaMeta());
-    Message responseMessage = mapper.getResponseMessage(operationMeta.getOperationId());
+  private void initRequestCodec(ScopedProtobufSchemaManager scopedProtobufSchemaManager, Invocation invocation) {
+    ProtoMapper mapper = scopedProtobufSchemaManager.getOrCreateProtoMapper(invocation.getSchemaMeta());
+    Message requestMessage = mapper.getRequestMessage(invocation.getOperationMeta().getOperationId());
+
+    if (!invocation.isConsumer()) {
+      initProducerRequestCodec(invocation, requestMessage, mapper);
+    } else {
+      initConsumerRequestCodec(invocation, requestMessage, mapper);
+    }
+  }
 
-    JavaType responseType = operationMeta.getResponsesMeta().findResponseType(Status.OK.getStatusCode());
-    if (operationMeta.getSwaggerProducerOperation() != null) {
-      if (ProtoUtils.isWrapProperty(responseMessage)) {
-        responseRootSerializer = new ResponseRootSerializer(
-            mapper.createRootSerializer(responseMessage, responseType), true, false);
+  private void initProviderResponseCode(Message responseMessage, ProtoMapper mapper,
+      JavaType responseType) {
+    if (ProtoUtils.isWrapProperty(responseMessage)) {
+      responseRootSerializer = new ResponseRootSerializer(
+          mapper.createRootSerializer(responseMessage, responseType), true, false);
+    } else {
+      if (ProtoUtils.isEmptyMessage(responseMessage)) {
+        responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
+            Object.class), false, false);
       } else {
-        if (ProtoUtils.isEmptyMessage(responseMessage)) {
-          responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
-              Object.class), false, false);
-        } else {
-          responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
-              responseType), false, true);
-        }
+        responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
+            responseType), false, true);
       }
+    }
+  }
+
+  private void initConsumerResponseCode(Message responseMessage, ProtoMapper mapper,
+      JavaType responseType) {
+    if (ProtoUtils.isWrapProperty(responseMessage)) {
+      responseRootSerializer = new ResponseRootSerializer(
+          mapper.createRootSerializer(responseMessage, responseType), true, false);
+      responseRootDeserializer = new ResponseRootDeserializer<>(
+          mapper.createRootDeserializer(responseMessage, responseType), false);
     } else {
-      if (ProtoUtils.isWrapProperty(responseMessage)) {
-        responseRootSerializer = new ResponseRootSerializer(
-            mapper.createRootSerializer(responseMessage, responseType), true, false);
+      if (ProtoUtils.isEmptyMessage(responseMessage)) {
+        responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
+            Object.class), false, false);
         responseRootDeserializer = new ResponseRootDeserializer<>(
-            mapper.createRootDeserializer(responseMessage, responseType), false);
+            mapper.createRootDeserializer(responseMessage, Object.class), true);
       } else {
-        if (ProtoUtils.isEmptyMessage(responseMessage)) {
-          responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
-              Object.class), false, false);
-          responseRootDeserializer = new ResponseRootDeserializer<>(
-              mapper.createRootDeserializer(responseMessage, Object.class), true);
-        } else {
-          responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
-              responseType), false, false);
-          responseRootDeserializer = new ResponseRootDeserializer<>(
-              mapper.createRootDeserializer(responseMessage, responseType), false);
-        }
+        responseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(responseMessage,
+            responseType), false, false);
+        responseRootDeserializer = new ResponseRootDeserializer<>(
+            mapper.createRootDeserializer(responseMessage, responseType), false);
       }
     }
+  }
+
+  private void initResponseCodec(ScopedProtobufSchemaManager scopedProtobufSchemaManager, Invocation invocation) {
+    ProtoMapper mapper = scopedProtobufSchemaManager.getOrCreateProtoMapper(invocation.getSchemaMeta());
+    Message responseMessage = mapper.getResponseMessage(invocation.getOperationMeta().getOperationId());
+
+    JavaType responseType = invocation.findResponseType(Status.OK.getStatusCode());
+    if (!invocation.isConsumer()) {
+      initProviderResponseCode(responseMessage, mapper, responseType);
+    } else {
+      initConsumerResponseCode(responseMessage, mapper, responseType);
+    }
     anyResponseRootSerializer = new ResponseRootSerializer(mapper.createRootSerializer(ProtoConst.ANY,
         Object.class), false, true);
     anyResponseRootDeserializer = new ResponseRootDeserializer<>(
diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java
index 86ef301..f0b0fd2 100644
--- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java
+++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java
@@ -17,34 +17,99 @@
 
 package org.apache.servicecomb.codec.protobuf.definition;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
 import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager;
+import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
-import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.google.common.annotations.VisibleForTesting;
 
 public final class ProtobufManager {
   public static final String EXT_ID = "protobuf";
 
   private static final Object LOCK = new Object();
 
-  public static OperationProtobuf getOrCreateOperation(OperationMeta operationMeta) {
-    OperationProtobuf operationProtobuf = operationMeta.getExtData(EXT_ID);
+  static class RuntimeCacheKey {
+    final InvocationType invocationType;
+
+    final String uniqueOperationId;
+
+    // Using response type as the cache key.
+    // May consider request type as well, but now not implemented
+    final JavaType responseType;
+
+    public RuntimeCacheKey(InvocationType invocationType, String operationId, JavaType responseType) {
+      this.invocationType = invocationType;
+      this.uniqueOperationId = operationId;
+      this.responseType = responseType;
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+
+      RuntimeCacheKey that = (RuntimeCacheKey) o;
+
+      if (invocationType != that.invocationType) {
+        return false;
+      }
+      if (!uniqueOperationId.equals(that.uniqueOperationId)) {
+        return false;
+      }
+      return responseType != null ? responseType.equals(that.responseType)
+          : that.responseType == null;
+    }
+
+    @Override
+    public int hashCode() {
+      int result = invocationType.hashCode();
+      result = 31 * result + uniqueOperationId.hashCode();
+      result = 31 * result + (responseType != null ? responseType.hashCode() : 0);
+      return result;
+    }
+  }
+
+  private static final Map<RuntimeCacheKey, OperationProtobuf> RUNTIME_CACHE = new HashMap<>();
+
+  public static OperationProtobuf getOrCreateOperation(Invocation invocation) {
+    RuntimeCacheKey cacheKey = new RuntimeCacheKey(invocation.getInvocationType(),
+        invocation.getOperationMeta().getMicroserviceQualifiedName(),
+        invocation.findResponseType(Status.OK.getStatusCode()));
+    OperationProtobuf operationProtobuf = RUNTIME_CACHE.get(cacheKey);
     if (operationProtobuf == null) {
       synchronized (LOCK) {
-        MicroserviceMeta microserviceMeta = operationMeta.getMicroserviceMeta();
+        MicroserviceMeta microserviceMeta = invocation.getMicroserviceMeta();
         ScopedProtobufSchemaManager scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID);
         if (scopedProtobufSchemaManager == null) {
           scopedProtobufSchemaManager = new ScopedProtobufSchemaManager();
           microserviceMeta.putExtData(EXT_ID, scopedProtobufSchemaManager);
         }
 
-        operationProtobuf = operationMeta.getExtData(EXT_ID);
+        operationProtobuf = RUNTIME_CACHE.get(cacheKey);
         if (operationProtobuf == null) {
-          operationProtobuf = new OperationProtobuf(scopedProtobufSchemaManager, operationMeta);
-          operationMeta.putExtData(EXT_ID, operationProtobuf);
+          operationProtobuf = new OperationProtobuf(scopedProtobufSchemaManager, invocation);
+          RUNTIME_CACHE.put(cacheKey, operationProtobuf);
         }
       }
     }
 
     return operationProtobuf;
   }
+
+  @VisibleForTesting
+  public static void clear() {
+    RUNTIME_CACHE.clear();
+  }
 }
diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java
index 2fd0ec0..822d4d8 100644
--- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java
+++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java
@@ -34,6 +34,8 @@ import org.apache.servicecomb.codec.protobuf.definition.ResponseRootDeserializer
 import org.apache.servicecomb.codec.protobuf.definition.ResponseRootSerializer;
 import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchema;
 import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchemaPojo;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.definition.InvocationRuntimeType;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.definition.SchemaMeta;
@@ -48,9 +50,11 @@ import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
 import org.apache.servicecomb.swagger.generator.core.AbstractSwaggerGenerator;
 import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGenerator;
 import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
@@ -75,10 +79,11 @@ public class TestSchemaMetaCodec {
 
   @Before
   public void setUp() {
-
+    ProtobufManager.clear();
   }
 
-  private void mockSchemaMeta(AbstractSwaggerGenerator swaggerGenerator, Object producerInstance) throws Exception {
+  private void mockSchemaMeta(String schemaId, AbstractSwaggerGenerator swaggerGenerator, Object producerInstance)
+      throws Exception {
     new Expectations() {
       {
         providerMicroserviceMeta.getMicroserviceName();
@@ -94,33 +99,67 @@ public class TestSchemaMetaCodec {
     Swagger swagger = swaggerGenerator.generate();
     SwaggerEnvironment swaggerEnvironment = new SwaggerEnvironment();
 
-    providerSchemaMeta = new SchemaMeta(providerMicroserviceMeta, "ProtoSchema", swagger);
+    providerSchemaMeta = new SchemaMeta(providerMicroserviceMeta, schemaId, swagger);
     SwaggerProducer swaggerProducer = swaggerEnvironment.createProducer(producerInstance, swagger);
     for (SwaggerProducerOperation producerOperation : swaggerProducer.getAllOperations()) {
       OperationMeta operationMeta = providerSchemaMeta.ensureFindOperation(producerOperation.getOperationId());
       operationMeta.setSwaggerProducerOperation(producerOperation);
     }
 
-    consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, "ProtoSchema", swagger);
+    consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, schemaId, swagger);
   }
 
   @Test
   public void testProtoSchemaOperationUserSpringMVC() throws Exception {
-    mockSchemaMeta(new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
+    mockSchemaMeta("ProtoSchema", new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
     testProtoSchemaOperationUserImpl();
   }
 
   @Test
   public void testProtoSchemaOperationUserPOJO() throws Exception {
-    mockSchemaMeta(new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
+    mockSchemaMeta("ProtoSchemaPojo", new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
     testProtoSchemaOperationUserImpl();
   }
 
+  private Invocation mockInvocation(String operation, InvocationType invocationType) {
+    OperationMeta operationMeta;
+    boolean isConsumer;
+    Invocation invocation = Mockito.mock(Invocation.class);
+    InvocationRuntimeType invocationRuntimeType;
+
+    if (InvocationType.CONSUMER == invocationType) {
+      operationMeta = consumerSchemaMeta.getOperations().get(operation);
+      isConsumer = true;
+      Mockito.when(invocation.getSchemaMeta()).thenReturn(consumerSchemaMeta);
+      invocationRuntimeType = operationMeta.buildBaseConsumerRuntimeType();
+    } else {
+      operationMeta = providerSchemaMeta.getOperations().get(operation);
+      isConsumer = false;
+      Mockito.when(invocation.getSchemaMeta()).thenReturn(providerSchemaMeta);
+      invocationRuntimeType = operationMeta.buildBaseProviderRuntimeType();
+    }
+
+    MicroserviceMeta microserviceMeta = operationMeta.getMicroserviceMeta();
+    Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
+    Mockito.when(invocation.getInvocationRuntimeType())
+        .thenReturn(invocationRuntimeType);
+    Mockito.when(invocation.findResponseType(200))
+        .thenReturn(invocationRuntimeType.findResponseType(200));
+    Mockito.when(invocation.getInvocationType()).thenReturn(invocationType);
+    Mockito.when(invocation.getMicroserviceMeta()).thenReturn(microserviceMeta);
+
+    Mockito.when(invocation.isConsumer()).thenReturn(isConsumer);
+    return invocation;
+  }
+
   private void testProtoSchemaOperationUserImpl() throws IOException {
+    Invocation consumerInvocation = mockInvocation("user", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("user", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("user"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("user"));
+        .getOrCreateOperation(consumerInvocation);
     User user = new User();
     user.name = "user";
     User friend = new User();
@@ -178,21 +217,24 @@ public class TestSchemaMetaCodec {
 
   @Test
   public void testProtoSchemaOperationmapUserSpringMVC() throws Exception {
-    mockSchemaMeta(new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
+    mockSchemaMeta("ProtoSchema", new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
     testProtoSchemaOperationmapUserImpl(false);
   }
 
   @Test
   public void testProtoSchemaOperationmapUserPOJO() throws Exception {
-    mockSchemaMeta(new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
+    mockSchemaMeta("ProtoSchemaPojo", new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
     testProtoSchemaOperationmapUserImpl(true);
   }
 
   private void testProtoSchemaOperationmapUserImpl(boolean isPojo) throws IOException {
+    Invocation consumerInvocation = mockInvocation("mapUser", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("mapUser", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("mapUser"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("mapUser"));
+        .getOrCreateOperation(consumerInvocation);
     User user = new User();
     user.name = "user";
     User friend = new User();
@@ -248,21 +290,24 @@ public class TestSchemaMetaCodec {
 
   @Test
   public void testProtoSchemaOperationBaseSpringMVC() throws Exception {
-    mockSchemaMeta(new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
+    mockSchemaMeta("ProtoSchema", new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
     testProtoSchemaOperationBaseImpl(false);
   }
 
   @Test
   public void testProtoSchemaOperationBasePOJO() throws Exception {
-    mockSchemaMeta(new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
+    mockSchemaMeta("ProtoSchemaPojo", new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
     testProtoSchemaOperationBaseImpl(true);
   }
 
   private void testProtoSchemaOperationBaseImpl(boolean isPojo) throws IOException {
+    Invocation consumerInvocation = mockInvocation("base", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("base", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("base"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("base"));
+        .getOrCreateOperation(consumerInvocation);
     byte[] values;
 
     // request message
@@ -364,21 +409,24 @@ public class TestSchemaMetaCodec {
 
   @Test
   public void testProtoSchemaOperationlistListUserSpringMVC() throws Exception {
-    mockSchemaMeta(new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
+    mockSchemaMeta("ProtoSchema", new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
     testProtoSchemaOperationlistListUserImpl(false);
   }
 
   @Test
   public void testProtoSchemaOperationlistListUserPOJO() throws Exception {
-    mockSchemaMeta(new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
+    mockSchemaMeta("ProtoSchemaPojo", new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
     testProtoSchemaOperationlistListUserImpl(true);
   }
 
   private void testProtoSchemaOperationlistListUserImpl(boolean isPojo) throws IOException {
+    Invocation consumerInvocation = mockInvocation("listListUser", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("listListUser", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("listListUser"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("listListUser"));
+        .getOrCreateOperation(consumerInvocation);
     byte[] values;
 
     // request message
@@ -434,21 +482,24 @@ public class TestSchemaMetaCodec {
 
   @Test
   public void testProtoSchemaOperationObjSpringMVC() throws Exception {
-    mockSchemaMeta(new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
+    mockSchemaMeta("ProtoSchema", new SpringmvcSwaggerGenerator(ProtoSchema.class), new ProtoSchema());
     testProtoSchemaOperationObjImpl(false);
   }
 
   @Test
   public void testProtoSchemaOperationObjPOJO() throws Exception {
-    mockSchemaMeta(new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
+    mockSchemaMeta("ProtoSchemaPojo", new PojoSwaggerGenerator(ProtoSchemaPojo.class), new ProtoSchemaPojo());
     testProtoSchemaOperationObjImpl(true);
   }
 
   private void testProtoSchemaOperationObjImpl(boolean isPojo) throws IOException {
+    Invocation consumerInvocation = mockInvocation("obj", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("obj", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("obj"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("obj"));
+        .getOrCreateOperation(consumerInvocation);
     byte[] values;
 
     // request message
diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java
index 191a419..c638e8c 100644
--- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java
+++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java
@@ -31,6 +31,8 @@ import org.apache.servicecomb.codec.protobuf.definition.RequestRootSerializer;
 import org.apache.servicecomb.codec.protobuf.definition.ResponseRootDeserializer;
 import org.apache.servicecomb.codec.protobuf.definition.ResponseRootSerializer;
 import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchema;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.definition.InvocationRuntimeType;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.definition.SchemaMeta;
@@ -41,9 +43,11 @@ import org.apache.servicecomb.swagger.engine.SwaggerEnvironment;
 import org.apache.servicecomb.swagger.engine.SwaggerProducer;
 import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
 import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
@@ -67,6 +71,8 @@ public class TestSchemaMetaCodecRestTemplate {
 
   @Before
   public void setUp() {
+    ProtobufManager.clear();
+
     new Expectations() {
       {
         providerMicroserviceMeta.getMicroserviceName();
@@ -93,12 +99,46 @@ public class TestSchemaMetaCodecRestTemplate {
     consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, "ProtoSchema", swagger);
   }
 
+  private Invocation mockInvocation(String operation, InvocationType invocationType) {
+    OperationMeta operationMeta;
+    boolean isConsumer;
+    Invocation invocation = Mockito.mock(Invocation.class);
+    InvocationRuntimeType invocationRuntimeType;
+
+    if (InvocationType.CONSUMER == invocationType) {
+      operationMeta = consumerSchemaMeta.getOperations().get(operation);
+      isConsumer = true;
+      Mockito.when(invocation.getSchemaMeta()).thenReturn(consumerSchemaMeta);
+      invocationRuntimeType = operationMeta.buildBaseConsumerRuntimeType();
+    } else {
+      operationMeta = providerSchemaMeta.getOperations().get(operation);
+      isConsumer = false;
+      Mockito.when(invocation.getSchemaMeta()).thenReturn(providerSchemaMeta);
+      invocationRuntimeType = operationMeta.buildBaseProviderRuntimeType();
+    }
+
+    MicroserviceMeta microserviceMeta = operationMeta.getMicroserviceMeta();
+    Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
+    Mockito.when(invocation.getInvocationRuntimeType())
+        .thenReturn(invocationRuntimeType);
+    Mockito.when(invocation.findResponseType(200))
+        .thenReturn(invocationRuntimeType.findResponseType(200));
+    Mockito.when(invocation.getInvocationType()).thenReturn(invocationType);
+    Mockito.when(invocation.getMicroserviceMeta()).thenReturn(microserviceMeta);
+
+    Mockito.when(invocation.isConsumer()).thenReturn(isConsumer);
+    return invocation;
+  }
+
   @Test
   public void testProtoSchemaOperationUser() throws Exception {
+    Invocation consumerInvocation = mockInvocation("user", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("user", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("user"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("user"));
+        .getOrCreateOperation(consumerInvocation);
     User user = new User();
     user.name = "user";
     User friend = new User();
@@ -124,13 +164,15 @@ public class TestSchemaMetaCodecRestTemplate {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(user);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    User decodedUser = (User) responseDeserializer.deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
+    User decodedUser = (User) responseDeserializer
+        .deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
     Assert.assertEquals(user.name, decodedUser.name);
     Assert.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name);
 
     user.friends = new ArrayList<>();
     values = responseSerializer.serialize(user);
-    decodedUser = (User) responseDeserializer.deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
+    decodedUser = (User) responseDeserializer
+        .deserialize(values, TypeFactory.defaultInstance().constructType(User.class));
     Assert.assertEquals(user.name, decodedUser.name);
     // proto buffer encode and decode empty list to be null
     Assert.assertEquals(null, decodedUser.friends);
@@ -139,10 +181,13 @@ public class TestSchemaMetaCodecRestTemplate {
   @Test
   @SuppressWarnings({"rawtypes", "unchecked"})
   public void testProtoSchemaOperationBase() throws Exception {
+    Invocation consumerInvocation = mockInvocation("base", InvocationType.CONSUMER);
+    Invocation providerInvocation = mockInvocation("base", InvocationType.PRODUCER);
+
     OperationProtobuf providerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(providerSchemaMeta.getOperations().get("base"));
+        .getOrCreateOperation(providerInvocation);
     OperationProtobuf consumerOperationProtobuf = ProtobufManager
-        .getOrCreateOperation(consumerSchemaMeta.getOperations().get("base"));
+        .getOrCreateOperation(consumerInvocation);
     byte[] values;
 
     // request message
@@ -214,7 +259,8 @@ public class TestSchemaMetaCodecRestTemplate {
     ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200);
     values = responseSerializer.serialize(30);
     ResponseRootDeserializer<Object> responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200);
-    Object decodedValue = responseDeserializer.deserialize(values, TypeFactory.defaultInstance().constructType(int.class));
+    Object decodedValue = responseDeserializer
+        .deserialize(values, TypeFactory.defaultInstance().constructType(int.class));
     Assert.assertEquals(30, (int) decodedValue);
   }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/Invocation.java b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
index 75b1ddb..38dbeb6 100644
--- a/core/src/main/java/org/apache/servicecomb/core/Invocation.java
+++ b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
@@ -324,6 +324,10 @@ public class Invocation extends SwaggerInvocation {
     return referenceConfig.getVersionRule();
   }
 
+  public InvocationRuntimeType getInvocationRuntimeType() {
+    return this.invocationRuntimeType;
+  }
+
   public JavaType findResponseType(int statusCode) {
     return this.invocationRuntimeType.findResponseType(statusCode);
   }
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java
index ec03ef8..4fd41fc 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java
@@ -74,7 +74,7 @@ public class RestObjectMapper extends AbstractRestObjectMapper {
   @SuppressWarnings("unchecked")
   public <T> T convertValue(Object fromValue, JavaType toValueType) throws IllegalArgumentException {
     // After jackson 2.10.*, will by pass the following check when convert value. But this is useful
-    // for java chassis applications and do not need to convert. So add the check here.(conversion is
+    // for java chassis applications and do not need to convert to keep performance. So add the check here.(conversion is
     // not necessary and will cause some trouble in some user applications that depend on this)
     if (fromValue == null) {
       return null;
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/TypesUtil.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/TypesUtil.java
new file mode 100644
index 0000000..5f72a1d
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/TypesUtil.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.common.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+/**
+ * common utils to convert java types.
+ */
+public class TypesUtil {
+  private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER = new HashMap<>();
+
+  static {
+    PRIMITIVE_TO_WRAPPER.put(byte.class, Byte.class);
+    PRIMITIVE_TO_WRAPPER.put(short.class, Short.class);
+    PRIMITIVE_TO_WRAPPER.put(int.class, Integer.class);
+    PRIMITIVE_TO_WRAPPER.put(long.class, Long.class);
+    PRIMITIVE_TO_WRAPPER.put(float.class, Float.class);
+    PRIMITIVE_TO_WRAPPER.put(double.class, Double.class);
+    PRIMITIVE_TO_WRAPPER.put(boolean.class, Boolean.class);
+    PRIMITIVE_TO_WRAPPER.put(char.class, Character.class);
+  }
+
+
+  private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE = new HashMap<>();
+
+  static {
+    WRAPPER_TO_PRIMITIVE.put(Byte.class, byte.class);
+    WRAPPER_TO_PRIMITIVE.put(Short.class, short.class);
+    WRAPPER_TO_PRIMITIVE.put(Integer.class, int.class);
+    WRAPPER_TO_PRIMITIVE.put(Long.class, long.class);
+    WRAPPER_TO_PRIMITIVE.put(Float.class, float.class);
+    WRAPPER_TO_PRIMITIVE.put(Double.class, double.class);
+    WRAPPER_TO_PRIMITIVE.put(Boolean.class, boolean.class);
+    WRAPPER_TO_PRIMITIVE.put(Character.class, char.class);
+  }
+
+  public static final JavaType PRIMITIVE_BYTE = TypeFactory.defaultInstance().constructType(byte.class);
+
+  public static final JavaType PRIMITIVE_SHORT = TypeFactory.defaultInstance().constructType(short.class);
+
+  public static final JavaType PRIMITIVE_INT = TypeFactory.defaultInstance().constructType(int.class);
+
+  public static final JavaType PRIMITIVE_LONG = TypeFactory.defaultInstance().constructType(long.class);
+
+  public static final JavaType PRIMITIVE_FLOAT = TypeFactory.defaultInstance().constructType(float.class);
+
+  public static final JavaType PRIMITIVE_DOUBLE = TypeFactory.defaultInstance().constructType(double.class);
+
+  public static final JavaType PRIMITIVE_BOOLEAN = TypeFactory.defaultInstance().constructType(boolean.class);
+
+  public static final JavaType PRIMITIVE_CHAR = TypeFactory.defaultInstance().constructType(char.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_BYTE = TypeFactory.defaultInstance().constructType(Byte.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_SHORT = TypeFactory.defaultInstance().constructType(Short.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_INT = TypeFactory.defaultInstance().constructType(Integer.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_LONG = TypeFactory.defaultInstance().constructType(Long.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_FLOAT = TypeFactory.defaultInstance().constructType(Float.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_DOUBLE = TypeFactory.defaultInstance().constructType(Double.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_BOOLEAN = TypeFactory.defaultInstance().constructType(Boolean.class);
+
+  public static final JavaType PRIMITIVE_WRAPPER_CHAR = TypeFactory.defaultInstance().constructType(Character.class);
+
+
+  private static final Map<JavaType, JavaType> PRIMITIVE_TO_WRAPPER_JAVATYPE = new HashMap<>();
+
+  static {
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_BYTE, PRIMITIVE_WRAPPER_BYTE);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_SHORT, PRIMITIVE_WRAPPER_SHORT);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_INT, PRIMITIVE_WRAPPER_INT);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_LONG, PRIMITIVE_WRAPPER_LONG);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_FLOAT, PRIMITIVE_WRAPPER_FLOAT);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_DOUBLE, PRIMITIVE_WRAPPER_DOUBLE);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_BOOLEAN, PRIMITIVE_WRAPPER_BOOLEAN);
+    PRIMITIVE_TO_WRAPPER_JAVATYPE.put(PRIMITIVE_CHAR, PRIMITIVE_WRAPPER_CHAR);
+  }
+
+  private static final Map<JavaType, JavaType> WRAPPER_TO_PRIMITIVE_JAVATYPE = new HashMap<>();
+
+  static {
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_BYTE, PRIMITIVE_BYTE);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_SHORT, PRIMITIVE_SHORT);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_INT, PRIMITIVE_INT);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_LONG, PRIMITIVE_LONG);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_FLOAT, PRIMITIVE_FLOAT);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_DOUBLE, PRIMITIVE_DOUBLE);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_BOOLEAN, PRIMITIVE_BOOLEAN);
+    WRAPPER_TO_PRIMITIVE_JAVATYPE.put(PRIMITIVE_WRAPPER_CHAR, PRIMITIVE_CHAR);
+  }
+
+  public static Class<?> primitiveTypeToWrapper(Class<?> primitiveType) {
+    return PRIMITIVE_TO_WRAPPER.get(primitiveType);
+  }
+
+  public static Class<?> wrapperTypeToPrimitive(Class<?> wrapperType) {
+    return WRAPPER_TO_PRIMITIVE.get(wrapperType);
+  }
+
+  public static JavaType primitiveJavaTypeToWrapper(JavaType primitiveType) {
+    return PRIMITIVE_TO_WRAPPER_JAVATYPE.get(primitiveType);
+  }
+
+  public static JavaType wrapperJavaTypeToPrimitive(JavaType wrapperType) {
+    return WRAPPER_TO_PRIMITIVE_JAVATYPE.get(wrapperType);
+  }
+}
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java
new file mode 100644
index 0000000..c2fe52c
--- /dev/null
+++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.foundation.common.utils;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestTypesUtil {
+  @Test
+  public void testTypesUtil() {
+    Assert.assertEquals(double.class, TypesUtil.wrapperTypeToPrimitive(Double.class));
+    Assert.assertEquals(Float.class, TypesUtil.primitiveTypeToWrapper(float.class));
+    Assert
+        .assertEquals(TypesUtil.PRIMITIVE_CHAR, TypesUtil.wrapperJavaTypeToPrimitive(TypesUtil.PRIMITIVE_WRAPPER_CHAR));
+    Assert
+        .assertEquals(TypesUtil.PRIMITIVE_WRAPPER_BYTE, TypesUtil.primitiveJavaTypeToWrapper(TypesUtil.PRIMITIVE_BYTE));
+  }
+}
diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
index 9965a62..cf47f8f 100644
--- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
+++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java
@@ -21,9 +21,9 @@ import static org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils.isW
 import java.lang.reflect.Type;
 import java.util.Map;
 
+import org.apache.servicecomb.foundation.common.utils.TypesUtil;
 import org.apache.servicecomb.foundation.protobuf.ProtoMapper;
 import org.apache.servicecomb.foundation.protobuf.RootDeserializer;
-import org.apache.servicecomb.foundation.protobuf.RootSerializer;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst;
 import org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils;
 import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyDescriptor;
@@ -124,7 +124,13 @@ public class DeserializerSchemaManager extends SchemaManager {
             protoField.isRepeated() && !protoField.isMap() ? ProtoConst.LIST_TYPE
                 : ProtoConst.MAP_TYPE;
       }
-      javaType = TypeFactory.defaultInstance().constructParametricType(PropertyWrapper.class, javaType);
+
+      if (javaType.isPrimitive()) {
+        javaType = TypeFactory.defaultInstance()
+            .constructParametricType(PropertyWrapper.class, TypesUtil.primitiveJavaTypeToWrapper(javaType));
+      } else {
+        javaType = TypeFactory.defaultInstance().constructParametricType(PropertyWrapper.class, javaType);
+      }
     }
 
     if (javaType.isJavaLangObject()) {
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java
index 56c61e2..b80cd43 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java
@@ -92,7 +92,7 @@ public class HighwayClient {
     HighwayClientConnectionPool tcpClientPool = clientMgr.findClientPool(invocation.isSync());
 
     OperationMeta operationMeta = invocation.getOperationMeta();
-    OperationProtobuf operationProtobuf = ProtobufManager.getOrCreateOperation(operationMeta);
+    OperationProtobuf operationProtobuf = ProtobufManager.getOrCreateOperation(invocation);
 
     HighwayClientConnection tcpClient =
         tcpClientPool.findOrCreateClient(invocation.getEndpoint().getEndpoint());
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
index 61423f2..ea8fd0b 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
@@ -60,16 +60,16 @@ public final class HighwayCodec {
   }
 
   @SuppressWarnings({"rawtypes", "unchecked"})
-  private static Map<String, Object> addPrimitiveTypeDefaultValues(Invocation invocation, OperationMeta operationMeta,
+  private static Map<String, Object> addPrimitiveTypeDefaultValues(Invocation invocation,
       Map<String, Object> swaggerArguments) {
     // proto buffer never serialize default values, put it back in provider
-    SwaggerProducerOperation swaggerProducerOperation = operationMeta.getSwaggerProducerOperation();
-    if (swaggerProducerOperation != null && !invocation.isEdge()) {
-      List<Parameter> swaggerParameters = operationMeta.getSwaggerOperation()
+    if (invocation.getOperationMeta().getSwaggerProducerOperation() != null && !invocation.isEdge()) {
+      List<Parameter> swaggerParameters = invocation.getOperationMeta().getSwaggerOperation()
           .getParameters();
       for (Parameter parameter : swaggerParameters) {
         if (swaggerArguments.get(parameter.getName()) == null) {
-          Type type = swaggerProducerOperation.getSwaggerParameterType(parameter.getName());
+          Type type = invocation.getOperationMeta().getSwaggerProducerOperation()
+              .getSwaggerParameterType(parameter.getName());
           if (type instanceof Class) {
             if (((Class) type).isPrimitive()) {
               swaggerArguments.put(parameter.getName(), Defaults.defaultValue((Class) type));
@@ -86,7 +86,7 @@ public final class HighwayCodec {
       Buffer bodyBuffer) throws Exception {
     RequestRootDeserializer<Object> requestDeserializer = operationProtobuf.getRequestRootDeserializer();
     Map<String, Object> swaggerArguments = requestDeserializer.deserialize(bodyBuffer.getBytes());
-    addPrimitiveTypeDefaultValues(invocation, operationProtobuf.getOperationMeta(), swaggerArguments);
+    addPrimitiveTypeDefaultValues(invocation, swaggerArguments);
     invocation.setSwaggerArguments(swaggerArguments);
     invocation.mergeContext(header.getContext());
   }
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java
index d8a6cd3..47c9afa 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java
@@ -52,8 +52,6 @@ public class HighwayServerInvoke {
 
   private OperationMeta operationMeta;
 
-  private OperationProtobuf operationProtobuf;
-
   private TcpConnection connection;
 
   private long msgId;
@@ -62,9 +60,11 @@ public class HighwayServerInvoke {
 
   private Endpoint endpoint;
 
-  Invocation invocation;
+  private Invocation invocation;
 
-  protected long start;
+  private OperationProtobuf operationProtobuf;
+
+  private long start;
 
   public HighwayServerInvoke(Endpoint endpoint) {
     this.start = System.nanoTime();
@@ -97,8 +97,6 @@ public class HighwayServerInvoke {
     MicroserviceMeta microserviceMeta = SCBEngine.getInstance().getProducerMicroserviceMeta();
     SchemaMeta schemaMeta = microserviceMeta.ensureFindSchemaMeta(header.getSchemaId());
     this.operationMeta = schemaMeta.ensureFindOperation(header.getOperationName());
-    this.operationProtobuf = ProtobufManager.getOrCreateOperation(operationMeta);
-
     this.bodyBuffer = bodyBuffer;
   }
 
@@ -154,9 +152,9 @@ public class HighwayServerInvoke {
       invocation.getInvocationStageTrace().finishServerFiltersResponse();
       connection.write(respBuffer.getByteBuf());
     } catch (Exception e) {
-      // 没招了,直接打日志
+      // keep highway performance and simple, this encoding/decoding error not need handle by client
       String msg = String.format("encode response failed, %s, msgId=%d",
-          operationProtobuf.getOperationMeta().getMicroserviceQualifiedName(),
+          invocation.getOperationMeta().getMicroserviceQualifiedName(),
           msgId);
       LOGGER.error(msg, e);
     } finally {
@@ -172,8 +170,9 @@ public class HighwayServerInvoke {
   public void execute() {
     try {
       invocation = InvocationFactory.forProvider(endpoint,
-          operationProtobuf.getOperationMeta(),
+          operationMeta,
           null);
+      operationProtobuf = ProtobufManager.getOrCreateOperation(invocation);
       invocation.onStart(null, start);
       invocation.getInvocationStageTrace().startSchedule();
 
diff --git a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java
index 914f9b7..baaef46 100644
--- a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java
+++ b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java
@@ -130,7 +130,7 @@ public class TestHighwayClient {
 
     new MockUp<ProtobufManager>() {
       @Mock
-      public OperationProtobuf getOrCreateOperation(OperationMeta operationMeta) {
+      public OperationProtobuf getOrCreateOperation(Invocation operationMeta) {
         return operationProtobuf;
       }
     };
diff --git a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java
index e0cd2df..55f29d9 100644
--- a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java
+++ b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java
@@ -181,7 +181,7 @@ public class TestHighwayCodec {
     Mockito.when(bodyBuffer.getByteBuf()).thenReturn(lByteBuf);
     Mockito.when(bodyBuffer.getBytes()).thenReturn(new byte[0]);
     Mockito.when(lByteBuf.nioBuffer()).thenReturn(nioBuffer);
-    Mockito.when(operationProtobuf.getOperationMeta()).thenReturn(operationMeta);
+
     Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta);
     Mockito.when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta);
   }