You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@servicecomb.apache.org by GitBox <gi...@apache.org> on 2017/12/27 02:10:56 UTC

[GitHub] liubao68 closed pull request #464: [JAV-583] Pojo consumer return completable future

liubao68 closed pull request #464: [JAV-583] Pojo consumer return completable future
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/464
 
 
   

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

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

diff --git a/core/src/main/java/io/servicecomb/core/definition/MicroserviceVersionMeta.java b/core/src/main/java/io/servicecomb/core/definition/MicroserviceVersionMeta.java
index 52e54bb72..76627e906 100644
--- a/core/src/main/java/io/servicecomb/core/definition/MicroserviceVersionMeta.java
+++ b/core/src/main/java/io/servicecomb/core/definition/MicroserviceVersionMeta.java
@@ -35,10 +35,10 @@ public MicroserviceVersionMeta(String microserviceName, String microserviceId,
     if (Const.REGISTRY_APP_ID.equals(microservice.getAppId()) && Const.REGISTRY_SERVICE_NAME.equals(microserviceName)) {
       // do not load service center schemas
       return;
-    } else {
-      CseContext.getInstance().getConsumerSchemaFactory().getOrCreateConsumerSchema(microserviceMeta, microservice);
-      CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(microserviceMeta);
     }
+
+    CseContext.getInstance().getConsumerSchemaFactory().getOrCreateConsumerSchema(microserviceMeta, microservice);
+    CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(microserviceMeta);
   }
 
   public MicroserviceMeta getMicroserviceMeta() {
diff --git a/core/src/main/java/io/servicecomb/core/definition/OperationMeta.java b/core/src/main/java/io/servicecomb/core/definition/OperationMeta.java
index a1abf3b42..f3ea286ef 100644
--- a/core/src/main/java/io/servicecomb/core/definition/OperationMeta.java
+++ b/core/src/main/java/io/servicecomb/core/definition/OperationMeta.java
@@ -24,7 +24,6 @@
 import java.util.concurrent.Executor;
 
 import io.servicecomb.core.executor.ExecutorManager;
-import io.servicecomb.swagger.invocation.AsyncResponse;
 import io.servicecomb.swagger.invocation.response.ResponseMeta;
 import io.servicecomb.swagger.invocation.response.ResponsesMeta;
 import io.swagger.models.Operation;
@@ -41,8 +40,6 @@
   // ?????method??consumer?producer?method??????
   private Method method;
 
-  private boolean sync;
-
   private String httpMethod;
 
   private String operationPath;
@@ -67,9 +64,8 @@ public void init(SchemaMeta schemaMeta, Method method, String operationPath, Str
     this.method = method;
     this.httpMethod = httpMethod.toUpperCase(Locale.US);
     this.swaggerOperation = swaggerOperation;
-    executor = ExecutorManager.findExecutor(this);
 
-    collectMethodType();
+    executor = ExecutorManager.findExecutor(this);
 
     responsesMeta.init(schemaMeta.getMicroserviceMeta().getClassLoader(),
         schemaMeta.getPackageName(),
@@ -90,17 +86,6 @@ public String getOperationPath() {
     return operationPath;
   }
 
-  private void collectMethodType() {
-    Class<?>[] params = method.getParameterTypes();
-    if (params.length == 0) {
-      sync = true;
-      return;
-    }
-
-    Class<?> lastParam = params[params.length - 1];
-    sync = !AsyncResponse.class.isAssignableFrom(lastParam);
-  }
-
   public Operation getSwaggerOperation() {
     return swaggerOperation;
   }
@@ -147,10 +132,6 @@ public void putExtData(String key, Object data) {
     return (T) extData.get(key);
   }
 
-  public boolean isSync() {
-    return sync;
-  }
-
   public Executor getExecutor() {
     return executor;
   }
diff --git a/core/src/main/java/io/servicecomb/core/provider/consumer/InvokerUtils.java b/core/src/main/java/io/servicecomb/core/provider/consumer/InvokerUtils.java
index 8ef593b33..c142493ed 100644
--- a/core/src/main/java/io/servicecomb/core/provider/consumer/InvokerUtils.java
+++ b/core/src/main/java/io/servicecomb/core/provider/consumer/InvokerUtils.java
@@ -87,14 +87,8 @@ public static void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp
     }
   }
 
+  @Deprecated
   public static Object invoke(Invocation invocation) {
-    if (invocation.getOperationMeta().isSync()) {
-      return syncInvoke(invocation);
-    }
-
-    Object[] args = invocation.getArgs();
-    AsyncResponse asyncResp = (AsyncResponse) args[args.length - 1];
-    reactiveInvoke(invocation, asyncResp);
-    return null;
+    return syncInvoke(invocation);
   }
 }
diff --git a/core/src/test/java/io/servicecomb/core/TestConsumer.java b/core/src/test/java/io/servicecomb/core/TestConsumer.java
index 331de0cf2..d10e62b74 100644
--- a/core/src/test/java/io/servicecomb/core/TestConsumer.java
+++ b/core/src/test/java/io/servicecomb/core/TestConsumer.java
@@ -30,7 +30,6 @@
 import io.servicecomb.core.definition.OperationMeta;
 import io.servicecomb.core.definition.SchemaMeta;
 import io.servicecomb.core.provider.consumer.ConsumerProviderManager;
-import io.servicecomb.core.provider.consumer.InvokerUtils;
 import io.servicecomb.core.provider.consumer.SyncResponseExecutor;
 import io.servicecomb.foundation.common.RegisterManager;
 import io.servicecomb.swagger.invocation.AsyncResponse;
@@ -73,39 +72,6 @@ public void run() {
     Assert.assertEquals(true, oExecutor.waitResponse().isSuccessed());
   }
 
-  @Test
-  public void testInvokerUtils() {
-    Invocation oInvocation = Mockito.mock(Invocation.class);
-    OperationMeta oOperationMeta = Mockito.mock(OperationMeta.class);
-    Mockito.when(oOperationMeta.isSync()).thenReturn(false);
-    Mockito.when(oInvocation.getOperationMeta()).thenReturn(oOperationMeta);
-    InvokerUtils.reactiveInvoke(oInvocation, Mockito.mock(AsyncResponse.class));
-    boolean validReactiveInvoke = true;
-    try {
-      InvokerUtils.reactiveInvoke(null, null);
-    } catch (Exception e) {
-      Assert.assertEquals(java.lang.NullPointerException.class, e.getClass());
-      validReactiveInvoke = false;
-    }
-    Assert.assertFalse(validReactiveInvoke);
-    boolean validInvokeIsNull = true;
-    try {
-      InvokerUtils.invoke(null);
-    } catch (Exception e) {
-      Assert.assertEquals(java.lang.NullPointerException.class, e.getClass());
-      validInvokeIsNull = false;
-    }
-    Assert.assertFalse(validInvokeIsNull);
-    boolean validInvoke = true;
-    try {
-      InvokerUtils.invoke(oInvocation);
-    } catch (Exception e) {
-      Assert.assertEquals(java.lang.NullPointerException.class, e.getClass());
-      validInvoke = false;
-    }
-    Assert.assertFalse(validInvoke);
-  }
-
   @Test
   public void testInvocation() {
     OperationMeta oOperationMeta = Mockito.mock(OperationMeta.class);
diff --git a/core/src/test/java/io/servicecomb/core/definition/TestOperationMeta.java b/core/src/test/java/io/servicecomb/core/definition/TestOperationMeta.java
index e4ee7c239..97f2a923a 100644
--- a/core/src/test/java/io/servicecomb/core/definition/TestOperationMeta.java
+++ b/core/src/test/java/io/servicecomb/core/definition/TestOperationMeta.java
@@ -56,7 +56,6 @@ public void testOperationMeta() {
     Assert.assertEquals("app:test", operationMeta.getMicroserviceName());
     Assert.assertEquals("test", operationMeta.getOperationId());
     Assert.assertEquals("x", operationMeta.getParamName(0));
-    Assert.assertEquals(true, operationMeta.isSync());
 
     operationMeta.putExtData("ext", 1);
     Assert.assertEquals(1, (int) operationMeta.getExtData("ext"));
diff --git a/core/src/test/java/io/servicecomb/core/provider/consumer/TestInvokerUtils.java b/core/src/test/java/io/servicecomb/core/provider/consumer/TestInvokerUtils.java
index 4e322c789..bba11bd10 100644
--- a/core/src/test/java/io/servicecomb/core/provider/consumer/TestInvokerUtils.java
+++ b/core/src/test/java/io/servicecomb/core/provider/consumer/TestInvokerUtils.java
@@ -73,35 +73,17 @@ public void testReactiveInvoke() {
     Assert.assertTrue(validAssert);
   }
 
+  @SuppressWarnings("deprecation")
   @Test
-  public void testInvokeWithException() {
-    new MockUp<SyncResponseExecutor>() {
+  public void invoke() {
+    new MockUp<InvokerUtils>() {
       @Mock
-      public Response waitResponse() throws InterruptedException {
-        return Mockito.mock(Response.class);
+      Object syncInvoke(Invocation invocation) {
+        return 1;
       }
     };
-    Invocation invocation = Mockito.mock(Invocation.class);
-    OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
-    Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
-    Mockito.when(operationMeta.isSync()).thenReturn(true);
-    try {
-      InvokerUtils.invoke(invocation);
-    } catch (InvocationException e) {
-      Assert.assertEquals(490, e.getStatusCode());
-    }
-  }
 
-  @Test
-  public void testInvoke() {
-    Object[] objectArray = new Object[2];
-    Invocation invocation = Mockito.mock(Invocation.class);
-    OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
-    Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta);
-    Mockito.when(operationMeta.isSync()).thenReturn(false);
-    Mockito.when(invocation.getArgs()).thenReturn(objectArray);
-    Object obj = InvokerUtils.invoke(invocation);
-    Assert.assertNull(obj);
+    Assert.assertEquals(1, InvokerUtils.invoke(null));
   }
 
   @Test
diff --git a/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClient.java b/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClient.java
index 1f89fe9e6..578c722b0 100644
--- a/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClient.java
+++ b/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClient.java
@@ -22,6 +22,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 
 import javax.inject.Inject;
 
@@ -35,7 +37,7 @@
 
 public class CodeFirstPojoClient {
   @RpcReference(microserviceName = "pojo", schemaId = "io.servicecomb.demo.CodeFirstPojoIntf")
-  public CodeFirstPojoIntf codeFirstAnnotation;
+  public CodeFirstPojoClientIntf codeFirstAnnotation;
 
   @RpcReference(microserviceName = "pojo")
   public CodeFirstPojoIntf codeFirstAnnotationEmptySchemaId;
@@ -68,6 +70,20 @@ protected void testAll(CodeFirstPojoIntf codeFirst, String transport) {
     //            testCodeFirstRawJsonString(template, cseUrlPrefix);
     testCodeFirstSayHello(codeFirst);
     testCodeFirstReduce(codeFirst);
+    testCodeFirstCompletableFuture(codeFirst);
+  }
+
+  private void testCodeFirstCompletableFuture(CodeFirstPojoIntf codeFirst) {
+    if (!CodeFirstPojoClientIntf.class.isInstance(codeFirst)) {
+      return;
+    }
+
+    CompletableFuture<String> future = ((CodeFirstPojoClientIntf) codeFirst).sayHiAsync("someone");
+    try {
+      TestMgr.check("someone sayhi", future.get());
+    } catch (InterruptedException | ExecutionException e) {
+      throw new IllegalStateException(e);
+    }
   }
 
   private void testCodeFirstUserMap(CodeFirstPojoIntf codeFirst) {
diff --git a/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java b/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java
new file mode 100644
index 000000000..6603deb8c
--- /dev/null
+++ b/demo/demo-pojo/pojo-client/src/main/java/io/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.servicecomb.demo.pojo.client;
+
+import java.util.concurrent.CompletableFuture;
+
+import io.servicecomb.demo.CodeFirstPojoIntf;
+import io.swagger.annotations.ApiOperation;
+
+public interface CodeFirstPojoClientIntf extends CodeFirstPojoIntf {
+  @ApiOperation(nickname = "sayHi", value = "")
+  CompletableFuture<String> sayHiAsync(String name);
+}
diff --git a/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java b/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java
index ba6ff401f..4a46ba642 100644
--- a/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java
+++ b/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java
@@ -20,6 +20,7 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.concurrent.CompletableFuture;
 
 import org.springframework.util.StringUtils;
 
@@ -49,7 +50,7 @@
 
   private ReferenceConfig referenceConfig;
 
-  private SwaggerConsumer swaggerConsumer;
+  private volatile SwaggerConsumer swaggerConsumer;
 
   @SuppressWarnings("unchecked")
   public static <T> T createProxy(String microserviceName, String schemaId, Class<?> consumerIntf) {
@@ -86,15 +87,28 @@ protected void prepare() {
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     if (swaggerConsumer == null) {
-      prepare();
+      synchronized (this) {
+        if (swaggerConsumer == null) {
+          prepare();
+        }
+      }
     }
 
+    SwaggerConsumerOperation consumerOperation = swaggerConsumer.findOperation(method.getName());
     Invocation invocation =
-        InvocationFactory.forConsumer(referenceConfig, schemaMeta, method.getName(), null);
+        InvocationFactory
+            .forConsumer(referenceConfig, schemaMeta, consumerOperation.getSwaggerMethod().getName(), null);
 
-    SwaggerConsumerOperation consumerOperation = swaggerConsumer.findOperation(method.getName());
     consumerOperation.getArgumentsMapper().toInvocation(args, invocation);
 
+    if (CompletableFuture.class.equals(method.getReturnType())) {
+      return completableFutureInvoke(invocation, consumerOperation);
+    }
+
+    return syncInvoke(invocation, consumerOperation);
+  }
+
+  protected Object syncInvoke(Invocation invocation, SwaggerConsumerOperation consumerOperation) {
     Response response = InvokerUtils.innerSyncInvoke(invocation);
     if (response.isSuccessed()) {
       return consumerOperation.getResponseMapper().mapResponse(response);
@@ -102,4 +116,19 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
 
     throw ExceptionFactory.convertConsumerException(response.getResult());
   }
+
+  protected CompletableFuture<Object> completableFutureInvoke(Invocation invocation,
+      SwaggerConsumerOperation consumerOperation) {
+    CompletableFuture<Object> future = new CompletableFuture<>();
+    InvokerUtils.reactiveInvoke(invocation, response -> {
+      if (response.isSuccessed()) {
+        Object result = consumerOperation.getResponseMapper().mapResponse(response);
+        future.complete(result);
+        return;
+      }
+
+      future.completeExceptionally(response.getResult());
+    });
+    return future;
+  }
 }
diff --git a/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java b/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java
index ae47e3afb..a9899bc1e 100644
--- a/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java
+++ b/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java
@@ -17,24 +17,42 @@
 
 package io.servicecomb.provider.pojo;
 
+import java.util.concurrent.CompletableFuture;
+
+import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import io.servicecomb.core.CseContext;
+import io.servicecomb.core.Invocation;
 import io.servicecomb.core.definition.MicroserviceMeta;
 import io.servicecomb.core.definition.schema.ConsumerSchemaFactory;
 import io.servicecomb.core.provider.consumer.ConsumerProviderManager;
+import io.servicecomb.core.provider.consumer.InvokerUtils;
 import io.servicecomb.core.provider.consumer.ReferenceConfig;
 import io.servicecomb.core.provider.consumer.ReferenceConfigUtils;
 import io.servicecomb.swagger.engine.SwaggerConsumer;
+import io.servicecomb.swagger.engine.SwaggerConsumerOperation;
 import io.servicecomb.swagger.engine.bootstrap.BootstrapNormal;
+import io.servicecomb.swagger.invocation.AsyncResponse;
+import io.servicecomb.swagger.invocation.Response;
+import io.servicecomb.swagger.invocation.exception.InvocationException;
+import io.servicecomb.swagger.invocation.response.consumer.ConsumerResponseMapper;
 import mockit.Deencapsulation;
 import mockit.Expectations;
 import mockit.Injectable;
+import mockit.Mock;
+import mockit.MockUp;
+import mockit.Mocked;
 
 public class TestInvoker {
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
   @Before
   public void setup() {
     ReferenceConfigUtils.setReady(true);
@@ -138,4 +156,98 @@ public void testConsumerInterfaceAsSchemaId(@Injectable ConsumerProviderManager
     SwaggerConsumer swaggerConsumer = Deencapsulation.getField(invoker, "swaggerConsumer");
     Assert.assertEquals(IPerson.class, swaggerConsumer.getConsumerIntf());
   }
+
+  @Test
+  public void syncInvoke_normal(@Mocked Invocation invocation,
+      @Mocked SwaggerConsumerOperation consumerOperation,
+      @Mocked ConsumerResponseMapper mapper) {
+    Response response = Response.ok("1");
+    new MockUp<InvokerUtils>() {
+      @Mock
+      Response innerSyncInvoke(Invocation invocation) {
+        return response;
+      }
+    };
+    new Expectations() {
+      {
+        consumerOperation.getResponseMapper();
+        result = mapper;
+        mapper.mapResponse(response);
+        result = 1;
+      }
+    };
+
+    Invoker invoker = new Invoker("test", null, IPerson.class);
+    Object result = invoker.syncInvoke(invocation, consumerOperation);
+    Assert.assertEquals(1, result);
+  }
+
+  @Test
+  public void syncInvoke_failed(@Mocked Invocation invocation,
+      @Mocked SwaggerConsumerOperation consumerOperation,
+      @Mocked ConsumerResponseMapper mapper) {
+    Throwable error = new Error("failed");
+    Response response = Response.createConsumerFail(error);
+    new MockUp<InvokerUtils>() {
+      @Mock
+      Response innerSyncInvoke(Invocation invocation) {
+        return response;
+      }
+    };
+
+    expectedException.expect(InvocationException.class);
+    expectedException.expectCause(Matchers.sameInstance(error));
+
+    Invoker invoker = new Invoker("test", null, IPerson.class);
+    invoker.syncInvoke(invocation, consumerOperation);
+  }
+
+  @Test
+  public void completableFutureInvoke_normal(@Mocked Invocation invocation,
+      @Mocked SwaggerConsumerOperation consumerOperation,
+      @Mocked ConsumerResponseMapper mapper) {
+    Response response = Response.ok("1");
+    new MockUp<InvokerUtils>() {
+      @Mock
+      void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp) {
+        asyncResp.handle(response);;
+      }
+    };
+    new Expectations() {
+      {
+        consumerOperation.getResponseMapper();
+        result = mapper;
+        mapper.mapResponse(response);
+        result = 1;
+      }
+    };
+
+    Invoker invoker = new Invoker("test", null, IPerson.class);
+    CompletableFuture<Object> future = invoker.completableFutureInvoke(invocation, consumerOperation);
+    future.whenComplete((result, ex) -> {
+      Assert.assertEquals(1, result);
+      Assert.assertEquals(null, ex);
+    });
+  }
+
+  @Test
+  public void completableFutureInvoke_failed(@Mocked Invocation invocation,
+      @Mocked SwaggerConsumerOperation consumerOperation,
+      @Mocked ConsumerResponseMapper mapper) {
+    Throwable error = new Error("failed");
+    Response response = Response.createConsumerFail(error);
+    new MockUp<InvokerUtils>() {
+      @Mock
+      void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp) {
+        asyncResp.handle(response);;
+      }
+    };
+
+    Invoker invoker = new Invoker("test", null, IPerson.class);
+    CompletableFuture<Object> future = invoker.completableFutureInvoke(invocation, consumerOperation);
+    future.whenComplete((result, ex) -> {
+      Assert.assertEquals(null, result);
+      Assert.assertSame(error, ex);
+    });
+  }
 }
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/SwaggerEnvironment.java b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/SwaggerEnvironment.java
index b80dc539f..4206363bb 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/SwaggerEnvironment.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/SwaggerEnvironment.java
@@ -22,6 +22,7 @@
 
 import javax.inject.Inject;
 
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 
 import io.servicecomb.foundation.common.utils.BeanUtils;
@@ -88,9 +89,9 @@ public SwaggerConsumer createConsumer(Class<?> consumerIntf, Class<?> swaggerInt
     consumer.setConsumerIntf(consumerIntf);
     consumer.setSwaggerIntf(swaggerIntf);
     for (Method consumerMethod : consumerIntf.getMethods()) {
-      String methodName = consumerMethod.getName();
+      String swaggerMethodName = findSwaggerMethodName(consumerMethod);
       // consumer???????swagger??
-      Method swaggerMethod = ReflectUtils.findMethod(swaggerIntf, methodName);
+      Method swaggerMethod = ReflectUtils.findMethod(swaggerIntf, swaggerMethodName);
       if (swaggerMethod == null) {
         // consumer???????
         String msg = String.format("consumer method %s:%s not exist in swagger.",
@@ -106,7 +107,7 @@ public SwaggerConsumer createConsumer(Class<?> consumerIntf, Class<?> swaggerInt
           consumerMethod.getGenericReturnType());
 
       SwaggerConsumerOperation op = new SwaggerConsumerOperation();
-      op.setName(methodName);
+      op.setName(consumerMethod.getName());
       op.setConsumerMethod(consumerMethod);
       op.setSwaggerMethod(swaggerMethod);
       op.setArgumentsMapper(argsMapper);
@@ -118,6 +119,15 @@ public SwaggerConsumer createConsumer(Class<?> consumerIntf, Class<?> swaggerInt
     return consumer;
   }
 
+  protected String findSwaggerMethodName(Method consumerMethod) {
+    ApiOperation apiOperationAnnotation = consumerMethod.getAnnotation(ApiOperation.class);
+    if (apiOperationAnnotation == null || StringUtils.isEmpty(apiOperationAnnotation.nickname())) {
+      return consumerMethod.getName();
+    }
+
+    return apiOperationAnnotation.nickname();
+  }
+
   public SwaggerProducer createProducer(Object producerInstance, Swagger swagger) {
     Class<?> producerCls = BeanUtils.getImplClassFromBean(producerInstance);
     Map<String, Method> visibleProducerMethods = retrieveVisibleMethods(producerCls);
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/unittest/LocalProducerInvoker.java b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/unittest/LocalProducerInvoker.java
index c9049023c..ff3bcc361 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/unittest/LocalProducerInvoker.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/engine/unittest/LocalProducerInvoker.java
@@ -19,6 +19,7 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.concurrent.CompletableFuture;
 
 import io.servicecomb.swagger.engine.SwaggerConsumer;
 import io.servicecomb.swagger.engine.SwaggerConsumerOperation;
@@ -73,10 +74,18 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
     invocation = new SwaggerInvocation();
 
     SwaggerConsumerOperation consumerOp = consumer.findOperation(method.getName());
-    SwaggerProducerOperation producerOp = producer.findOperation(method.getName());
+    SwaggerProducerOperation producerOp = producer.findOperation(consumerOp.getSwaggerMethod().getName());
 
     consumerOp.getArgumentsMapper().toInvocation(args, invocation);
     producerResponse = producerOp.doInvoke(invocation);
-    return consumerOp.getResponseMapper().mapResponse(producerResponse);
+    Object realResult = consumerOp.getResponseMapper().mapResponse(producerResponse);
+
+    if (CompletableFuture.class.equals(method.getReturnType())) {
+      CompletableFuture<Object> future = new CompletableFuture<>();
+      future.complete(realResult);
+      return future;
+    }
+
+    return realResult;
   }
 }
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/arguments/TestPojoConsumerEqualProducer.java b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/arguments/TestPojoConsumerEqualProducer.java
index 8c1773b41..1d0187f86 100644
--- a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/arguments/TestPojoConsumerEqualProducer.java
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/arguments/TestPojoConsumerEqualProducer.java
@@ -19,6 +19,7 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
 
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -81,6 +82,20 @@ public void testObject() throws Exception {
     Assert.assertEquals("hello abc", result.getName());
   }
 
+  @Test
+  public void testObjectAsync() throws Exception {
+    Person person = new Person();
+    person.setName("abc");
+
+    CompletableFuture<Person> future = proxy.testObjectAsync(person);
+    Person result = future.get();
+
+    Person swaggerPerson = invoker.getSwaggerArgument(0);
+    Assert.assertEquals(person, swaggerPerson);
+
+    Assert.assertEquals("hello abc", result.getName());
+  }
+
   @Test
   public void testSimpleAndObject() throws Exception {
     Person person = new Person();
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/models/PojoConsumerIntf.java b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/models/PojoConsumerIntf.java
index 5abc03d6a..c3839c1a1 100644
--- a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/models/PojoConsumerIntf.java
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/models/PojoConsumerIntf.java
@@ -18,14 +18,19 @@
 package io.servicecomb.swagger.invocation.models;
 
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
 
 import io.servicecomb.swagger.invocation.context.InvocationContext;
+import io.swagger.annotations.ApiOperation;
 
 public interface PojoConsumerIntf {
   int testSimple(int a, int b, int c);
 
   Person testObject(Person user);
 
+  @ApiOperation(nickname = "testObject", value = "")
+  CompletableFuture<Person> testObjectAsync(Person user);
+
   String testSimpleAndObject(String prefix, Person user);
 
   String testContext(InvocationContext context, String name);


 

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


With regards,
Apache Git Services