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 2017/12/27 02:10:55 UTC
[incubator-servicecomb-java-chassis] 01/05: JAV-583 pojo consumer
support return CompletableFuture
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 c94697ae22b703267cf8b893b780cf661a1456b8
Author: wujimin <wu...@huawei.com>
AuthorDate: Mon Dec 25 16:18:41 2017 +0800
JAV-583 pojo consumer support return CompletableFuture
---
.../java/io/servicecomb/provider/pojo/Invoker.java | 32 +++++-
.../io/servicecomb/provider/pojo/TestInvoker.java | 112 +++++++++++++++++++++
2 files changed, 142 insertions(+), 2 deletions(-)
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 ba6ff40..14527b8 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 @@ package io.servicecomb.provider.pojo;
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 @@ public class Invoker implements InvocationHandler {
private ReferenceConfig referenceConfig;
- private SwaggerConsumer swaggerConsumer;
+ private volatile SwaggerConsumer swaggerConsumer;
@SuppressWarnings("unchecked")
public static <T> T createProxy(String microserviceName, String schemaId, Class<?> consumerIntf) {
@@ -86,7 +87,11 @@ public class Invoker implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (swaggerConsumer == null) {
- prepare();
+ synchronized (this) {
+ if (swaggerConsumer == null) {
+ prepare();
+ }
+ }
}
Invocation invocation =
@@ -95,6 +100,14 @@ public class Invoker implements InvocationHandler {
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 +115,19 @@ public class Invoker implements InvocationHandler {
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 ae47e3a..a9899bc 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 class TestInvoker {
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);
+ });
+ }
}
--
To stop receiving notification emails like this one, please contact
"commits@servicecomb.apache.org" <co...@servicecomb.apache.org>.