diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
index a17c4abcbd2..3b98859728b 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
@@ -23,11 +23,11 @@
import org.apache.dubbo.common.timer.Timer;
import org.apache.dubbo.common.timer.TimerTask;
import org.apache.dubbo.common.utils.NamedThreadFactory;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.LoadBalance;
@@ -103,7 +103,7 @@ protected Result doInvoke(Invocation invocation, List> invokers, Load
logger.error("Failback to invoke method " + invocation.getMethodName() + ", wait for retry in background. Ignored exception: "
+ e.getMessage() + ", ", e);
addFailed(loadbalance, invocation, invokers, invoker);
- return new RpcResult(); // ignore
+ return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
}
}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java
index 0f5378a19a0..539686ed0e4 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailsafeClusterInvoker.java
@@ -18,18 +18,18 @@
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import java.util.List;
/**
- * When invoke fails, log the error message and ignore this error by returning an empty RpcResult.
+ * When invoke fails, log the error message and ignore this error by returning an empty Result.
* Usually used to write audit logs and other operations
*
* Fail-safe
@@ -50,7 +50,7 @@ public Result doInvoke(Invocation invocation, List> invokers, LoadBal
return invoker.invoke(invocation);
} catch (Throwable e) {
logger.error("Failsafe ignore exception: " + e.getMessage(), e);
- return new RpcResult(); // ignore
+ return AsyncRpcResult.newDefaultAsyncResult(null, null, invocation); // ignore
}
}
}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
index 70a6eaa75ff..2c352b2cee9 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
@@ -40,6 +40,8 @@
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
/**
+ * NOTICE! This implementation does not work well with async call.
+ *
* Invoke a specific number of invokers concurrently, usually used for demanding real-time operations, but need to waste more service resources.
*
* Fork
@@ -70,7 +72,6 @@ public Result doInvoke(final Invocation invocation, List> invokers, L
} else {
selected = new ArrayList<>();
for (int i = 0; i < forks; i++) {
- // TODO. Add some comment here, refer chinese version for more details.
Invoker invoker = select(loadbalance, invocation, invokers, selected);
if (!selected.contains(invoker)) {
//Avoid add the same invoker several times.
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java
index d23459e909d..d3243c4c086 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java
@@ -22,12 +22,12 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.NamedThreadFactory;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.cluster.Merger;
@@ -40,17 +40,16 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
+import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
import static org.apache.dubbo.rpc.Constants.MERGER_KEY;
+/**
+ * @param
+ */
@SuppressWarnings("unchecked")
public class MergeableClusterInvoker extends AbstractClusterInvoker {
@@ -90,26 +89,21 @@ protected Result doInvoke(Invocation invocation, List> invokers, Load
returnType = null;
}
- Map> results = new HashMap>();
+ Map results = new HashMap<>();
for (final Invoker invoker : invokers) {
- Future future = executor.submit(new Callable() {
- @Override
- public Result call() throws Exception {
- return invoker.invoke(new RpcInvocation(invocation, invoker));
- }
- });
- results.put(invoker.getUrl().getServiceKey(), future);
+ RpcInvocation subInvocation = new RpcInvocation(invocation, invoker);
+ subInvocation.setAttachment(ASYNC_KEY, "true");
+ results.put(invoker.getUrl().getServiceKey(), invoker.invoke(subInvocation));
}
Object result = null;
List resultList = new ArrayList(results.size());
- int timeout = getUrl().getMethodParameter(invocation.getMethodName(), TIMEOUT_KEY, DEFAULT_TIMEOUT);
- for (Map.Entry> entry : results.entrySet()) {
- Future future = entry.getValue();
+ for (Map.Entry entry : results.entrySet()) {
+ Result asyncResult = entry.getValue();
try {
- Result r = future.get(timeout, TimeUnit.MILLISECONDS);
+ Result r = asyncResult.get();
if (r.hasException()) {
log.error("Invoke " + getGroupDescFromServiceKey(entry.getKey()) +
" failed: " + r.getException().getMessage(),
@@ -123,13 +117,13 @@ public Result call() throws Exception {
}
if (resultList.isEmpty()) {
- return new RpcResult((Object) null);
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else if (resultList.size() == 1) {
return resultList.iterator().next();
}
if (returnType == void.class) {
- return new RpcResult((Object) null);
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
}
if (merger.startsWith(".")) {
@@ -177,7 +171,7 @@ public Result call() throws Exception {
throw new RpcException("There is no merger to merge result.");
}
}
- return new RpcResult(result);
+ return AsyncRpcResult.newDefaultAsyncResult(result, invocation);
}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
index c85eed476bb..77eceb0e75c 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
@@ -21,12 +21,12 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.support.MockInvoker;
@@ -115,7 +115,7 @@ private Result doMockInvoke(Invocation invocation, RpcException e) {
result = minvoker.invoke(invocation);
} catch (RpcException me) {
if (me.isBiz()) {
- result = new RpcResult(me.getCause());
+ result = AsyncRpcResult.newDefaultAsyncResult(me.getCause(), invocation);
} else {
throw new RpcException(me.getCode(), getMockExceptionMessage(e, me), me.getCause());
}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
index 878e3742df6..cb2656f33b9 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
@@ -19,12 +19,12 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
import org.junit.jupiter.api.Assertions;
@@ -48,7 +48,7 @@ public class StickyTest {
private Invoker invoker2 = mock(Invoker.class);
private RpcInvocation invocation;
private Directory dic;
- private Result result = new RpcResult();
+ private Result result = new AppResponse();
private StickyClusterInvoker clusterinvoker = null;
private URL url = URL.valueOf("test://test:11/test?"
+ "&loadbalance=roundrobin"
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
index ec3541eed1f..5245a2cb69d 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
@@ -57,6 +57,16 @@ public Map getAttachments() {
return attachments;
}
+ @Override
+ public void setAttachment(String key, String value) {
+
+ }
+
+ @Override
+ public void setAttachmentIfAbsent(String key, String value) {
+
+ }
+
public Invoker> getInvoker() {
return null;
}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
index 635014863b1..6a03001ddf3 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
@@ -18,12 +18,12 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.cluster.RouterFactory;
@@ -52,7 +52,7 @@ public class FileRouterEngineTest {
Invoker invoker2 = mock(Invoker.class);
Invocation invocation;
StaticDirectory dic;
- Result result = new RpcResult();
+ Result result = new AppResponse();
private RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getAdaptiveExtension();
@BeforeAll
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java
index 413d9b9dc8a..8ab596bec1e 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailSafeClusterInvokerTest.java
@@ -18,11 +18,11 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.LogUtil;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.filter.DemoService;
@@ -48,7 +48,7 @@ public class FailSafeClusterInvokerTest {
Invoker invoker = mock(Invoker.class);
RpcInvocation invocation = new RpcInvocation();
Directory dic;
- Result result = new RpcResult();
+ Result result = new AppResponse();
/**
* @throws java.lang.Exception
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java
index ad96a66830d..b745b0e1b26 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailbackClusterInvokerTest.java
@@ -20,11 +20,11 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.DubboAppender;
import org.apache.dubbo.common.utils.LogUtil;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.log4j.Level;
@@ -59,7 +59,7 @@ public class FailbackClusterInvokerTest {
Invoker invoker = mock(Invoker.class);
RpcInvocation invocation = new RpcInvocation();
Directory dic;
- Result result = new RpcResult();
+ Result result = new AppResponse();
/**
* @throws java.lang.Exception
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java
index 9b6d2e88b73..6a706868bb9 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailfastClusterInvokerTest.java
@@ -17,12 +17,12 @@
package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.junit.jupiter.api.Assertions;
@@ -47,7 +47,7 @@ public class FailfastClusterInvokerTest {
Invoker invoker1 = mock(Invoker.class);
RpcInvocation invocation = new RpcInvocation();
Directory dic;
- Result result = new RpcResult();
+ Result result = new AppResponse();
/**
* @throws java.lang.Exception
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
index ff29a6183a9..6a2e76e0474 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
@@ -17,12 +17,12 @@
package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
@@ -55,7 +55,7 @@ public class FailoverClusterInvokerTest {
private Invoker invoker2 = mock(Invoker.class);
private RpcInvocation invocation = new RpcInvocation();
private Directory dic;
- private Result result = new RpcResult();
+ private Result result = new AppResponse();
/**
* @throws java.lang.Exception
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java
index b3d343a3bbe..aa27fabe458 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvokerTest.java
@@ -17,12 +17,12 @@
package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
-import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.cluster.Directory;
import org.junit.jupiter.api.Assertions;
@@ -50,7 +50,7 @@ public class ForkingClusterInvokerTest {
private Invoker invoker3 = mock(Invoker.class);
private RpcInvocation invocation = new RpcInvocation();
private Directory dic;
- private Result result = new RpcResult();
+ private Result result = new AppResponse();
@BeforeEach
public void setUp() throws Exception {
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvokerTest.java
index 07bae73e2f5..3223b27ca8f 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvokerTest.java
@@ -17,10 +17,11 @@
package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.cluster.Directory;
import org.junit.jupiter.api.Assertions;
@@ -120,7 +121,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
return MenuService.class;
}
if ("invoke".equals(method.getName())) {
- return new RpcResult(firstMenu);
+ return AsyncRpcResult.newDefaultAsyncResult(firstMenu, invocation);
}
return null;
}
@@ -136,7 +137,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
return MenuService.class;
}
if ("invoke".equals(method.getName())) {
- return new RpcResult(secondMenu);
+ return AsyncRpcResult.newDefaultAsyncResult(secondMenu, invocation);
}
return null;
}
@@ -196,14 +197,14 @@ public void testAddMenu() throws Exception {
given(firstInvoker.getUrl()).willReturn(
url.addParameter(GROUP_KEY, "first"));
given(firstInvoker.getInterface()).willReturn(MenuService.class);
- given(firstInvoker.invoke(invocation)).willReturn(new RpcResult())
+ given(firstInvoker.invoke(invocation)).willReturn(new AppResponse())
;
given(firstInvoker.isAvailable()).willReturn(true);
given(secondInvoker.getUrl()).willReturn(
url.addParameter(GROUP_KEY, "second"));
given(secondInvoker.getInterface()).willReturn(MenuService.class);
- given(secondInvoker.invoke(invocation)).willReturn(new RpcResult())
+ given(secondInvoker.invoke(invocation)).willReturn(new AppResponse())
;
given(secondInvoker.isAvailable()).willReturn(true);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RpcConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RpcConstants.java
index 75c70852666..b40a9c1d58c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RpcConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RpcConstants.java
@@ -42,6 +42,62 @@ public interface RpcConstants {
String $INVOKE = "$invoke";
+ String $INVOKE_ASYNC = "$invokeAsync";
+
+ String $ECHO = "$echo";
+
+ String RETURN_PREFIX = "return ";
+
+ String THROW_PREFIX = "throw";
+
+ String FAIL_PREFIX = "fail:";
+
+ String FORCE_PREFIX = "force:";
+
+ String MERGER_KEY = "merger";
+
+ String IS_SERVER_KEY = "isserver";
+
+ String FORCE_USE_TAG = "dubbo.force.tag";
+
+ String GENERIC_SERIALIZATION_NATIVE_JAVA = "nativejava";
+
+ String GENERIC_SERIALIZATION_DEFAULT = "true";
+
+ String GENERIC_SERIALIZATION_BEAN = "bean";
+
+ String GENERIC_SERIALIZATION_PROTOBUF = "protobuf-json";
+
+ String TPS_LIMIT_RATE_KEY = "tps";
+
+ String TPS_LIMIT_INTERVAL_KEY = "tps.interval";
+
+ long DEFAULT_TPS_LIMIT_INTERVAL = 60 * 1000;
+
+ String AUTO_ATTACH_INVOCATIONID_KEY = "invocationid.autoattach";
+
+ String STUB_EVENT_KEY = "dubbo.stub.event";
+
+ boolean DEFAULT_STUB_EVENT = false;
+
+ String STUB_EVENT_METHODS_KEY = "dubbo.stub.event.methods";
+
+ String PROXY_KEY = "proxy";
+
+ String EXECUTES_KEY = "executes";
+
+ String REFERENCE_FILTER_KEY = "reference.filter";
+
+ String INVOKER_LISTENER_KEY = "invoker.listener";
+
+ String SERVICE_FILTER_KEY = "service.filter";
+
+ String EXPORTER_LISTENER_KEY = "exporter.listener";
+
+ String ACCESS_LOG_KEY = "accesslog";
+
+ String ACTIVES_KEY = "actives";
+
String CONNECTIONS_KEY = "connections";
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java
index c505326d0c3..874ab564a2e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/Logger.java
@@ -142,7 +142,7 @@ public interface Logger {
/**
* Is debug logging currently enabled?
- *
+ *
* @return true if debug is enabled
*/
boolean isDebugEnabled();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
index ccec6875ca8..0c1a13dfe25 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
@@ -28,6 +28,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
@@ -39,6 +40,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -1096,4 +1098,25 @@ public static Map getBeanPropertyReadMethods(Class cl) {
return properties;
}
+
+ public static Type[] getReturnTypes(Method method) {
+ Class> returnType = method.getReturnType();
+ Type genericReturnType = method.getGenericReturnType();
+ if (Future.class.isAssignableFrom(returnType)) {
+ if (genericReturnType instanceof ParameterizedType) {
+ Type actualArgType = ((ParameterizedType) genericReturnType).getActualTypeArguments()[0];
+ if (actualArgType instanceof ParameterizedType) {
+ returnType = (Class>) ((ParameterizedType) actualArgType).getRawType();
+ genericReturnType = actualArgType;
+ } else {
+ returnType = (Class>) actualArgType;
+ genericReturnType = returnType;
+ }
+ } else {
+ returnType = null;
+ genericReturnType = null;
+ }
+ }
+ return new Type[]{returnType, genericReturnType};
+ }
}
\ No newline at end of file
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java
index f46235daaa1..298f15c2f02 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java
@@ -22,12 +22,14 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@@ -401,6 +403,32 @@ public void testForName2() {
});
}
+ @Test
+ public void testGetReturnTypes () throws Exception{
+ Class clazz = TypeClass.class;
+
+ Type[] types = ReflectUtils.getReturnTypes(clazz.getMethod("getFuture"));
+ Assertions.assertEquals("java.lang.String", types[0].getTypeName());
+ Assertions.assertEquals("java.lang.String", types[1].getTypeName());
+
+ Type[] types1 = ReflectUtils.getReturnTypes(clazz.getMethod("getString"));
+ Assertions.assertEquals("java.lang.String", types1[0].getTypeName());
+ Assertions.assertEquals("java.lang.String", types1[1].getTypeName());
+
+ Type[] types2 = ReflectUtils.getReturnTypes(clazz.getMethod("getListFuture"));
+ Assertions.assertEquals("java.util.List", types2[0].getTypeName());
+ Assertions.assertEquals("java.util.List", types2[1].getTypeName());
+ }
+
+ public static interface TypeClass {
+
+ CompletableFuture getFuture();
+
+ String getString();
+
+ CompletableFuture> getListFuture();
+ }
+
public static class EmptyClass {
private EmptyProperty property;
public boolean set;
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
index 9d960c219df..d283c63b26a 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
@@ -29,6 +29,15 @@ default org.apache.dubbo.rpc.Invocation getOriginal() {
return null;
}
+ @Override
+ default void setAttachmentIfAbsent(String key, String value) {
+ }
+
+ @Override
+ default void setAttachment(String key, String value) {
+
+ }
+
class CompatibleInvocation implements Invocation, org.apache.dubbo.rpc.Invocation {
private org.apache.dubbo.rpc.Invocation delegate;
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Result.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Result.java
index a661b2b6b5b..07f5df9bf5a 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Result.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Result.java
@@ -18,11 +18,30 @@
package com.alibaba.dubbo.rpc;
import java.util.Map;
+import java.util.function.Function;
@Deprecated
public interface Result extends org.apache.dubbo.rpc.Result {
- class CompatibleResult implements Result {
+ @Override
+ default void setValue(Object value) {
+
+ }
+
+ @Override
+ default void setException(Throwable t) {
+
+ }
+
+ abstract class AbstractResult extends org.apache.dubbo.rpc.AbstractResult implements Result {
+
+ @Override
+ public org.apache.dubbo.rpc.Result thenApplyWithContext(Function fn) {
+ return null;
+ }
+ }
+
+ class CompatibleResult extends AbstractResult {
private org.apache.dubbo.rpc.Result delegate;
public CompatibleResult(org.apache.dubbo.rpc.Result result) {
@@ -38,11 +57,21 @@ public Object getValue() {
return delegate.getValue();
}
+ @Override
+ public void setValue(Object value) {
+ delegate.setValue(value);
+ }
+
@Override
public Throwable getException() {
return delegate.getException();
}
+ @Override
+ public void setException(Throwable t) {
+ delegate.setException(t);
+ }
+
@Override
public boolean hasException() {
return delegate.hasException();
@@ -53,11 +82,6 @@ public Object recreate() throws Throwable {
return delegate.recreate();
}
- @Override
- public Object getResult() {
- return delegate.getResult();
- }
-
@Override
public Map getAttachments() {
return delegate.getAttachments();
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
index bf6160c06ac..28ae5f1757a 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
@@ -29,7 +29,7 @@ private static RpcContext newInstance(org.apache.dubbo.rpc.RpcContext rpcContext
RpcContext copy = new RpcContext();
copy.getAttachments().putAll(rpcContext.getAttachments());
copy.get().putAll(rpcContext.get());
- copy.setFuture(rpcContext.getFuture());
+ copy.setFuture(rpcContext.getCompletableFuture());
copy.setUrls(rpcContext.getUrls());
copy.setUrl(rpcContext.getUrl());
copy.setMethodName(rpcContext.getMethodName());
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/support/RpcUtils.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/support/RpcUtils.java
index 7f1ab98de5c..d7db04fe106 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/support/RpcUtils.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/support/RpcUtils.java
@@ -20,7 +20,6 @@
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
-import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
@@ -74,10 +73,6 @@ public static boolean isReturnTypeFuture(Invocation inv) {
return org.apache.dubbo.rpc.support.RpcUtils.isReturnTypeFuture(inv);
}
- public static boolean hasFutureReturnType(Method method) {
- return org.apache.dubbo.rpc.support.RpcUtils.hasFutureReturnType(method);
- }
-
public static boolean isOneway(URL url, Invocation inv) {
return org.apache.dubbo.rpc.support.RpcUtils.isOneway(url.getOriginalURL(), inv);
}
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java b/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java
index ee1288affff..f77e0a523d0 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/filter/LegacyInvoker.java
@@ -17,7 +17,7 @@
package org.apache.dubbo.filter;
-import org.apache.dubbo.rpc.RpcResult;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.service.DemoService;
import com.alibaba.dubbo.common.URL;
@@ -58,7 +58,7 @@ public boolean isAvailable() {
}
public Result invoke(Invocation invocation) throws RpcException {
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
if (hasException == false) {
result.setValue("alibaba");
} else {
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java
index 761ce4b99e7..c088917e51d 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java
@@ -63,6 +63,16 @@ public Map getAttachments() {
return attachments;
}
+ @Override
+ public void setAttachment(String key, String value) {
+
+ }
+
+ @Override
+ public void setAttachmentIfAbsent(String key, String value) {
+
+ }
+
public Invoker> getInvoker() {
return null;
}
diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java
index 24fa51cd531..772a16b5789 100644
--- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java
+++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java
@@ -21,12 +21,12 @@
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import java.io.Serializable;
@@ -48,10 +48,10 @@
* 3)<dubbo:provider cache="expiring" />
* 4)<dubbo:consumer cache="jcache" />
*
- * If cache type is defined in method level then method level type will get precedence. According to above provided
- * example, if service has two method, method1 and method2, method2 will have cache type as threadlocal where others will
- * be backed by lru
- *
+ *If cache type is defined in method level then method level type will get precedence. According to above provided
+ *example, if service has two method, method1 and method2, method2 will have cache type as threadlocal where others will
+ *be backed by lru
+ *
*
* @see org.apache.dubbo.rpc.Filter
* @see org.apache.dubbo.cache.support.lru.LruCacheFactory
@@ -62,6 +62,7 @@
* @see org.apache.dubbo.cache.support.threadlocal.ThreadLocalCache
* @see org.apache.dubbo.cache.support.expiring.ExpiringCacheFactory
* @see org.apache.dubbo.cache.support.expiring.ExpiringCache
+ *
*/
@Activate(group = {CONSUMER, PROVIDER}, value = CACHE_KEY)
public class CacheFilter implements Filter {
@@ -83,7 +84,6 @@ public void setCacheFactory(CacheFactory cacheFactory) {
* If cache is configured, dubbo will invoke method on each method call. If cache value is returned by cache store
* then it will return otherwise call the remote method and return value. If remote method's return valeu has error
* then it will not cache the value.
- *
* @param invoker service
* @param invocation invocation.
* @return Cache returned value if found by the underlying cache store. If cache miss it will call target method.
@@ -98,9 +98,9 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
Object value = cache.get(key);
if (value != null) {
if (value instanceof ValueWrapper) {
- return new RpcResult(((ValueWrapper) value).get());
+ return AsyncRpcResult.newDefaultAsyncResult(((ValueWrapper) value).get(), invocation);
} else {
- return new RpcResult(value);
+ return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
}
}
Result result = invoker.invoke(invocation);
@@ -122,7 +122,7 @@ static class ValueWrapper implements Serializable {
private final Object value;
- public ValueWrapper(Object value) {
+ public ValueWrapper (Object value) {
this.value = value;
}
diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/filter/CacheFilterTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/filter/CacheFilterTest.java
index c64647309f0..217919f1d6f 100644
--- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/filter/CacheFilterTest.java
+++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/filter/CacheFilterTest.java
@@ -22,9 +22,10 @@
import org.apache.dubbo.cache.support.lru.LruCacheFactory;
import org.apache.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
@@ -60,19 +61,19 @@ public void setUp(String cacheType, CacheFactory cacheFactory) {
URL url = URL.valueOf("test://test:11/test?cache=" + cacheType);
- given(invoker.invoke(invocation)).willReturn(new RpcResult("value"));
+ given(invoker.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult("value", invocation));
given(invoker.getUrl()).willReturn(url);
- given(invoker1.invoke(invocation)).willReturn(new RpcResult("value1"));
+ given(invoker1.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult("value1", invocation));
given(invoker1.getUrl()).willReturn(url);
- given(invoker2.invoke(invocation)).willReturn(new RpcResult("value2"));
+ given(invoker2.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult("value2", invocation));
given(invoker2.getUrl()).willReturn(url);
- given(invoker3.invoke(invocation)).willReturn(new RpcResult(new RuntimeException()));
+ given(invoker3.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult(new RuntimeException(), invocation));
given(invoker3.getUrl()).willReturn(url);
- given(invoker4.invoke(invocation)).willReturn(new RpcResult());
+ given(invoker4.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult(invocation));
given(invoker4.getUrl()).willReturn(url);
}
@@ -85,8 +86,8 @@ public void testNonArgsMethod(String cacheType, CacheFactory cacheFactory) {
invocation.setArguments(new Object[]{});
cacheFilter.invoke(invoker, invocation);
- RpcResult rpcResult1 = (RpcResult) cacheFilter.invoke(invoker1, invocation);
- RpcResult rpcResult2 = (RpcResult) cacheFilter.invoke(invoker2, invocation);
+ Result rpcResult1 = cacheFilter.invoke(invoker1, invocation);
+ Result rpcResult2 = cacheFilter.invoke(invoker2, invocation);
Assertions.assertEquals(rpcResult1.getValue(), rpcResult2.getValue());
Assertions.assertEquals(rpcResult1.getValue(), "value");
}
@@ -100,8 +101,8 @@ public void testMethodWithArgs(String cacheType, CacheFactory cacheFactory) {
invocation.setArguments(new Object[]{"arg1"});
cacheFilter.invoke(invoker, invocation);
- RpcResult rpcResult1 = (RpcResult) cacheFilter.invoke(invoker1, invocation);
- RpcResult rpcResult2 = (RpcResult) cacheFilter.invoke(invoker2, invocation);
+ Result rpcResult1 = cacheFilter.invoke(invoker1, invocation);
+ Result rpcResult2 = cacheFilter.invoke(invoker2, invocation);
Assertions.assertEquals(rpcResult1.getValue(), rpcResult2.getValue());
Assertions.assertEquals(rpcResult1.getValue(), "value");
}
@@ -115,7 +116,7 @@ public void testException(String cacheType, CacheFactory cacheFactory) {
invocation.setArguments(new Object[]{"arg2"});
cacheFilter.invoke(invoker3, invocation);
- RpcResult rpcResult = (RpcResult) cacheFilter.invoke(invoker2, invocation);
+ Result rpcResult = cacheFilter.invoke(invoker2, invocation);
Assertions.assertEquals(rpcResult.getValue(), "value2");
}
@@ -128,9 +129,9 @@ public void testNull(String cacheType, CacheFactory cacheFactory) {
invocation.setArguments(new Object[]{"arg3"});
cacheFilter.invoke(invoker4, invocation);
- RpcResult rpcResult1 = (RpcResult) cacheFilter.invoke(invoker1, invocation);
- RpcResult rpcResult2 = (RpcResult) cacheFilter.invoke(invoker2, invocation);
- Assertions.assertEquals(rpcResult1.getValue(), null);
- Assertions.assertEquals(rpcResult2.getValue(), null);
+ Result result1 = cacheFilter.invoke(invoker1, invocation);
+ Result result2 = cacheFilter.invoke(invoker2, invocation);
+ Assertions.assertEquals(result1.getValue(), null);
+ Assertions.assertEquals(result2.getValue(), null);
}
}
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java
index 5d2551dd149..d2f0539d83a 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java
@@ -18,12 +18,12 @@
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.validation.Validation;
import org.apache.dubbo.validation.Validator;
@@ -90,7 +90,7 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
} catch (RpcException e) {
throw e;
} catch (Throwable t) {
- return new RpcResult(t);
+ return AsyncRpcResult.newDefaultAsyncResult(t, invocation);
}
}
return invoker.invoke(invocation);
diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java
index cade5936402..b757536e9da 100644
--- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java
+++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/filter/ValidationFilterTest.java
@@ -17,11 +17,11 @@
package org.apache.dubbo.validation.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.validation.Validation;
import org.apache.dubbo.validation.Validator;
@@ -52,7 +52,7 @@ public void testItWithNotExistClass() throws Exception {
URL url = URL.valueOf("test://test:11/test?default.validation=true");
given(validation.getValidator(url)).willThrow(new IllegalStateException("Not found class test, cause: test"));
- given(invoker.invoke(invocation)).willReturn(new RpcResult("success"));
+ given(invoker.invoke(invocation)).willReturn(new AppResponse("success"));
given(invoker.getUrl()).willReturn(url);
given(invocation.getMethodName()).willReturn("echo1");
given(invocation.getParameterTypes()).willReturn(new Class>[]{String.class});
@@ -70,7 +70,7 @@ public void testItWithExistClass() throws Exception {
URL url = URL.valueOf("test://test:11/test?default.validation=true");
given(validation.getValidator(url)).willReturn(validator);
- given(invoker.invoke(invocation)).willReturn(new RpcResult("success"));
+ given(invoker.invoke(invocation)).willReturn(new AppResponse("success"));
given(invoker.getUrl()).willReturn(url);
given(invocation.getMethodName()).willReturn("echo1");
given(invocation.getParameterTypes()).willReturn(new Class>[]{String.class});
@@ -87,7 +87,7 @@ public void testItWithoutUrlParameters() throws Exception {
URL url = URL.valueOf("test://test:11/test");
given(validation.getValidator(url)).willReturn(validator);
- given(invoker.invoke(invocation)).willReturn(new RpcResult("success"));
+ given(invoker.invoke(invocation)).willReturn(new AppResponse("success"));
given(invoker.getUrl()).willReturn(url);
given(invocation.getMethodName()).willReturn("echo1");
given(invocation.getParameterTypes()).willReturn(new Class>[]{String.class});
@@ -104,7 +104,7 @@ public void testItWhileMethodNameStartWithDollar() throws Exception {
URL url = URL.valueOf("test://test:11/test");
given(validation.getValidator(url)).willReturn(validator);
- given(invoker.invoke(invocation)).willReturn(new RpcResult("success"));
+ given(invoker.invoke(invocation)).willReturn(new AppResponse("success"));
given(invoker.getUrl()).willReturn(url);
given(invocation.getMethodName()).willReturn("$echo1");
given(invocation.getParameterTypes()).willReturn(new Class>[]{String.class});
@@ -124,7 +124,7 @@ public void testItWhileThrowoutRpcException() throws Exception {
URL url = URL.valueOf("test://test:11/test?default.validation=true");
given(validation.getValidator(url)).willThrow(new RpcException("rpc exception"));
- given(invoker.invoke(invocation)).willReturn(new RpcResult("success"));
+ given(invoker.invoke(invocation)).willReturn(new AppResponse("success"));
given(invoker.getUrl()).willReturn(url);
given(invocation.getMethodName()).willReturn("echo1");
given(invocation.getParameterTypes()).willReturn(new Class>[]{String.class});
diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MonitorService.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MonitorService.java
index 2221089426c..7e606a53b94 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MonitorService.java
+++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MonitorService.java
@@ -88,4 +88,5 @@ public interface MonitorService {
*/
List lookup(URL query);
+
}
\ No newline at end of file
diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java
index ef498063dbd..8c1f19a2892 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java
+++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MonitorFilter.java
@@ -24,9 +24,9 @@
import org.apache.dubbo.monitor.Monitor;
import org.apache.dubbo.monitor.MonitorFactory;
import org.apache.dubbo.monitor.MonitorService;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
@@ -52,10 +52,14 @@
* MonitorFilter. (SPI, Singleton, ThreadSafe)
*/
@Activate(group = {PROVIDER, CONSUMER})
-public class MonitorFilter implements Filter {
+public class MonitorFilter extends ListenableFilter {
private static final Logger logger = LoggerFactory.getLogger(MonitorFilter.class);
+ private static final String MONITOR_FILTER_START_TIME = "monitor_filter_start_time";
+ public MonitorFilter() {
+ super.listener = new MonitorListener();
+ }
/**
* The Concurrent counter
*/
@@ -70,6 +74,7 @@ public void setMonitorFactory(MonitorFactory monitorFactory) {
this.monitorFactory = monitorFactory;
}
+
/**
* The invocation interceptor,it will collect the invoke data about this invocation and send it to monitor center
*
@@ -81,105 +86,10 @@ public void setMonitorFactory(MonitorFactory monitorFactory) {
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
if (invoker.getUrl().hasParameter(MONITOR_KEY)) {
- RpcContext context = RpcContext.getContext(); // provider must fetch context before invoke() gets called
- String remoteHost = context.getRemoteHost();
- long start = System.currentTimeMillis(); // record start timestamp
+ invocation.setAttachment(MONITOR_FILTER_START_TIME, String.valueOf(System.currentTimeMillis()));
getConcurrent(invoker, invocation).incrementAndGet(); // count up
- try {
- Result result = invoker.invoke(invocation); // proceed invocation chain
- collect(invoker, invocation, result, remoteHost, start, false);
- return result;
- } catch (RpcException e) {
- collect(invoker, invocation, null, remoteHost, start, true);
- throw e;
- } finally {
- getConcurrent(invoker, invocation).decrementAndGet(); // count down
- }
- } else {
- return invoker.invoke(invocation);
- }
- }
-
- /**
- * The collector logic, it will be handled by the default monitor
- *
- * @param invoker
- * @param invocation
- * @param result the invoke result
- * @param remoteHost the remote host address
- * @param start the timestamp the invoke begin
- * @param error if there is an error on the invoke
- */
- private void collect(Invoker> invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) {
- try {
- URL monitorUrl = invoker.getUrl().getUrlParameter(MONITOR_KEY);
- Monitor monitor = monitorFactory.getMonitor(monitorUrl);
- if (monitor == null) {
- return;
- }
- URL statisticsURL = createStatisticsUrl(invoker, invocation, result, remoteHost, start, error);
- monitor.collect(statisticsURL);
- } catch (Throwable t) {
- logger.warn("Failed to monitor count service " + invoker.getUrl() + ", cause: " + t.getMessage(), t);
}
- }
-
- /**
- * Create statistics url
- *
- * @param invoker
- * @param invocation
- * @param result
- * @param remoteHost
- * @param start
- * @param error
- * @return
- */
- private URL createStatisticsUrl(Invoker> invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) {
- // ---- service statistics ----
- long elapsed = System.currentTimeMillis() - start; // invocation cost
- int concurrent = getConcurrent(invoker, invocation).get(); // current concurrent count
- String application = invoker.getUrl().getParameter(APPLICATION_KEY);
- String service = invoker.getInterface().getName(); // service name
- String method = RpcUtils.getMethodName(invocation); // method name
- String group = invoker.getUrl().getParameter(GROUP_KEY);
- String version = invoker.getUrl().getParameter(VERSION_KEY);
-
- int localPort;
- String remoteKey, remoteValue;
- if (CONSUMER_SIDE.equals(invoker.getUrl().getParameter(SIDE_KEY))) {
- // ---- for service consumer ----
- localPort = 0;
- remoteKey = MonitorService.PROVIDER;
- remoteValue = invoker.getUrl().getAddress();
- } else {
- // ---- for service provider ----
- localPort = invoker.getUrl().getPort();
- remoteKey = MonitorService.CONSUMER;
- remoteValue = remoteHost;
- }
- String input = "", output = "";
- if (invocation.getAttachment(INPUT_KEY) != null) {
- input = invocation.getAttachment(INPUT_KEY);
- }
- if (result != null && result.getAttachment(OUTPUT_KEY) != null) {
- output = result.getAttachment(OUTPUT_KEY);
- }
-
- return new URL(COUNT_PROTOCOL,
- NetUtils.getLocalHost(), localPort,
- service + PATH_SEPARATOR + method,
- MonitorService.APPLICATION, application,
- MonitorService.INTERFACE, service,
- MonitorService.METHOD, method,
- remoteKey, remoteValue,
- error ? MonitorService.FAILURE : MonitorService.SUCCESS, "1",
- MonitorService.ELAPSED, String.valueOf(elapsed),
- MonitorService.CONCURRENT, String.valueOf(concurrent),
- INPUT_KEY, input,
- OUTPUT_KEY, output,
- GROUP_KEY, group,
- VERSION_KEY, version);
+ return invoker.invoke(invocation); // proceed invocation chain
}
// concurrent counter
@@ -193,4 +103,93 @@ private AtomicInteger getConcurrent(Invoker> invoker, Invocation invocation) {
return concurrent;
}
+ class MonitorListener implements Listener {
+
+ @Override
+ public void onResponse(Result result, Invoker> invoker, Invocation invocation) {
+ if (invoker.getUrl().hasParameter(MONITOR_KEY)) {
+ collect(invoker, invocation, result, RpcContext.getContext().getRemoteHost(), Long.valueOf(invocation.getAttachment(MONITOR_FILTER_START_TIME)), false);
+ getConcurrent(invoker, invocation).decrementAndGet(); // count down
+ }
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+ if (invoker.getUrl().hasParameter(MONITOR_KEY)) {
+ collect(invoker, invocation, null, RpcContext.getContext().getRemoteHost(), Long.valueOf(invocation.getAttachment(MONITOR_FILTER_START_TIME)), true);
+ getConcurrent(invoker, invocation).decrementAndGet(); // count down
+ }
+ }
+
+ /**
+ * The collector logic, it will be handled by the default monitor
+ *
+ * @param invoker
+ * @param invocation
+ * @param result the invoke result
+ * @param remoteHost the remote host address
+ * @param start the timestamp the invoke begin
+ * @param error if there is an error on the invoke
+ */
+ private void collect(Invoker> invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) {
+ try {
+ URL monitorUrl = invoker.getUrl().getUrlParameter(MONITOR_KEY);
+ Monitor monitor = monitorFactory.getMonitor(monitorUrl);
+ if (monitor == null) {
+ return;
+ }
+ URL statisticsURL = createStatisticsUrl(invoker, invocation, result, remoteHost, start, error);
+ monitor.collect(statisticsURL);
+ } catch (Throwable t) {
+ logger.warn("Failed to monitor count service " + invoker.getUrl() + ", cause: " + t.getMessage(), t);
+ }
+ }
+
+ /**
+ * Create statistics url
+ *
+ * @param invoker
+ * @param invocation
+ * @param result
+ * @param remoteHost
+ * @param start
+ * @param error
+ * @return
+ */
+ private URL createStatisticsUrl(Invoker> invoker, Invocation invocation, Result result, String remoteHost, long start, boolean error) {
+ // ---- service statistics ----
+ long elapsed = System.currentTimeMillis() - start; // invocation cost
+ int concurrent = getConcurrent(invoker, invocation).get(); // current concurrent count
+ String application = invoker.getUrl().getParameter(APPLICATION_KEY);
+ String service = invoker.getInterface().getName(); // service name
+ String method = RpcUtils.getMethodName(invocation); // method name
+ String group = invoker.getUrl().getParameter(GROUP_KEY);
+ String version = invoker.getUrl().getParameter(VERSION_KEY);
+
+ int localPort;
+ String remoteKey, remoteValue;
+ if (CONSUMER_SIDE.equals(invoker.getUrl().getParameter(SIDE_KEY))) {
+ // ---- for service consumer ----
+ localPort = 0;
+ remoteKey = MonitorService.PROVIDER;
+ remoteValue = invoker.getUrl().getAddress();
+ } else {
+ // ---- for service provider ----
+ localPort = invoker.getUrl().getPort();
+ remoteKey = MonitorService.CONSUMER;
+ remoteValue = remoteHost;
+ }
+ String input = "", output = "";
+ if (invocation.getAttachment(INPUT_KEY) != null) {
+ input = invocation.getAttachment(INPUT_KEY);
+ }
+ if (result != null && result.getAttachment(OUTPUT_KEY) != null) {
+ output = result.getAttachment(OUTPUT_KEY);
+ }
+
+ return new URL(COUNT_PROTOCOL, NetUtils.getLocalHost(), localPort, service + PATH_SEPARATOR + method, MonitorService.APPLICATION, application, MonitorService.INTERFACE, service, MonitorService.METHOD, method, remoteKey, remoteValue, error ? MonitorService.FAILURE : MonitorService.SUCCESS, "1", MonitorService.ELAPSED, String.valueOf(elapsed), MonitorService.CONCURRENT, String.valueOf(concurrent), INPUT_KEY, input, OUTPUT_KEY, output, GROUP_KEY, group, VERSION_KEY, version);
+ }
+
+ }
+
}
diff --git a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java b/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java
index 586ea60d10d..56d372c1d2b 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java
+++ b/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MonitorFilterTest.java
@@ -21,6 +21,7 @@
import org.apache.dubbo.monitor.Monitor;
import org.apache.dubbo.monitor.MonitorFactory;
import org.apache.dubbo.monitor.MonitorService;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
@@ -77,7 +78,7 @@ public boolean isAvailable() {
public Result invoke(Invocation invocation) throws RpcException {
lastInvocation = invocation;
- return null;
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
}
@Override
@@ -119,7 +120,11 @@ public void testFilter() throws Exception {
monitorFilter.setMonitorFactory(monitorFactory);
Invocation invocation = new RpcInvocation("aaa", new Class>[0], new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
- monitorFilter.invoke(serviceInvoker, invocation);
+ Result result = monitorFilter.invoke(serviceInvoker, invocation);
+ result.thenApplyWithContext((r) -> {
+ monitorFilter.listener().onResponse(r, serviceInvoker, invocation);
+ return r;
+ });
while (lastStatistics == null) {
Thread.sleep(10);
}
@@ -155,7 +160,11 @@ public void testGenericFilter() throws Exception {
monitorFilter.setMonitorFactory(monitorFactory);
Invocation invocation = new RpcInvocation("$invoke", new Class>[]{String.class, String[].class, Object[].class}, new Object[]{"xxx", new String[]{}, new Object[]{}});
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
- monitorFilter.invoke(serviceInvoker, invocation);
+ Result result = monitorFilter.invoke(serviceInvoker, invocation);
+ result.thenApplyWithContext((r) -> {
+ monitorFilter.listener().onResponse(r, serviceInvoker, invocation);
+ return r;
+ });
while (lastStatistics == null) {
Thread.sleep(10);
}
diff --git a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
index fa16ae2f574..761de5945dc 100644
--- a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
+++ b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
@@ -23,7 +23,7 @@
import org.apache.dubbo.common.store.DataStore;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.monitor.MetricsService;
-import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
@@ -31,7 +31,6 @@
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.RpcUtils;
import com.alibaba.fastjson.JSON;
@@ -66,6 +65,7 @@
import static org.apache.dubbo.monitor.Constants.METRICS_PORT;
import static org.apache.dubbo.monitor.Constants.METRICS_PROTOCOL;
import static org.apache.dubbo.monitor.Constants.SERVICE;
+import static org.apache.dubbo.remoting.Constants.EXECUTOR_SERVICE_COMPONENT_KEY;
public class MetricsFilter implements Filter {
@@ -178,7 +178,7 @@ private void setCompassQuantity(String groupName, String result, long duration,
private List getThreadPoolMessage() {
DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
- Map executors = dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);
+ Map executors = dataStore.get(EXECUTOR_SERVICE_COMPONENT_KEY);
List threadPoolMtricList = new ArrayList<>();
for (Map.Entry entry : executors.entrySet()) {
@@ -235,12 +235,9 @@ public Result invoke(Invocation invocation) throws RpcException {
collector.collect(entry.getKey(), entry.getValue(), timestamp);
}
- RpcResult result = new RpcResult();
-
List res = collector.build();
res.addAll(getThreadPoolMessage());
- result.setValue(JSON.toJSONString(res));
- return result;
+ return AsyncRpcResult.newDefaultAsyncResult(JSON.toJSONString(res), invocation);
}
@Override
diff --git a/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/MockChannel.java b/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/MockChannel.java
index fa061b99696..7a4961bf954 100644
--- a/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/MockChannel.java
+++ b/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/MockChannel.java
@@ -21,9 +21,9 @@
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.exchange.ExchangeChannel;
import org.apache.dubbo.remoting.exchange.ExchangeHandler;
-import org.apache.dubbo.remoting.exchange.ResponseFuture;
import java.net.InetSocketAddress;
+import java.util.concurrent.CompletableFuture;
public class MockChannel implements ExchangeChannel {
@@ -76,7 +76,7 @@ public URL getUrl() {
return null;
}
- public ResponseFuture send(Object request, int timeout) throws RemotingException {
+ public CompletableFuture
- * TODO RpcResult can be an instance of {@link java.util.concurrent.CompletionStage} instead of composing CompletionStage inside.
+ * TODO if it's reasonable or even right to keep a reference to Invocation?
+ *
+ * As {@link Result} implements CompletionStage, {@link AsyncRpcResult} allows you to easily build a async filter chain whose status will be
+ * driven entirely by the state of the underlying RPC call.
+ *
+ * AsyncRpcResult does not contain any concrete value (except the underlying value bring by CompletableFuture), consider it as a status transfer node.
+ * {@link #getValue()} and {@link #getException()} are all inherited from {@link Result} interface, implementing them are mainly
+ * for compatibility consideration. Because many legacy {@link Filter} implementation are most possibly to call getValue directly.
*/
public class AsyncRpcResult extends AbstractResult {
private static final Logger logger = LoggerFactory.getLogger(AsyncRpcResult.class);
/**
- * RpcContext can be changed, because thread may have been used by other thread. It should be cloned before store.
- * So we use Invocation instead, Invocation will create for every invoke, but invocation only support attachments of string type.
+ * RpcContext may already have been changed when callback happens, it happens when the same thread is used to execute another RPC call.
+ * So we should keep the reference of current RpcContext instance and restore it before callback being executed.
*/
private RpcContext storedContext;
private RpcContext storedServerContext;
- protected CompletableFuture valueFuture;
-
- protected CompletableFuture resultFuture;
+ private Invocation invocation;
- public AsyncRpcResult(CompletableFuture future) {
- this(future, true);
+ public AsyncRpcResult(Invocation invocation) {
+ this.invocation = invocation;
+ this.storedContext = RpcContext.getContext();
+ this.storedServerContext = RpcContext.getServerContext();
}
- public AsyncRpcResult(CompletableFuture future, boolean registerCallback) {
- this(future, new CompletableFuture<>(), registerCallback);
+ public AsyncRpcResult(AsyncRpcResult asyncRpcResult) {
+ this.invocation = asyncRpcResult.getInvocation();
+ this.storedContext = asyncRpcResult.getStoredContext();
+ this.storedServerContext = asyncRpcResult.getStoredServerContext();
}
/**
- * @param future
- * @param rFuture
- * @param registerCallback
+ * Notice the return type of {@link #getValue} is the actual type of the RPC method, not {@link AppResponse}
+ *
+ * @return
*/
- public AsyncRpcResult(CompletableFuture future, final CompletableFuture rFuture, boolean registerCallback) {
- if (rFuture == null) {
- throw new IllegalArgumentException();
- }
- resultFuture = rFuture;
- if (registerCallback) {
- /**
- * We do not know whether future already completed or not, it's a future exposed or even created by end user.
- * 1. future complete before whenComplete. whenComplete fn (resultFuture.complete) will be executed in thread subscribing, in our case, it's Dubbo thread.
- * 2. future complete after whenComplete. whenComplete fn (resultFuture.complete) will be executed in thread calling complete, normally its User thread.
- */
- future.whenComplete((v, t) -> {
- RpcResult rpcResult;
- if (t != null) {
- if (t instanceof CompletionException) {
- rpcResult = new RpcResult(t.getCause());
- } else {
- rpcResult = new RpcResult(t);
- }
- } else {
- rpcResult = new RpcResult(v);
- }
- // instead of resultFuture we must use rFuture here, resultFuture may being changed before complete when building filter chain, but rFuture was guaranteed never changed by closure.
- rFuture.complete(rpcResult);
- });
- }
- this.valueFuture = future;
- // employ copy of context avoid the other call may modify the context content
- this.storedContext = RpcContext.getContext().copyOf();
- this.storedServerContext = RpcContext.getServerContext().copyOf();
- }
-
@Override
public Object getValue() {
- return getRpcResult().getValue();
+ return getAppResponse().getValue();
}
@Override
- public Throwable getException() {
- return getRpcResult().getException();
+ public void setValue(Object value) {
+ AppResponse appResponse = new AppResponse();
+ appResponse.setValue(value);
+ this.complete(appResponse);
}
@Override
- public boolean hasException() {
- return getRpcResult().hasException();
+ public Throwable getException() {
+ return getAppResponse().getException();
}
@Override
- public Object getResult() {
- return getRpcResult().getResult();
- }
-
- public CompletableFuture getValueFuture() {
- return valueFuture;
+ public void setException(Throwable t) {
+ AppResponse appResponse = new AppResponse();
+ appResponse.setException(t);
+ this.complete(appResponse);
}
- public CompletableFuture getResultFuture() {
- return resultFuture;
- }
-
- public void setResultFuture(CompletableFuture resultFuture) {
- this.resultFuture = resultFuture;
+ @Override
+ public boolean hasException() {
+ return getAppResponse().hasException();
}
- public Result getRpcResult() {
+ public Result getAppResponse() {
try {
- if (resultFuture.isDone()) {
- return resultFuture.get();
+ if (this.isDone()) {
+ return this.get();
}
} catch (Exception e) {
// This should never happen;
logger.error("Got exception when trying to fetch the underlying result from AsyncRpcResult.", e);
}
- return new RpcResult();
+ return new AppResponse();
}
@Override
public Object recreate() throws Throwable {
- return valueFuture;
+ RpcInvocation rpcInvocation = (RpcInvocation) invocation;
+ if (InvokeMode.FUTURE == rpcInvocation.getInvokeMode()) {
+ AppResponse appResponse = new AppResponse();
+ CompletableFuture future = new CompletableFuture<>();
+ appResponse.setValue(future);
+ this.whenComplete((result, t) -> {
+ if (t != null) {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ future.completeExceptionally(t);
+ } else {
+ if (result.hasException()) {
+ future.completeExceptionally(result.getException());
+ } else {
+ future.complete(result.getValue());
+ }
+ }
+ });
+ return appResponse.recreate();
+ } else if (this.isDone()) {
+ return this.get().recreate();
+ }
+ return (new AppResponse()).recreate();
+ }
+
+ public Result thenApplyWithContext(Function fn) {
+ CompletableFuture future = this.thenApply(fn.compose(beforeContext).andThen(afterContext));
+ AsyncRpcResult nextAsyncRpcResult = new AsyncRpcResult(this);
+ nextAsyncRpcResult.subscribeTo(future);
+ return nextAsyncRpcResult;
}
- public void thenApplyWithContext(Function fn) {
- this.resultFuture = resultFuture.thenApply(fn.compose(beforeContext).andThen(afterContext));
+ public void subscribeTo(CompletableFuture> future) {
+ future.whenComplete((obj, t) -> {
+ if (t != null) {
+ this.completeExceptionally(t);
+ } else {
+ this.complete((Result) obj);
+ }
+ });
}
@Override
public Map getAttachments() {
- return getRpcResult().getAttachments();
+ return getAppResponse().getAttachments();
}
@Override
public void setAttachments(Map map) {
- getRpcResult().setAttachments(map);
+ getAppResponse().setAttachments(map);
}
@Override
public void addAttachments(Map map) {
- getRpcResult().addAttachments(map);
+ getAppResponse().addAttachments(map);
}
@Override
public String getAttachment(String key) {
- return getRpcResult().getAttachment(key);
+ return getAppResponse().getAttachment(key);
}
@Override
public String getAttachment(String key, String defaultValue) {
- return getRpcResult().getAttachment(key, defaultValue);
+ return getAppResponse().getAttachment(key, defaultValue);
}
@Override
public void setAttachment(String key, String value) {
- getRpcResult().setAttachment(key, value);
+ getAppResponse().setAttachment(key, value);
+ }
+
+ public RpcContext getStoredContext() {
+ return storedContext;
+ }
+
+ public RpcContext getStoredServerContext() {
+ return storedServerContext;
+ }
+
+ public Invocation getInvocation() {
+ return invocation;
}
/**
@@ -203,18 +201,51 @@ public void setAttachment(String key, String value) {
private RpcContext tmpContext;
private RpcContext tmpServerContext;
- private Function beforeContext = (result) -> {
+ private Function beforeContext = (appResponse) -> {
tmpContext = RpcContext.getContext();
tmpServerContext = RpcContext.getServerContext();
RpcContext.restoreContext(storedContext);
RpcContext.restoreServerContext(storedServerContext);
- return result;
+ return appResponse;
};
- private Function afterContext = (result) -> {
+ private Function afterContext = (appResponse) -> {
RpcContext.restoreContext(tmpContext);
RpcContext.restoreServerContext(tmpServerContext);
- return result;
+ return appResponse;
};
+
+ /**
+ * Some utility methods used to quickly generate default AsyncRpcResult instance.
+ */
+ public static AsyncRpcResult newDefaultAsyncResult(AppResponse appResponse, Invocation invocation) {
+ AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
+ asyncRpcResult.complete(appResponse);
+ return asyncRpcResult;
+ }
+
+ public static AsyncRpcResult newDefaultAsyncResult(Invocation invocation) {
+ return newDefaultAsyncResult(null, null, invocation);
+ }
+
+ public static AsyncRpcResult newDefaultAsyncResult(Object value, Invocation invocation) {
+ return newDefaultAsyncResult(value, null, invocation);
+ }
+
+ public static AsyncRpcResult newDefaultAsyncResult(Throwable t, Invocation invocation) {
+ return newDefaultAsyncResult(null, t, invocation);
+ }
+
+ public static AsyncRpcResult newDefaultAsyncResult(Object value, Throwable t, Invocation invocation) {
+ AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
+ AppResponse appResponse = new AppResponse();
+ if (t != null) {
+ appResponse.setException(t);
+ } else {
+ appResponse.setValue(value);
+ }
+ asyncRpcResult.complete(appResponse);
+ return asyncRpcResult;
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
index a17fd906d55..53ad128efa7 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
@@ -42,35 +42,29 @@
*/
@SPI
public interface Filter {
-
/**
- * do invoke filter.
- *
- *
- * // before filter
- * Result result = invoker.invoke(invocation);
- * // after filter
- * return result;
- *
- *
- * @param invoker service
- * @param invocation invocation.
- * @return invoke result.
- * @throws RpcException
- * @see org.apache.dubbo.rpc.Invoker#invoke(Invocation)
+ * Does not need to override/implement this method.
*/
Result invoke(Invoker> invoker, Invocation invocation) throws RpcException;
/**
- * Return processing result
+ * Filter itself should only be response for passing invocation, all callbacks has been placed into {@link Listener}
*
- * @param result result
- * @param invoker invoker
- * @param invocation invocation
- * @return Return {@link Result}
+ * @param appResponse
+ * @param invoker
+ * @param invocation
+ * @return
*/
- default Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- return result;
+ @Deprecated
+ default Result onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ return appResponse;
+ }
+
+ interface Listener {
+
+ void onResponse(Result appResponse, Invoker> invoker, Invocation invocation);
+
+ void onError(Throwable t, Invoker> invoker, Invocation invocation);
}
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/FutureContext.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/FutureContext.java
new file mode 100644
index 00000000000..8d5a1b62fa3
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/FutureContext.java
@@ -0,0 +1,54 @@
+/*
+ * 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.dubbo.rpc;
+
+import org.apache.dubbo.common.threadlocal.InternalThreadLocal;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Used for async call scenario. But if the method you are calling has a {@link CompletableFuture>} signature
+ * you do not need to use this class since you will get a Future response directly.
+ *
+ * Remember to save the Future reference before making another call using the same thread, otherwise,
+ * the current Future will be override by the new one, which means you will lose the chance get the return value.
+ */
+public class FutureContext {
+
+ public static InternalThreadLocal> futureTL = new InternalThreadLocal<>();
+
+ /**
+ * get future.
+ *
+ * @param
+ * @return future
+ */
+ @SuppressWarnings("unchecked")
+ public static CompletableFuture getCompletableFuture() {
+ return (CompletableFuture) futureTL.get();
+ }
+
+ /**
+ * set future.
+ *
+ * @param future
+ */
+ public static void setFuture(CompletableFuture> future) {
+ futureTL.set(future);
+ }
+
+}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
index 2b5f3dd9e95..058e0ad09c9 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
@@ -59,6 +59,10 @@ public interface Invocation {
*/
Map getAttachments();
+ void setAttachment(String key, String value);
+
+ void setAttachmentIfAbsent(String key, String value);
+
/**
* get attachment by key.
*
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java
similarity index 82%
rename from dubbo-compatible/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java
rename to dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java
index 893b262094b..a97a0be61f4 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java
@@ -14,12 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.rpc;
-package com.alibaba.dubbo.remoting.exchange;
+public enum InvokeMode {
+
+ SYNC, ASYNC, FUTURE;
-/**
- * 2019-04-18
- */
-@Deprecated
-public interface ResponseCallback extends org.apache.dubbo.remoting.exchange.ResponseCallback {
}
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java
similarity index 74%
rename from dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java
rename to dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java
index 07a69871af7..622ef1f0309 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java
@@ -14,16 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package com.alibaba.dubbo.rpc.protocol.dubbo;
-
-import org.apache.dubbo.remoting.exchange.ResponseFuture;
+package org.apache.dubbo.rpc;
/**
- * 2019-04-18
+ *
*/
-public class FutureAdapter extends org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter {
- public FutureAdapter(ResponseFuture future) {
- super(future);
+public abstract class ListenableFilter implements Filter {
+
+ protected Listener listener = null;
+
+ public Listener listener() {
+ return listener;
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java
index 58a258241ff..1f3a5138319 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Result.java
@@ -18,16 +18,27 @@
import java.io.Serializable;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Future;
+import java.util.function.Function;
/**
- * RPC invoke result. (API, Prototype, NonThreadSafe)
+ * (API, Prototype, NonThreadSafe)
+ *
+ * An RPC {@link Result}.
+ *
+ * Known implementations are:
+ * 1. {@link AsyncRpcResult}, it's a {@link CompletionStage} whose underlying value signifies the return value of an RPC call.
+ * 2. {@link AppResponse}, it inevitably inherits {@link CompletionStage} and {@link Future}, but you should never treat AppResponse as a type of Future,
+ * instead, it is a normal concrete type.
*
* @serial Don't change the class name and package name.
* @see org.apache.dubbo.rpc.Invoker#invoke(Invocation)
- * @see org.apache.dubbo.rpc.RpcResult
+ * @see AppResponse
*/
-public interface Result extends Serializable {
+public interface Result extends CompletionStage, Future, Serializable {
/**
* Get invoke result.
@@ -36,6 +47,8 @@ public interface Result extends Serializable {
*/
Object getValue();
+ void setValue(Object value);
+
/**
* Get exception.
*
@@ -43,6 +56,8 @@ public interface Result extends Serializable {
*/
Throwable getException();
+ void setException(Throwable t);
+
/**
* Has exception.
*
@@ -66,14 +81,6 @@ public interface Result extends Serializable {
*/
Object recreate() throws Throwable;
- /**
- * @see org.apache.dubbo.rpc.Result#getValue()
- * @deprecated Replace to getValue()
- */
- @Deprecated
- Object getResult();
-
-
/**
* get attachments.
*
@@ -111,4 +118,26 @@ public interface Result extends Serializable {
void setAttachment(String key, String value);
+ /**
+ * Returns the specified {@code valueIfAbsent} when not complete, or
+ * returns the result value or throws an exception when complete.
+ *
+ * @see CompletableFuture#getNow(Object)
+ */
+ Result getNow(Result valueIfAbsent);
+
+ /**
+ * Add a callback which can be triggered when the RPC call finishes.
+ *
+ * Just as the method name implies, this method will guarantee the callback being triggered under the same context as when the call was started,
+ * see implementation in {@link AsyncRpcResult#thenApplyWithContext(Function)}
+ *
+ * @param fn
+ * @return
+ */
+ Result thenApplyWithContext(Function fn);
+
+ default CompletableFuture completionFuture() {
+ return toCompletableFuture();
+ }
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java
index fc658db052d..50221704099 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcContext.java
@@ -75,7 +75,6 @@ protected RpcContext initialValue() {
private final Map attachments = new HashMap();
private final Map values = new HashMap();
- private Future> future;
private List urls;
@@ -144,32 +143,6 @@ public static void restoreContext(RpcContext oldContext) {
LOCAL.set(oldContext);
}
-
- public RpcContext copyOf() {
- RpcContext copy = new RpcContext();
- copy.attachments.putAll(this.attachments);
- copy.values.putAll(this.values);
- copy.future = this.future;
- copy.urls = this.urls;
- copy.url = this.url;
- copy.methodName = this.methodName;
- copy.parameterTypes = this.parameterTypes;
- copy.arguments = this.arguments;
- copy.localAddress = this.localAddress;
- copy.remoteAddress = this.remoteAddress;
- copy.remoteApplicationName = this.remoteApplicationName;
- copy.invokers = this.invokers;
- copy.invoker = this.invoker;
- copy.invocation = this.invocation;
-
- copy.request = this.request;
- copy.response = this.response;
- copy.asyncContext = this.asyncContext;
-
- return copy;
- }
-
-
/**
* remove context.
*
@@ -251,7 +224,7 @@ public boolean isConsumerSide() {
*/
@SuppressWarnings("unchecked")
public CompletableFuture getCompletableFuture() {
- return (CompletableFuture) future;
+ return FutureContext.getCompletableFuture();
}
/**
@@ -262,7 +235,7 @@ public CompletableFuture getCompletableFuture() {
*/
@SuppressWarnings("unchecked")
public Future getFuture() {
- return (Future) future;
+ return FutureContext.getCompletableFuture();
}
/**
@@ -270,8 +243,8 @@ public Future getFuture() {
*
* @param future
*/
- public void setFuture(Future> future) {
- this.future = future;
+ public void setFuture(CompletableFuture> future) {
+ FutureContext.setFuture(future);
}
public List getUrls() {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
index a03e3dc15a2..e422bef6cf1 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
@@ -52,6 +52,10 @@ public class RpcInvocation implements Invocation, Serializable {
private transient Invoker> invoker;
+ private transient Class> returnType;
+
+ private transient InvokeMode invokeMode;
+
public RpcInvocation() {
}
@@ -94,6 +98,7 @@ public RpcInvocation(Method method, Object[] arguments) {
public RpcInvocation(Method method, Object[] arguments, Map attachment) {
this(method.getName(), method.getParameterTypes(), arguments, attachment, null);
+ this.returnType = method.getReturnType();
}
public RpcInvocation(String methodName, Class>[] parameterTypes, Object[] arguments) {
@@ -212,6 +217,22 @@ public String getAttachment(String key, String defaultValue) {
return value;
}
+ public Class> getReturnType() {
+ return returnType;
+ }
+
+ public void setReturnType(Class> returnType) {
+ this.returnType = returnType;
+ }
+
+ public InvokeMode getInvokeMode() {
+ return invokeMode;
+ }
+
+ public void setInvokeMode(InvokeMode invokeMode) {
+ this.invokeMode = invokeMode;
+ }
+
@Override
public String toString() {
return "RpcInvocation [methodName=" + methodName + ", parameterTypes="
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcResult.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcResult.java
deleted file mode 100644
index 8087210f29a..00000000000
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcResult.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.dubbo.rpc;
-
-import java.lang.reflect.Field;
-
-/**
- * RPC Result.
- *
- * @serial Don't change the class name and properties.
- */
-public class RpcResult extends AbstractResult {
-
- private static final long serialVersionUID = -6925924956850004727L;
-
- public RpcResult() {
- }
-
- public RpcResult(Object result) {
- this.result = result;
- }
-
- public RpcResult(Throwable exception) {
- this.exception = handleStackTraceNull(exception);
- }
-
- @Override
- public Object recreate() throws Throwable {
- if (exception != null) {
- throw exception;
- }
- return result;
- }
-
- /**
- * @see org.apache.dubbo.rpc.RpcResult#getValue()
- * @deprecated Replace to getValue()
- */
- @Override
- @Deprecated
- public Object getResult() {
- return getValue();
- }
-
- /**
- * @see org.apache.dubbo.rpc.RpcResult#setValue(Object)
- * @deprecated Replace to setValue()
- */
- @Deprecated
- public void setResult(Object result) {
- setValue(result);
- }
-
- @Override
- public Object getValue() {
- return result;
- }
-
- public void setValue(Object value) {
- this.result = value;
- }
-
- @Override
- public Throwable getException() {
- return exception;
- }
-
- public void setException(Throwable e) {
- this.exception = handleStackTraceNull(e);
- }
-
- @Override
- public boolean hasException() {
- return exception != null;
- }
-
- @Override
- public String toString() {
- return "RpcResult [result=" + result + ", exception=" + exception + "]";
- }
-
- /**
- * we need to deal the exception whose stack trace is null.
- *
- * see https://github.com/apache/incubator-dubbo/pull/2956
- * and https://github.com/apache/incubator-dubbo/pull/3634
- * and https://github.com/apache/incubator-dubbo/issues/619
- *
- * @param e exception
- * @return exception after deal with stack trace
- */
- private Throwable handleStackTraceNull(Throwable e) {
- if (e != null) {
- try {
- // get Throwable class
- Class clazz = e.getClass();
- while (!clazz.getName().equals(Throwable.class.getName())) {
- clazz = clazz.getSuperclass();
- }
- // get stackTrace value
- Field stackTraceField = clazz.getDeclaredField("stackTrace");
- stackTraceField.setAccessible(true);
- Object stackTrace = stackTraceField.get(e);
- if (stackTrace == null) {
- e.setStackTrace(new StackTraceElement[0]);
- }
- } catch (Throwable t) {
- // ignore
- }
- }
-
- return e;
- }
-}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/SimpleAsyncRpcResult.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/SimpleAsyncRpcResult.java
deleted file mode 100644
index 98e42d94a38..00000000000
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/SimpleAsyncRpcResult.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.dubbo.rpc;
-
-import java.util.concurrent.CompletableFuture;
-
-/**
- * A sub class used for normal async invoke.
- *
- * NOTICE!!
- *
- *
- * You should never rely on this class directly when using or extending Dubbo, the implementation of {@link SimpleAsyncRpcResult}
- * is only a workaround for compatibility purpose. It may be changed or even get removed from the next major version.
- * Please only use {@link Result} or {@link RpcResult}.
- *
- *
- * Check {@link AsyncRpcResult} for more details.
- *
- * TODO AsyncRpcResult, AsyncNormalRpcResult should not be a parent-child hierarchy.
- */
-public class SimpleAsyncRpcResult extends AsyncRpcResult {
- public SimpleAsyncRpcResult(CompletableFuture future, boolean registerCallback) {
- super(future, registerCallback);
- }
-
- public SimpleAsyncRpcResult(CompletableFuture future, CompletableFuture rFuture, boolean registerCallback) {
- super(future, rFuture, registerCallback);
- }
-
- @Override
- public Object recreate() throws Throwable {
- // TODO should we check the status of valueFuture here?
- return null;
- }
-}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java
index 0e1df8f1d02..19090c1e0fb 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java
@@ -18,9 +18,11 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcStatus;
@@ -42,50 +44,75 @@
* @see Filter
*/
@Activate(group = CONSUMER, value = ACTIVES_KEY)
-public class ActiveLimitFilter implements Filter {
+public class ActiveLimitFilter extends ListenableFilter {
+
+ private static final String ACTIVELIMIT_FILTER_START_TIME = "activelimit_filter_start_time";
+
+ public ActiveLimitFilter() {
+ super.listener = new ActiveLimitListener();
+ }
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
URL url = invoker.getUrl();
String methodName = invocation.getMethodName();
int max = invoker.getUrl().getMethodParameter(methodName, ACTIVES_KEY, 0);
- RpcStatus count = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
+ RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
if (!RpcStatus.beginCount(url, methodName, max)) {
long timeout = invoker.getUrl().getMethodParameter(invocation.getMethodName(), TIMEOUT_KEY, 0);
long start = System.currentTimeMillis();
long remain = timeout;
- synchronized (count) {
+ synchronized (rpcStatus) {
while (!RpcStatus.beginCount(url, methodName, max)) {
try {
- count.wait(remain);
+ rpcStatus.wait(remain);
} catch (InterruptedException e) {
// ignore
}
long elapsed = System.currentTimeMillis() - start;
remain = timeout - elapsed;
if (remain <= 0) {
- throw new RpcException("Waiting concurrent invoke timeout in client-side for service: "
- + invoker.getInterface().getName() + ", method: "
- + invocation.getMethodName() + ", elapsed: " + elapsed
- + ", timeout: " + timeout + ". concurrent invokes: " + count.getActive()
- + ". max concurrent invoke limit: " + max);
+ throw new RpcException("Waiting concurrent invoke timeout in client-side for service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", elapsed: " + elapsed + ", timeout: " + timeout + ". concurrent invokes: " + rpcStatus.getActive() + ". max concurrent invoke limit: " + max);
}
}
}
}
- boolean isSuccess = true;
- long begin = System.currentTimeMillis();
- try {
- return invoker.invoke(invocation);
- } catch (RuntimeException t) {
- isSuccess = false;
- throw t;
- } finally {
- RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, isSuccess);
+ invocation.setAttachment(ACTIVELIMIT_FILTER_START_TIME, String.valueOf(System.currentTimeMillis()));
+
+ return invoker.invoke(invocation);
+ }
+
+ static class ActiveLimitListener implements Listener {
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ String methodName = invocation.getMethodName();
+ URL url = invoker.getUrl();
+ int max = invoker.getUrl().getMethodParameter(methodName, ACTIVES_KEY, 0);
+
+ RpcStatus.endCount(url, methodName, getElapsed(invocation), true);
+ notifyFinish(RpcStatus.getStatus(url, methodName), max);
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+ String methodName = invocation.getMethodName();
+ URL url = invoker.getUrl();
+ int max = invoker.getUrl().getMethodParameter(methodName, ACTIVES_KEY, 0);
+
+ RpcStatus.endCount(url, methodName, getElapsed(invocation), false);
+ notifyFinish(RpcStatus.getStatus(url, methodName), max);
+ }
+
+ private long getElapsed(Invocation invocation) {
+ String beginTime = invocation.getAttachment(ACTIVELIMIT_FILTER_START_TIME);
+ return StringUtils.isNotEmpty(beginTime) ? System.currentTimeMillis() - Long.parseLong(beginTime) : 0;
+ }
+
+ private void notifyFinish(RpcStatus rpcStatus, int max) {
if (max > 0) {
- synchronized (count) {
- count.notifyAll();
+ synchronized (rpcStatus) {
+ rpcStatus.notifyAll();
}
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/CompatibleFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/CompatibleFilter.java
index 5842b32c04d..54aea0d7378 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/CompatibleFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/CompatibleFilter.java
@@ -20,17 +20,18 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CompatibleTypeUtils;
import org.apache.dubbo.common.utils.PojoUtils;
-import org.apache.dubbo.remoting.Constants;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
+
/**
* CompatibleFilter make the remote method's return value compatible to invoker's version of object.
* To make return object compatible it does
@@ -45,44 +46,54 @@
* @see Filter
*
*/
-public class CompatibleFilter implements Filter {
+public class CompatibleFilter extends ListenableFilter {
private static Logger logger = LoggerFactory.getLogger(CompatibleFilter.class);
+ public CompatibleFilter() {
+ super.listener = new CompatibleListener();
+ }
+
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
- Result result = invoker.invoke(invocation);
- if (!invocation.getMethodName().startsWith("$") && !result.hasException()) {
- Object value = result.getValue();
- if (value != null) {
- try {
- Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());
- Class> type = method.getReturnType();
- Object newValue;
- String serialization = invoker.getUrl().getParameter(Constants.SERIALIZATION_KEY);
- if ("json".equals(serialization)
- || "fastjson".equals(serialization)) {
- // If the serialization key is json or fastjson
- Type gtype = method.getGenericReturnType();
- newValue = PojoUtils.realize(value, type, gtype);
- } else if (!type.isInstance(value)) {
- //if local service interface's method's return type is not instance of return value
- newValue = PojoUtils.isPojo(type)
- ? PojoUtils.realize(value, type)
- : CompatibleTypeUtils.compatibleTypeConvert(value, type);
+ return invoker.invoke(invocation);
+ }
- } else {
- newValue = value;
- }
- if (newValue != value) {
- result = new RpcResult(newValue);
+ static class CompatibleListener implements Listener {
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ if (!invocation.getMethodName().startsWith("$") && !appResponse.hasException()) {
+ Object value = appResponse.getValue();
+ if (value != null) {
+ try {
+ Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());
+ Class> type = method.getReturnType();
+ Object newValue;
+ String serialization = invoker.getUrl().getParameter(SERIALIZATION_KEY);
+ if ("json".equals(serialization) || "fastjson".equals(serialization)) {
+ // If the serialization key is json or fastjson
+ Type gtype = method.getGenericReturnType();
+ newValue = PojoUtils.realize(value, type, gtype);
+ } else if (!type.isInstance(value)) {
+ //if local service interface's method's return type is not instance of return value
+ newValue = PojoUtils.isPojo(type) ? PojoUtils.realize(value, type) : CompatibleTypeUtils.compatibleTypeConvert(value, type);
+
+ } else {
+ newValue = value;
+ }
+ if (newValue != value) {
+ appResponse.setValue(newValue);
+ }
+ } catch (Throwable t) {
+ logger.warn(t.getMessage(), t);
}
- } catch (Throwable t) {
- logger.warn(t.getMessage(), t);
}
}
}
- return result;
- }
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ConsumerContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ConsumerContextFilter.java
index f1696f4a077..43353f7e7dc 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ConsumerContextFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ConsumerContextFilter.java
@@ -16,17 +16,18 @@
*/
package org.apache.dubbo.rpc.filter;
-import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
+import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
+
/**
* ConsumerContextFilter set current RpcContext with invoker,invocation, local host, remote host and port
* for consumer invoker.It does it to make the requires info available to execution thread's RpcContext.
@@ -34,8 +35,12 @@
* @see org.apache.dubbo.rpc.Filter
* @see RpcContext
*/
-@Activate(group = CommonConstants.CONSUMER, order = -10000)
-public class ConsumerContextFilter implements Filter {
+@Activate(group = CONSUMER, order = -10000)
+public class ConsumerContextFilter extends ListenableFilter {
+
+ public ConsumerContextFilter() {
+ super.listener = new ConsumerContextListener();
+ }
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
@@ -49,18 +54,22 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
((RpcInvocation) invocation).setInvoker(invoker);
}
try {
- // TODO should we clear server context?
RpcContext.removeServerContext();
return invoker.invoke(invocation);
} finally {
- // TODO removeContext? but we need to save future for RpcContext.getFuture() API. If clear attachments here, attachments will not available when postProcessResult is invoked.
- RpcContext.getContext().clearAttachments();
+ RpcContext.removeContext();
}
}
- @Override
- public Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- RpcContext.getServerContext().setAttachments(result.getAttachments());
- return result;
+ static class ConsumerContextListener implements Listener {
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ RpcContext.getServerContext().setAttachments(appResponse.getAttachments());
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
index 8939c3ace2a..49e2a602d21 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
@@ -17,9 +17,9 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
@@ -48,9 +48,13 @@
* @see RpcContext
*/
@Activate(group = PROVIDER, order = -10000)
-public class ContextFilter implements Filter {
+public class ContextFilter extends ListenableFilter {
private static final String TAG_KEY = "dubbo.tag";
+ public ContextFilter() {
+ super.listener = new ContextListener();
+ }
+
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
Map attachments = invocation.getAttachments();
@@ -97,10 +101,16 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
}
}
- @Override
- public Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- // pass attachments to result
- result.addAttachments(RpcContext.getServerContext().getAttachments());
- return result;
+ static class ContextListener implements Listener {
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ // pass attachments to result
+ appResponse.addAttachments(RpcContext.getServerContext().getAttachments());
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/EchoFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/EchoFilter.java
index b50e9ffe16c..d51e6d4a2a3 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/EchoFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/EchoFilter.java
@@ -18,12 +18,12 @@
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import static org.apache.dubbo.rpc.Constants.$ECHO;
@@ -36,7 +36,7 @@ public class EchoFilter implements Filter {
@Override
public Result invoke(Invoker> invoker, Invocation inv) throws RpcException {
if (inv.getMethodName().equals($ECHO) && inv.getArguments() != null && inv.getArguments().length == 1) {
- return new RpcResult(inv.getArguments()[0]);
+ return AsyncRpcResult.newDefaultAsyncResult(inv.getArguments()[0], inv);
}
return invoker.invoke(inv);
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java
index bc4018513fc..8f5411b179c 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExceptionFilter.java
@@ -22,13 +22,12 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.service.GenericService;
import java.lang.reflect.Method;
@@ -45,85 +44,82 @@
*
*/
@Activate(group = CommonConstants.PROVIDER)
-public class ExceptionFilter implements Filter {
-
- private final Logger logger;
+public class ExceptionFilter extends ListenableFilter {
public ExceptionFilter() {
- this(LoggerFactory.getLogger(ExceptionFilter.class));
- }
-
- public ExceptionFilter(Logger logger) {
- this.logger = logger;
+ super.listener = new ExceptionListener();
}
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
- try {
- return invoker.invoke(invocation);
- } catch (RuntimeException e) {
- logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()
- + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
- + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
- throw e;
- }
+ return invoker.invoke(invocation);
}
- @Override
- public Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- if (result.hasException() && GenericService.class != invoker.getInterface()) {
- try {
- Throwable exception = result.getException();
-
- // directly throw if it's checked exception
- if (!(exception instanceof RuntimeException) && (exception instanceof Exception)) {
- return result;
- }
- // directly throw if the exception appears in the signature
+ static class ExceptionListener implements Listener {
+
+ private Logger logger = LoggerFactory.getLogger(ExceptionListener.class);
+
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ if (appResponse.hasException() && GenericService.class != invoker.getInterface()) {
try {
- Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());
- Class>[] exceptionClassses = method.getExceptionTypes();
- for (Class> exceptionClass : exceptionClassses) {
- if (exception.getClass().equals(exceptionClass)) {
- return result;
+ Throwable exception = appResponse.getException();
+
+ // directly throw if it's checked exception
+ if (!(exception instanceof RuntimeException) && (exception instanceof Exception)) {
+ return;
+ }
+ // directly throw if the exception appears in the signature
+ try {
+ Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());
+ Class>[] exceptionClassses = method.getExceptionTypes();
+ for (Class> exceptionClass : exceptionClassses) {
+ if (exception.getClass().equals(exceptionClass)) {
+ return;
+ }
}
+ } catch (NoSuchMethodException e) {
+ return;
}
- } catch (NoSuchMethodException e) {
- return result;
- }
- // for the exception not found in method's signature, print ERROR message in server's log.
- logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()
- + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
- + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);
+ // for the exception not found in method's signature, print ERROR message in server's log.
+ logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);
- // directly throw if exception class and interface class are in the same jar file.
- String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
- String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
- if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)) {
- return result;
- }
- // directly throw if it's JDK exception
- String className = exception.getClass().getName();
- if (className.startsWith("java.") || className.startsWith("javax.")) {
- return result;
- }
- // directly throw if it's dubbo exception
- if (exception instanceof RpcException) {
- return result;
- }
+ // directly throw if exception class and interface class are in the same jar file.
+ String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());
+ String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());
+ if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)) {
+ return;
+ }
+ // directly throw if it's JDK exception
+ String className = exception.getClass().getName();
+ if (className.startsWith("java.") || className.startsWith("javax.")) {
+ return;
+ }
+ // directly throw if it's dubbo exception
+ if (exception instanceof RpcException) {
+ return;
+ }
- // otherwise, wrap with RuntimeException and throw back to the client
- return new RpcResult(new RuntimeException(StringUtils.toString(exception)));
- } catch (Throwable e) {
- logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()
- + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
- + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
- return result;
+ // otherwise, wrap with RuntimeException and throw back to the client
+ appResponse.setException(new RuntimeException(StringUtils.toString(exception)));
+ return;
+ } catch (Throwable e) {
+ logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
+ return;
+ }
}
}
- return result;
- }
+ @Override
+ public void onError(Throwable e, Invoker> invoker, Invocation invocation) {
+ logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost() + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);
+ }
+
+ // For test purpose
+ public void setLogger(Logger logger) {
+ this.logger = logger;
+ }
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java
index f14dddfab68..e1af529b15f 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java
@@ -19,9 +19,10 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcStatus;
@@ -30,12 +31,20 @@
/**
+ *
* The maximum parallel execution request count per method per service for the provider.If the max configured
* executes is set to 10 and if invoke request where it is already 10 then it will throws exception. It
* continue the same behaviour un till it is <10.
+ *
*/
@Activate(group = CommonConstants.PROVIDER, value = EXECUTES_KEY)
-public class ExecuteLimitFilter implements Filter {
+public class ExecuteLimitFilter extends ListenableFilter {
+
+ private static final String EXECUTELIMIT_FILTER_START_TIME = "execugtelimit_filter_start_time";
+
+ public ExecuteLimitFilter() {
+ super.listener = new ExecuteLimitListener();
+ }
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
@@ -48,20 +57,32 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
"\" /> limited.");
}
- long begin = System.currentTimeMillis();
- boolean isSuccess = true;
+ invocation.setAttachment(EXECUTELIMIT_FILTER_START_TIME, String.valueOf(System.currentTimeMillis()));
try {
return invoker.invoke(invocation);
} catch (Throwable t) {
- isSuccess = false;
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new RpcException("unexpected exception when ExecuteLimitFilter", t);
}
- } finally {
- RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, isSuccess);
}
}
+ static class ExecuteLimitListener implements Listener {
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ RpcStatus.endCount(invoker.getUrl(), invocation.getMethodName(), getElapsed(invocation), true);
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+ RpcStatus.endCount(invoker.getUrl(), invocation.getMethodName(), getElapsed(invocation), false);
+ }
+
+ private long getElapsed(Invocation invocation) {
+ String beginTime = invocation.getAttachment(EXECUTELIMIT_FILTER_START_TIME);
+ return StringUtils.isNotEmpty(beginTime) ? System.currentTimeMillis() - Long.parseLong(beginTime) : 0;
+ }
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
index 07702dcb3e9..fd83e1f4271 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
@@ -28,14 +28,13 @@
import org.apache.dubbo.common.utils.PojoUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -44,20 +43,25 @@
import java.lang.reflect.Method;
import static org.apache.dubbo.common.constants.RpcConstants.$INVOKE;
-import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
+import static org.apache.dubbo.common.constants.RpcConstants.$INVOKE_ASYNC;
+import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_BEAN;
+import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_PROTOBUF;
-import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
/**
* GenericInvokerFilter.
*/
@Activate(group = CommonConstants.PROVIDER, order = -20000)
-public class GenericFilter implements Filter {
+public class GenericFilter extends ListenableFilter {
+
+ public GenericFilter() {
+ super.listener = new GenericListener();
+ }
@Override
public Result invoke(Invoker> invoker, Invocation inv) throws RpcException {
- if (inv.getMethodName().equals($INVOKE)
+ if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
&& inv.getArguments() != null
&& inv.getArguments().length == 3
&& !GenericService.class.isAssignableFrom(invoker.getInterface())) {
@@ -134,18 +138,38 @@ public Result invoke(Invoker> invoker, Invocation inv) throws RpcException {
args[0].getClass().getName());
}
}
- Result result = invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));
- if (result.hasException()
- && !(result.getException() instanceof GenericException)) {
- return new RpcResult(new GenericException(result.getException()));
+ return invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));
+ } catch (NoSuchMethodException e) {
+ throw new RpcException(e.getMessage(), e);
+ } catch (ClassNotFoundException e) {
+ throw new RpcException(e.getMessage(), e);
+ }
+ }
+ return invoker.invoke(inv);
+ }
+
+ static class GenericListener implements Listener {
+
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation inv) {
+ if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
+ && inv.getArguments() != null
+ && inv.getArguments().length == 3
+ && !GenericService.class.isAssignableFrom(invoker.getInterface())) {
+
+ String generic = inv.getAttachment(GENERIC_KEY);
+ if (StringUtils.isBlank(generic)) {
+ generic = RpcContext.getContext().getAttachment(GENERIC_KEY);
+ }
+
+ if (appResponse.hasException() && !(appResponse.getException() instanceof GenericException)) {
+ appResponse.setException(new GenericException(appResponse.getException()));
}
if (ProtocolUtils.isJavaGenericSerialization(generic)) {
try {
UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(512);
- ExtensionLoader.getExtensionLoader(Serialization.class)
- .getExtension(GENERIC_SERIALIZATION_NATIVE_JAVA)
- .serialize(null, os).writeObject(result.getValue());
- return new RpcResult(os.toByteArray());
+ ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(GENERIC_SERIALIZATION_NATIVE_JAVA).serialize(null, os).writeObject(appResponse.getValue());
+ appResponse.setValue(os.toByteArray());
} catch (IOException e) {
throw new RpcException(
"Generic serialization [" +
@@ -153,29 +177,28 @@ public Result invoke(Invoker> invoker, Invocation inv) throws RpcException {
"] serialize result failed.", e);
}
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
- return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
+ appResponse.setValue(JavaBeanSerializeUtil.serialize(appResponse.getValue(), JavaBeanAccessor.METHOD));
} else if (ProtocolUtils.isProtobufGenericSerialization(generic)) {
try {
UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(512);
ExtensionLoader.getExtensionLoader(Serialization.class)
.getExtension(GENERIC_SERIALIZATION_PROTOBUF)
- .serialize(null, os).writeObject(result.getValue());
- return new RpcResult(os.toString());
+ .serialize(null, os).writeObject(appResponse.getValue());
+ appResponse.setValue(os.toString());
} catch (IOException e) {
throw new RpcException("Generic serialization [" +
GENERIC_SERIALIZATION_PROTOBUF +
"] serialize result failed.", e);
}
} else {
- return new RpcResult(PojoUtils.generalize(result.getValue()));
+ appResponse.setValue(PojoUtils.generalize(appResponse.getValue()));
}
- } catch (NoSuchMethodException e) {
- throw new RpcException(e.getMessage(), e);
- } catch (ClassNotFoundException e) {
- throw new RpcException(e.getMessage(), e);
}
}
- return invoker.invoke(inv);
- }
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
index d422fb474e9..ed5de7e1571 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java
@@ -25,40 +25,46 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.PojoUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.support.ProtocolUtils;
+import org.apache.dubbo.rpc.support.RpcUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import static org.apache.dubbo.common.constants.RpcConstants.$INVOKE;
+import static org.apache.dubbo.common.constants.RpcConstants.$INVOKE_ASYNC;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
/**
* GenericImplInvokerFilter
*/
@Activate(group = CommonConstants.CONSUMER, value = GENERIC_KEY, order = 20000)
-public class GenericImplFilter implements Filter {
+public class GenericImplFilter extends ListenableFilter {
private static final Logger logger = LoggerFactory.getLogger(GenericImplFilter.class);
private static final Class>[] GENERIC_PARAMETER_TYPES = new Class>[]{String.class, String[].class, Object[].class};
+ public GenericImplFilter() {
+ super.listener = new GenericImplListener();
+ }
+
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
String generic = invoker.getUrl().getParameter(GENERIC_KEY);
if (ProtocolUtils.isGeneric(generic)
- && !$INVOKE.equals(invocation.getMethodName())
+ && (!$INVOKE.equals(invocation.getMethodName()) && !$INVOKE_ASYNC.equals(invocation.getMethodName()))
&& invocation instanceof RpcInvocation) {
- RpcInvocation invocation2 = (RpcInvocation) invocation;
+ RpcInvocation invocation2 = new RpcInvocation(invocation);
String methodName = invocation2.getMethodName();
Class>[] parameterTypes = invocation2.getParameterTypes();
Object[] arguments = invocation2.getArguments();
@@ -78,77 +84,15 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
args = PojoUtils.generalize(arguments);
}
- invocation2.setMethodName($INVOKE);
+ if (RpcUtils.isReturnTypeFuture(invocation)) {
+ invocation2.setMethodName($INVOKE_ASYNC);
+ } else {
+ invocation2.setMethodName($INVOKE);
+ }
invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
invocation2.setArguments(new Object[]{methodName, types, args});
- Result result = invoker.invoke(invocation2);
-
- if (!result.hasException()) {
- Object value = result.getValue();
- try {
- Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
- if (ProtocolUtils.isBeanGenericSerialization(generic)) {
- if (value == null) {
- return new RpcResult(value);
- } else if (value instanceof JavaBeanDescriptor) {
- return new RpcResult(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) value));
- } else {
- throw new RpcException(
- "The type of result value is " +
- value.getClass().getName() +
- " other than " +
- JavaBeanDescriptor.class.getName() +
- ", and the result is " +
- value);
- }
- } else {
- return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
- }
- } catch (NoSuchMethodException e) {
- throw new RpcException(e.getMessage(), e);
- }
- } else if (result.getException() instanceof GenericException) {
- GenericException exception = (GenericException) result.getException();
- try {
- String className = exception.getExceptionClass();
- Class> clazz = ReflectUtils.forName(className);
- Throwable targetException = null;
- Throwable lastException = null;
- try {
- targetException = (Throwable) clazz.newInstance();
- } catch (Throwable e) {
- lastException = e;
- for (Constructor> constructor : clazz.getConstructors()) {
- try {
- targetException = (Throwable) constructor.newInstance(new Object[constructor.getParameterTypes().length]);
- break;
- } catch (Throwable e1) {
- lastException = e1;
- }
- }
- }
- if (targetException != null) {
- try {
- Field field = Throwable.class.getDeclaredField("detailMessage");
- if (!field.isAccessible()) {
- field.setAccessible(true);
- }
- field.set(targetException, exception.getExceptionMessage());
- } catch (Throwable e) {
- logger.warn(e.getMessage(), e);
- }
- result = new RpcResult(targetException);
- } else if (lastException != null) {
- throw lastException;
- }
- } catch (Throwable e) {
- throw new RpcException("Can not deserialize exception " + exception.getExceptionClass() + ", message: " + exception.getExceptionMessage(), e);
- }
- }
- return result;
- }
-
- if (invocation.getMethodName().equals($INVOKE)
+ return invoker.invoke(invocation2);
+ } else if ((invocation.getMethodName().equals($INVOKE) || invocation.getMethodName().equals($INVOKE_ASYNC))
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3
&& ProtocolUtils.isGeneric(generic)) {
@@ -169,19 +113,89 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
}
}
- ((RpcInvocation) invocation).setAttachment(GENERIC_KEY, invoker.getUrl().getParameter(GENERIC_KEY));
+ invocation.setAttachment(
+ GENERIC_KEY, invoker.getUrl().getParameter(GENERIC_KEY));
}
return invoker.invoke(invocation);
}
private void error(String generic, String expected, String actual) throws RpcException {
- throw new RpcException(
- "Generic serialization [" +
- generic +
- "] only support message type " +
- expected +
- " and your message type is " +
- actual);
+ throw new RpcException("Generic serialization [" + generic + "] only support message type " + expected + " and your message type is " + actual);
+ }
+
+ static class GenericImplListener implements Listener {
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ String generic = invoker.getUrl().getParameter(GENERIC_KEY);
+ String methodName = invocation.getMethodName();
+ Class>[] parameterTypes = invocation.getParameterTypes();
+ if (ProtocolUtils.isGeneric(generic)
+ && (!$INVOKE.equals(invocation.getMethodName()) && !$INVOKE_ASYNC.equals(invocation.getMethodName()))
+ && invocation instanceof RpcInvocation) {
+ if (!appResponse.hasException()) {
+ Object value = appResponse.getValue();
+ try {
+ Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
+ if (ProtocolUtils.isBeanGenericSerialization(generic)) {
+ if (value == null) {
+ appResponse.setValue(value);
+ } else if (value instanceof JavaBeanDescriptor) {
+ appResponse.setValue(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) value));
+ } else {
+ throw new RpcException("The type of result value is " + value.getClass().getName() + " other than " + JavaBeanDescriptor.class.getName() + ", and the result is " + value);
+ }
+ } else {
+ Type[] types = ReflectUtils.getReturnTypes(method);
+ appResponse.setValue(PojoUtils.realize(value, (Class>) types[0], types[1]));
+ }
+ } catch (NoSuchMethodException e) {
+ throw new RpcException(e.getMessage(), e);
+ }
+ } else if (appResponse.getException() instanceof GenericException) {
+ GenericException exception = (GenericException) appResponse.getException();
+ try {
+ String className = exception.getExceptionClass();
+ Class> clazz = ReflectUtils.forName(className);
+ Throwable targetException = null;
+ Throwable lastException = null;
+ try {
+ targetException = (Throwable) clazz.newInstance();
+ } catch (Throwable e) {
+ lastException = e;
+ for (Constructor> constructor : clazz.getConstructors()) {
+ try {
+ targetException = (Throwable) constructor.newInstance(new Object[constructor.getParameterTypes().length]);
+ break;
+ } catch (Throwable e1) {
+ lastException = e1;
+ }
+ }
+ }
+ if (targetException != null) {
+ try {
+ Field field = Throwable.class.getDeclaredField("detailMessage");
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ field.set(targetException, exception.getExceptionMessage());
+ } catch (Throwable e) {
+ logger.warn(e.getMessage(), e);
+ }
+ appResponse.setException(targetException);
+ } else if (lastException != null) {
+ throw lastException;
+ }
+ } catch (Throwable e) {
+ throw new RpcException("Can not deserialize exception " + exception.getExceptionClass() + ", message: " + exception.getExceptionMessage(), e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TimeoutFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TimeoutFilter.java
index d0f7b572497..31b0dc977a8 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TimeoutFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TimeoutFilter.java
@@ -20,12 +20,11 @@
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcInvocation;
import java.util.Arrays;
@@ -33,42 +32,40 @@
* Log any invocation timeout, but don't stop server from running
*/
@Activate(group = CommonConstants.PROVIDER)
-public class TimeoutFilter implements Filter {
+public class TimeoutFilter extends ListenableFilter {
private static final Logger logger = LoggerFactory.getLogger(TimeoutFilter.class);
private static final String TIMEOUT_FILTER_START_TIME = "timeout_filter_start_time";
+ public TimeoutFilter() {
+ super.listener = new TimeoutListener();
+ }
+
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
- if (invocation.getAttachments() != null) {
- long start = System.currentTimeMillis();
- invocation.getAttachments().put(TIMEOUT_FILTER_START_TIME, String.valueOf(start));
- } else {
- if (invocation instanceof RpcInvocation) {
- RpcInvocation invc = (RpcInvocation) invocation;
- long start = System.currentTimeMillis();
- invc.setAttachment(TIMEOUT_FILTER_START_TIME, String.valueOf(start));
- }
- }
+ invocation.setAttachment(TIMEOUT_FILTER_START_TIME, String.valueOf(System.currentTimeMillis()));
return invoker.invoke(invocation);
}
- @Override
- public Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- String startAttach = invocation.getAttachment(TIMEOUT_FILTER_START_TIME);
- if (startAttach != null) {
- long elapsed = System.currentTimeMillis() - Long.valueOf(startAttach);
- if (invoker.getUrl() != null
- && elapsed > invoker.getUrl().getMethodParameter(invocation.getMethodName(),
- "timeout", Integer.MAX_VALUE)) {
- if (logger.isWarnEnabled()) {
- logger.warn("invoke time out. method: " + invocation.getMethodName()
- + " arguments: " + Arrays.toString(invocation.getArguments()) + " , url is "
- + invoker.getUrl() + ", invoke elapsed " + elapsed + " ms.");
+ static class TimeoutListener implements Listener {
+
+ @Override
+ public void onResponse(Result appResponse, Invoker> invoker, Invocation invocation) {
+ String startAttach = invocation.getAttachment(TIMEOUT_FILTER_START_TIME);
+ if (startAttach != null) {
+ long elapsed = System.currentTimeMillis() - Long.valueOf(startAttach);
+ if (invoker.getUrl() != null && elapsed > invoker.getUrl().getMethodParameter(invocation.getMethodName(), "timeout", Integer.MAX_VALUE)) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("invoke time out. method: " + invocation.getMethodName() + " arguments: " + Arrays.toString(invocation.getArguments()) + " , url is " + invoker.getUrl() + ", invoke elapsed " + elapsed + " ms.");
+ }
}
}
}
- return result;
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java
index e218fa25f09..58cb4105f86 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java
@@ -23,13 +23,13 @@
import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.lang.reflect.InvocationTargetException;
@@ -38,8 +38,6 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
-import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
-
/**
* AbstractInvoker.
*/
@@ -149,9 +147,8 @@ public Result invoke(Invocation inv) throws RpcException {
*/
invocation.addAttachments(contextAttachments);
}
- if (getUrl().getMethodParameter(invocation.getMethodName(), ASYNC_KEY, false)) {
- invocation.setAttachment(ASYNC_KEY, Boolean.TRUE.toString());
- }
+
+ invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
try {
@@ -159,21 +156,21 @@ public Result invoke(Invocation inv) throws RpcException {
} catch (InvocationTargetException e) { // biz exception
Throwable te = e.getTargetException();
if (te == null) {
- return new RpcResult(e);
+ return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
} else {
if (te instanceof RpcException) {
((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
}
- return new RpcResult(te);
+ return AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
}
} catch (RpcException e) {
if (e.isBiz()) {
- return new RpcResult(e);
+ return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
} else {
throw e;
}
} catch (Throwable e) {
- return new RpcResult(e);
+ return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java
index 5c49e473ddb..ceeb92e1803 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProtocol.java
@@ -24,6 +24,7 @@
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.support.ProtocolUtils;
import java.util.ArrayList;
@@ -84,4 +85,11 @@ public void destroy() {
}
}
}
+
+ @Override
+ public Invoker refer(Class type, URL url) throws RpcException {
+ return new AsyncToSyncInvoker<>(protocolBindingRefer(type, url));
+ }
+
+ protected abstract Invoker protocolBindingRefer(Class type, URL url) throws RpcException;
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java
index 735b9fe4b7f..d45f9e3951f 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractProxyProtocol.java
@@ -95,13 +95,14 @@ public void unexport() {
}
@Override
- public Invoker refer(final Class type, final URL url) throws RpcException {
+ protected Invoker protocolBindingRefer(final Class type, final URL url) throws RpcException {
final Invoker target = proxyFactory.getInvoker(doRefer(type, url), type, url);
Invoker invoker = new AbstractInvoker(type, url) {
@Override
protected Result doInvoke(Invocation invocation) throws Throwable {
try {
Result result = target.invoke(invocation);
+ // FIXME result is an AsyncRpcResult instance.
Throwable e = result.getException();
if (e != null) {
for (Class> rpcException : rpcExceptions) {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AsyncToSyncInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AsyncToSyncInvoker.java
new file mode 100644
index 00000000000..5c06b4e4d1d
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AsyncToSyncInvoker.java
@@ -0,0 +1,89 @@
+/*
+ * 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.dubbo.rpc.protocol;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.TimeoutException;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.InvokeMode;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * This class will work as a wrapper wrapping outside of each protocol invoker.
+ * @param
+ */
+public class AsyncToSyncInvoker implements Invoker {
+
+ private Invoker invoker;
+
+ public AsyncToSyncInvoker(Invoker invoker) {
+ this.invoker = invoker;
+ }
+
+ @Override
+ public Class getInterface() {
+ return invoker.getInterface();
+ }
+
+ @Override
+ public Result invoke(Invocation invocation) throws RpcException {
+ Result asyncResult = invoker.invoke(invocation);
+
+ try {
+ if (InvokeMode.SYNC == ((RpcInvocation)invocation).getInvokeMode()) {
+ asyncResult.get();
+ }
+ } catch (InterruptedException e) {
+ throw new RpcException("Interrupted unexpectedly while waiting for remoting result to return! method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
+ } catch (ExecutionException e) {
+ Throwable t = e.getCause();
+ if (t instanceof TimeoutException) {
+ throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
+ } else if (t instanceof RemotingException) {
+ throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
+ }
+ } catch (Throwable e) {
+ throw new RpcException(e.getMessage(), e);
+ }
+ return asyncResult;
+ }
+
+ @Override
+ public URL getUrl() {
+ return invoker.getUrl();
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return invoker.isAvailable();
+ }
+
+ @Override
+ public void destroy() {
+ invoker.destroy();
+ }
+
+ public Invoker getInvoker() {
+ return invoker;
+ }
+}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java
index f0039dbb7ab..9ee7d3e1f2b 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolFilterWrapper.java
@@ -19,11 +19,11 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
@@ -75,14 +75,31 @@ public boolean isAvailable() {
@Override
public Result invoke(Invocation invocation) throws RpcException {
- Result result = filter.invoke(next, invocation);
- if (result instanceof AsyncRpcResult) {
- AsyncRpcResult asyncResult = (AsyncRpcResult) result;
- asyncResult.thenApplyWithContext(r -> filter.onResponse(r, invoker, invocation));
- return asyncResult;
- } else {
- return filter.onResponse(result, invoker, invocation);
+ Result asyncResult;
+ try {
+ asyncResult = filter.invoke(next, invocation);
+ } catch (Exception e) {
+ // onError callback
+ if (filter instanceof ListenableFilter) {
+ Filter.Listener listener = ((ListenableFilter) filter).listener();
+ if (listener != null) {
+ listener.onError(e, invoker, invocation);
+ }
+ }
+ throw e;
}
+ return asyncResult.thenApplyWithContext(r -> {
+ // onResponse callback
+ if (filter instanceof ListenableFilter) {
+ Filter.Listener listener = ((ListenableFilter) filter).listener();
+ if (listener != null) {
+ listener.onResponse(r, invoker, invocation);
+ }
+ } else {
+ filter.onResponse(r, invoker, invocation);
+ }
+ return r;
+ });
}
@Override
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java
index 6a562d6f6fd..fe42fb2c6be 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyInvoker.java
@@ -19,6 +19,7 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.AsyncContextImpl;
import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
@@ -26,11 +27,11 @@
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
/**
* InvokerWrapper
@@ -78,30 +79,48 @@ public boolean isAvailable() {
public void destroy() {
}
- // TODO Unified to AsyncResult?
@Override
public Result invoke(Invocation invocation) throws RpcException {
- RpcContext rpcContext = RpcContext.getContext();
try {
- Object obj = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
- if (RpcUtils.isReturnTypeFuture(invocation)) {
- return new AsyncRpcResult((CompletableFuture) obj);
- } else if (rpcContext.isAsyncStarted()) { // ignore obj in case of RpcContext.startAsync()? always rely on user to write back.
- return new AsyncRpcResult(((AsyncContextImpl)(rpcContext.getAsyncContext())).getInternalFuture());
- } else {
- return new RpcResult(obj);
- }
+ Object value = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
+ CompletableFuture future = wrapWithFuture(value, invocation);
+ AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
+ future.whenComplete((obj, t) -> {
+ AppResponse result = new AppResponse();
+ if (t != null) {
+ if (t instanceof CompletionException) {
+ result.setException(t.getCause());
+ } else {
+ result.setException(t);
+ }
+ } else {
+ result.setValue(obj);
+ }
+ asyncRpcResult.complete(result);
+ });
+ return asyncRpcResult;
} catch (InvocationTargetException e) {
- // TODO async throw exception before async thread write back, should stop asyncContext
- if (rpcContext.isAsyncStarted() && !rpcContext.stopAsync()) {
+ if (RpcContext.getContext().isAsyncStarted() && !RpcContext.getContext().stopAsync()) {
logger.error("Provider async started, but got an exception from the original method, cannot write the exception back to consumer because an async result may have returned the new thread.", e);
}
- return new RpcResult(e.getTargetException());
+ return AsyncRpcResult.newDefaultAsyncResult(null, e.getTargetException(), invocation);
} catch (Throwable e) {
throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
+ private CompletableFuture wrapWithFuture (Object value, Invocation invocation) {
+ if (RpcContext.getContext().isAsyncStarted()) {
+ return ((AsyncContextImpl)(RpcContext.getContext().getAsyncContext())).getInternalFuture();
+ } else if (RpcUtils.isReturnTypeFuture(invocation)) {
+ if (value == null) {
+ return CompletableFuture.completedFuture(null);
+ }
+ return (CompletableFuture) value;
+ }
+ return CompletableFuture.completedFuture(value);
+ }
+
protected abstract Object doInvoke(T proxy, String methodName, Class>[] parameterTypes, Object[] arguments) throws Throwable;
@Override
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
index a76f081122c..1d047cdccf4 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
@@ -20,14 +20,10 @@
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.support.RpcUtils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
-import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
-import static org.apache.dubbo.rpc.Constants.FUTURE_RETURNTYPE_KEY;
-
/**
* InvokerHandler
*/
@@ -56,16 +52,6 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
return invoker.equals(args[0]);
}
- return invoker.invoke(createInvocation(method, args)).recreate();
+ return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
-
- private RpcInvocation createInvocation(Method method, Object[] args) {
- RpcInvocation invocation = new RpcInvocation(method, args);
- if (RpcUtils.hasFutureReturnType(method)) {
- invocation.setAttachment(FUTURE_RETURNTYPE_KEY, "true");
- invocation.setAttachment(ASYNC_KEY, "true");
- }
- return invocation;
- }
-
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/service/GenericService.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/service/GenericService.java
index 07517d474a4..d93fa14930a 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/service/GenericService.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/service/GenericService.java
@@ -16,6 +16,8 @@
*/
package org.apache.dubbo.rpc.service;
+import java.util.concurrent.CompletableFuture;
+
/**
* Generic service interface
*
@@ -35,4 +37,12 @@ public interface GenericService {
*/
Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;
+ default CompletableFuture $invokeAsync(String method, String[] parameterTypes, Object[] args) throws GenericException {
+ Object object = $invoke(method, parameterTypes, args);
+ if (object instanceof CompletableFuture) {
+ return (CompletableFuture) object;
+ }
+ return CompletableFuture.completedFuture(object);
+ }
+
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java
index 32fc5ae6324..e8f8209e69b 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java
@@ -18,18 +18,18 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.PojoUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.common.utils.ArrayUtils;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import com.alibaba.fastjson.JSON;
@@ -112,7 +112,7 @@ public Result invoke(Invocation invocation) throws RpcException {
try {
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
Object value = parseMockValue(mock, returnTypes);
- return new RpcResult(value);
+ return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
} catch (Exception ew) {
throw new RpcException("mock return invoke error. method :" + invocation.getMethodName()
+ ", mock:" + mock + ", url: " + url, ew);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java
index 9237ab955c0..46089968172 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java
@@ -38,7 +38,7 @@ public Exporter export(Invoker invoker) throws RpcException {
}
@Override
- public Invoker refer(Class type, URL url) throws RpcException {
+ public Invoker protocolBindingRefer(Class type, URL url) throws RpcException {
return new MockInvoker<>(url, type);
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
index 18e59ba4170..7bf4533100e 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java
@@ -22,23 +22,22 @@
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.InvokeMode;
import org.apache.dubbo.rpc.RpcInvocation;
import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.common.constants.RpcConstants.$INVOKE;
-import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY;
-import static org.apache.dubbo.rpc.Constants.ID_KEY;
+import static org.apache.dubbo.common.constants.RpcConstants.$INVOKE_ASYNC;
import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
+import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY;
import static org.apache.dubbo.rpc.Constants.FUTURE_GENERATED_KEY;
-import static org.apache.dubbo.rpc.Constants.FUTURE_RETURNTYPE_KEY;
+import static org.apache.dubbo.rpc.Constants.ID_KEY;
import static org.apache.dubbo.rpc.Constants.RETURN_KEY;
/**
* RpcUtils
@@ -71,7 +70,6 @@ public static Class> getReturnType(Invocation invocation) {
return null;
}
- // TODO why not get return type when initialize Invocation?
public static Type[] getReturnTypes(Invocation invocation) {
try {
if (invocation != null && invocation.getInvoker() != null
@@ -86,24 +84,7 @@ public static Type[] getReturnTypes(Invocation invocation) {
if (method.getReturnType() == void.class) {
return null;
}
- Class> returnType = method.getReturnType();
- Type genericReturnType = method.getGenericReturnType();
- if (Future.class.isAssignableFrom(returnType)) {
- if (genericReturnType instanceof ParameterizedType) {
- Type actualArgType = ((ParameterizedType) genericReturnType).getActualTypeArguments()[0];
- if (actualArgType instanceof ParameterizedType) {
- returnType = (Class>) ((ParameterizedType) actualArgType).getRawType();
- genericReturnType = actualArgType;
- } else {
- returnType = (Class>) actualArgType;
- genericReturnType = returnType;
- }
- } else {
- returnType = null;
- genericReturnType = null;
- }
- }
- return new Type[]{returnType, genericReturnType};
+ return ReflectUtils.getReturnTypes(method);
}
}
} catch (Throwable t) {
@@ -190,11 +171,22 @@ public static boolean isAsync(URL url, Invocation inv) {
}
public static boolean isReturnTypeFuture(Invocation inv) {
- return Boolean.TRUE.toString().equals(inv.getAttachment(FUTURE_RETURNTYPE_KEY));
+ Class> clazz = getReturnType(inv);
+ return (clazz != null && CompletableFuture.class.isAssignableFrom(clazz)) || isGenericAsync(inv);
+ }
+
+ public static InvokeMode getInvokeMode(URL url, Invocation inv) {
+ if (isReturnTypeFuture(inv)) {
+ return InvokeMode.FUTURE;
+ } else if (isAsync(url, inv)) {
+ return InvokeMode.ASYNC;
+ } else {
+ return InvokeMode.SYNC;
+ }
}
- public static boolean hasFutureReturnType(Method method) {
- return CompletableFuture.class.isAssignableFrom(method.getReturnType());
+ public static boolean isGenericAsync(Invocation inv) {
+ return $INVOKE_ASYNC.equals(inv.getMethodName());
}
public static boolean isOneway(URL url, Invocation inv) {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcResultTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java
similarity index 78%
rename from dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcResultTest.java
rename to dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java
index 9c983a544a5..2fcace07a9a 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/RpcResultTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java
@@ -20,13 +20,13 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-public class RpcResultTest {
+public class AppResponseTest {
@Test
- public void testRpcResultWithNormalException() {
+ public void testAppResponseWithNormalException() {
NullPointerException npe = new NullPointerException();
- RpcResult rpcResult = new RpcResult(npe);
+ AppResponse appResponse = new AppResponse(npe);
- StackTraceElement[] stackTrace = rpcResult.getException().getStackTrace();
+ StackTraceElement[] stackTrace = appResponse.getException().getStackTrace();
Assertions.assertNotNull(stackTrace);
Assertions.assertTrue(stackTrace.length > 1);
}
@@ -35,14 +35,14 @@ public void testRpcResultWithNormalException() {
* please run this test in Run mode
*/
@Test
- public void testRpcResultWithEmptyStackTraceException() {
+ public void testAppResponseWithEmptyStackTraceException() {
Throwable throwable = buildEmptyStackTraceException();
if (throwable == null) {
return;
}
- RpcResult rpcResult = new RpcResult(throwable);
+ AppResponse appResponse = new AppResponse(throwable);
- StackTraceElement[] stackTrace = rpcResult.getException().getStackTrace();
+ StackTraceElement[] stackTrace = appResponse.getException().getStackTrace();
Assertions.assertNotNull(stackTrace);
Assertions.assertTrue(stackTrace.length == 0);
}
@@ -50,10 +50,10 @@ public void testRpcResultWithEmptyStackTraceException() {
@Test
public void testSetExceptionWithNormalException() {
NullPointerException npe = new NullPointerException();
- RpcResult rpcResult = new RpcResult();
- rpcResult.setException(npe);
+ AppResponse appResponse = new AppResponse();
+ appResponse.setException(npe);
- StackTraceElement[] stackTrace = rpcResult.getException().getStackTrace();
+ StackTraceElement[] stackTrace = appResponse.getException().getStackTrace();
Assertions.assertNotNull(stackTrace);
Assertions.assertTrue(stackTrace.length > 1);
}
@@ -67,10 +67,10 @@ public void testSetExceptionWithEmptyStackTraceException() {
if (throwable == null) {
return;
}
- RpcResult rpcResult = new RpcResult();
- rpcResult.setException(throwable);
+ AppResponse appResponse = new AppResponse();
+ appResponse.setException(throwable);
- StackTraceElement[] stackTrace = rpcResult.getException().getStackTrace();
+ StackTraceElement[] stackTrace = appResponse.getException().getStackTrace();
Assertions.assertNotNull(stackTrace);
Assertions.assertTrue(stackTrace.length == 0);
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ActiveLimitFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ActiveLimitFilterTest.java
index 6d085f70617..9c749c983c5 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ActiveLimitFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ActiveLimitFilterTest.java
@@ -17,9 +17,9 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcStatus;
import org.apache.dubbo.rpc.support.BlockMyInvoker;
@@ -35,13 +35,14 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* ActiveLimitFilterTest.java
*/
public class ActiveLimitFilterTest {
- Filter activeLimitFilter = new ActiveLimitFilter();
+ ActiveLimitFilter activeLimitFilter = new ActiveLimitFilter();
@Test
public void testInvokeNoActives() {
@@ -97,7 +98,7 @@ public void run() {
}
@Test
- public void testInvokeTimeOut() {
+ public void testInvokeTimeOut() throws Exception {
int totalThread = 100;
int maxActives = 10;
long timeout = 1;
@@ -120,9 +121,14 @@ public void run() {
e.printStackTrace();
}
try {
- activeLimitFilter.invoke(invoker, invocation);
+ Result asyncResult = activeLimitFilter.invoke(invoker, invocation);
+ Result result = asyncResult.get();
+ activeLimitFilter.listener().onResponse(result, invoker, invocation);
} catch (RpcException expected) {
count.incrementAndGet();
+// activeLimitFilter.listener().onError(expected, invoker, invocation);
+ } catch (Exception e) {
+ fail();
}
} finally {
latchBlocking.countDown();
@@ -142,7 +148,7 @@ public void run() {
}
@Test
- public void testInvokeNotTimeOut() {
+ public void testInvokeNotTimeOut() throws Exception {
int totalThread = 100;
int maxActives = 10;
long timeout = 1000;
@@ -163,9 +169,14 @@ public void run() {
e.printStackTrace();
}
try {
- activeLimitFilter.invoke(invoker, invocation);
+ Result asyncResult = activeLimitFilter.invoke(invoker, invocation);
+ Result result = asyncResult.get();
+ activeLimitFilter.listener().onResponse(result, invoker, invocation);
} catch (RpcException expected) {
count.incrementAndGet();
+ activeLimitFilter.listener().onError(expected, invoker, invocation);
+ } catch (Exception e) {
+ fail();
}
} finally {
latchBlocking.countDown();
@@ -208,6 +219,7 @@ public void testInvokeRuntimeExceptionWithActiveCountMatch() {
try {
activeLimitFilter.invoke(invoker, invocation);
} catch (RuntimeException ex) {
+ activeLimitFilter.listener().onError(ex, invoker, invocation);
int afterExceptionActiveCount = count.getActive();
assertEquals(beforeExceptionActiveCount, afterExceptionActiveCount, "After exception active count should be same");
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java
index b91c92d1640..709401d4278 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java
@@ -17,13 +17,14 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.DemoService;
import org.apache.dubbo.rpc.support.Type;
+
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@@ -37,7 +38,7 @@
* CompatibleFilterTest.java
*/
public class CompatibleFilterFilterTest {
- private Filter compatibleFilter = new CompatibleFilter();
+ private CompatibleFilter compatibleFilter = new CompatibleFilter();
private Invocation invocation;
private Invoker invoker;
@@ -56,7 +57,7 @@ public void testInvokerGeneric() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
@@ -76,7 +77,7 @@ public void testResulthasException() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setException(new RuntimeException());
result.setValue("High");
given(invoker.invoke(invocation)).willReturn(result);
@@ -88,7 +89,7 @@ public void testResulthasException() {
}
@Test
- public void testInvokerJsonPojoSerialization() {
+ public void testInvokerJsonPojoSerialization() throws Exception {
invocation = mock(Invocation.class);
given(invocation.getMethodName()).willReturn("enumlength");
given(invocation.getParameterTypes()).willReturn(new Class>[]{Type[].class});
@@ -97,18 +98,20 @@ public void testInvokerJsonPojoSerialization() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
- given(invoker.invoke(invocation)).willReturn(result);
+ given(invoker.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult(result, invocation));
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1&serialization=json");
given(invoker.getUrl()).willReturn(url);
- Result filterResult = compatibleFilter.invoke(invoker, invocation);
- assertEquals(Type.High, filterResult.getValue());
+ Result asyncResult = compatibleFilter.invoke(invoker, invocation);
+ AppResponse appResponse = (AppResponse) asyncResult.get();
+ compatibleFilter.listener().onResponse(appResponse, invoker, invocation);
+ assertEquals(Type.High, appResponse.getValue());
}
@Test
- public void testInvokerNonJsonEnumSerialization() {
+ public void testInvokerNonJsonEnumSerialization() throws Exception {
invocation = mock(Invocation.class);
given(invocation.getMethodName()).willReturn("enumlength");
given(invocation.getParameterTypes()).willReturn(new Class>[]{Type[].class});
@@ -117,14 +120,16 @@ public void testInvokerNonJsonEnumSerialization() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
- given(invoker.invoke(invocation)).willReturn(result);
+ given(invoker.invoke(invocation)).willReturn(AsyncRpcResult.newDefaultAsyncResult(result, invocation));
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
given(invoker.getUrl()).willReturn(url);
- Result filterResult = compatibleFilter.invoke(invoker, invocation);
- assertEquals(Type.High, filterResult.getValue());
+ Result asyncResult = compatibleFilter.invoke(invoker, invocation);
+ AppResponse appResponse = (AppResponse) asyncResult.get();
+ compatibleFilter.listener().onResponse(appResponse, invoker, invocation);
+ assertEquals(Type.High, appResponse.getValue());
}
@Test
@@ -137,7 +142,7 @@ public void testInvokerNonJsonNonPojoSerialization() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue(new String[]{"High"});
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
@@ -157,7 +162,7 @@ public void testInvokerNonJsonPojoSerialization() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("hello");
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ConsumerContextFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ConsumerContextFilterTest.java
index a906af47be2..93635528338 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ConsumerContextFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ConsumerContextFilterTest.java
@@ -21,6 +21,7 @@
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.support.DemoService;
import org.apache.dubbo.rpc.support.MockInvocation;
@@ -41,11 +42,13 @@ public void testSetContext() {
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
Invoker invoker = new MyInvoker(url);
Invocation invocation = new MockInvocation();
- consumerContextFilter.invoke(invoker, invocation);
- assertEquals(invoker, RpcContext.getContext().getInvoker());
- assertEquals(invocation, RpcContext.getContext().getInvocation());
- assertEquals(NetUtils.getLocalHost() + ":0", RpcContext.getContext().getLocalAddressString());
- assertEquals("test:11", RpcContext.getContext().getRemoteAddressString());
-
+ Result asyncResult = consumerContextFilter.invoke(invoker, invocation);
+ asyncResult.thenApplyWithContext(result -> {
+ assertEquals(invoker, RpcContext.getContext().getInvoker());
+ assertEquals(invocation, RpcContext.getContext().getInvocation());
+ assertEquals(NetUtils.getLocalHost() + ":0", RpcContext.getContext().getLocalAddressString());
+ assertEquals("test:11", RpcContext.getContext().getRemoteAddressString());
+ return result;
+ });
}
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
index c753c7e0e2e..506c10db5d5 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ContextFilterTest.java
@@ -17,12 +17,12 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.DemoService;
import org.apache.dubbo.rpc.support.MockInvocation;
import org.apache.dubbo.rpc.support.MyInvoker;
@@ -55,7 +55,7 @@ public void testSetContext() {
invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java
index 02f367b8a8e..3befdc77df9 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/EchoFilterTest.java
@@ -17,11 +17,11 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.DemoService;
import org.junit.jupiter.api.Test;
@@ -46,7 +46,7 @@ public void testEcho() {
Invoker invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
@@ -68,7 +68,7 @@ public void testNonEcho() {
Invoker invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java
index f40f8776e45..bc9c1320372 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExceptionFilterTest.java
@@ -17,13 +17,13 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.DemoService;
import org.apache.dubbo.rpc.support.LocalException;
@@ -51,18 +51,20 @@ public void testRpcException() {
RpcContext.getContext().setRemoteAddress("127.0.0.1", 1234);
RpcException exception = new RpcException("TestRpcException");
- ExceptionFilter exceptionFilter = new ExceptionFilter(logger);
+ ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class>[]{String.class}, new Object[]{"world"});
Invoker invoker = mock(Invoker.class);
given(invoker.getInterface()).willReturn(DemoService.class);
given(invoker.invoke(eq(invocation))).willThrow(exception);
-
try {
exceptionFilter.invoke(invoker, invocation);
} catch (RpcException e) {
assertEquals("TestRpcException", e.getMessage());
+ ((ExceptionFilter.ExceptionListener) exceptionFilter.listener()).setLogger(logger);
+ exceptionFilter.listener().onError(e, invoker, invocation);
}
+
Mockito.verify(logger).error(eq("Got unchecked and undeclared exception which called by 127.0.0.1. service: "
+ DemoService.class.getName() + ", method: sayHello, exception: "
+ RpcException.class.getName() + ": TestRpcException"), eq(exception));
@@ -76,16 +78,16 @@ public void testJavaException() {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class>[]{String.class}, new Object[]{"world"});
- RpcResult rpcResult = new RpcResult();
- rpcResult.setException(new IllegalArgumentException("java"));
+ AppResponse appResponse = new AppResponse();
+ appResponse.setException(new IllegalArgumentException("java"));
Invoker invoker = mock(Invoker.class);
- when(invoker.invoke(invocation)).thenReturn(rpcResult);
+ when(invoker.invoke(invocation)).thenReturn(appResponse);
when(invoker.getInterface()).thenReturn(DemoService.class);
Result newResult = exceptionFilter.invoke(invoker, invocation);
- Assertions.assertEquals(rpcResult.getException(), newResult.getException());
+ Assertions.assertEquals(appResponse.getException(), newResult.getException());
}
@@ -96,42 +98,43 @@ public void testRuntimeException() {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class>[]{String.class}, new Object[]{"world"});
- RpcResult rpcResult = new RpcResult();
- rpcResult.setException(new LocalException("localException"));
+ AppResponse appResponse = new AppResponse();
+ appResponse.setException(new LocalException("localException"));
Invoker invoker = mock(Invoker.class);
- when(invoker.invoke(invocation)).thenReturn(rpcResult);
+ when(invoker.invoke(invocation)).thenReturn(appResponse);
when(invoker.getInterface()).thenReturn(DemoService.class);
Result newResult = exceptionFilter.invoke(invoker, invocation);
- Assertions.assertEquals(rpcResult.getException(), newResult.getException());
+ Assertions.assertEquals(appResponse.getException(), newResult.getException());
}
@SuppressWarnings("unchecked")
@Test
- public void testConvertToRunTimeException() {
+ public void testConvertToRunTimeException() throws Exception {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class>[]{String.class}, new Object[]{"world"});
- RpcResult rpcResult = new RpcResult();
- rpcResult.setException(new HessianException("hessian"));
+ AppResponse mockRpcResult = new AppResponse();
+ mockRpcResult.setException(new HessianException("hessian"));
+ Result mockAsyncResult = AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation);
+
Invoker invoker = mock(Invoker.class);
- when(invoker.invoke(invocation)).thenReturn(rpcResult);
+ when(invoker.invoke(invocation)).thenReturn(mockAsyncResult);
when(invoker.getInterface()).thenReturn(DemoService.class);
- Result newResult = exceptionFilter.invoke(invoker, invocation);
-
- newResult = exceptionFilter.onResponse(newResult, invoker, invocation);
+ Result asyncResult = exceptionFilter.invoke(invoker, invocation);
- Assertions.assertFalse(newResult.getException() instanceof HessianException);
+ AppResponse appResponse = (AppResponse) asyncResult.get();
+ exceptionFilter.listener().onResponse(appResponse, invoker, invocation);
- Assertions.assertEquals(newResult.getException().getClass(), RuntimeException.class);
- Assertions.assertEquals(newResult.getException().getMessage(), StringUtils.toString(rpcResult.getException()));
+ Assertions.assertFalse(appResponse.getException() instanceof HessianException);
+ Assertions.assertEquals(appResponse.getException().getClass(), RuntimeException.class);
}
}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilterTest.java
index 2fab7894e32..4cbc280275d 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilterTest.java
@@ -17,11 +17,11 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.RpcStatus;
import org.apache.dubbo.rpc.support.BlockMyInvoker;
@@ -43,7 +43,7 @@ public class ExecuteLimitFilterTest {
@Test
public void testNoExecuteLimitInvoke() throws Exception {
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult("result"));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse("result"));
when(invoker.getUrl()).thenReturn(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1"));
Invocation invocation = Mockito.mock(Invocation.class);
@@ -56,7 +56,7 @@ public void testNoExecuteLimitInvoke() throws Exception {
@Test
public void testExecuteLimitInvoke() throws Exception {
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult("result"));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse("result"));
when(invoker.getUrl()).thenReturn(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&executes=10"));
Invocation invocation = Mockito.mock(Invocation.class);
@@ -82,6 +82,7 @@ public void testExecuteLimitInvokeWitException() throws Exception {
executeLimitFilter.invoke(invoker, invocation);
} catch (Exception e) {
Assertions.assertTrue(e instanceof RpcException);
+ executeLimitFilter.listener().onError(e, invoker, invocation);
}
Assertions.assertEquals(1, RpcStatus.getStatus(url, invocation.getMethodName()).getFailed());
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
index f7639f7f57f..46bc99ce9c4 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericFilterTest.java
@@ -17,7 +17,13 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.rpc.*;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.DemoService;
import org.apache.dubbo.rpc.support.Person;
@@ -54,14 +60,16 @@ public void testInvokeWithDefault() throws Exception {
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
"accesslog=true&group=dubbo&version=1.1");
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult(new Person("person", 10)));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(AsyncRpcResult.newDefaultAsyncResult(new Person("person", 10), invocation));
when(invoker.getUrl()).thenReturn(url);
when(invoker.getInterface()).thenReturn(DemoService.class);
- Result result = genericFilter.invoke(invoker, invocation);
+ Result asyncResult = genericFilter.invoke(invoker, invocation);
- Assertions.assertEquals(HashMap.class, result.getValue().getClass());
- Assertions.assertEquals(10, ((HashMap) result.getValue()).get("age"));
+ AppResponse appResponse = (AppResponse) asyncResult.get();
+ genericFilter.listener().onResponse(appResponse, invoker, invocation);
+ Assertions.assertEquals(HashMap.class, appResponse.getValue().getClass());
+ Assertions.assertEquals(10, ((HashMap) appResponse.getValue()).get("age"));
}
@@ -81,7 +89,7 @@ public void testInvokeWithJavaException() throws Exception {
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
"accesslog=true&group=dubbo&version=1.1");
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult(new Person("person", 10)));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10)));
when(invoker.getUrl()).thenReturn(url);
when(invoker.getInterface()).thenReturn(DemoService.class);
@@ -104,7 +112,7 @@ public void testInvokeWithJavaException() throws Exception {
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
"accesslog=true&group=dubbo&version=1.1");
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult(new Person("person", 10)));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10)));
when(invoker.getUrl()).thenReturn(url);
when(invoker.getInterface()).thenReturn(DemoService.class);
@@ -128,7 +136,7 @@ public void testInvokeWithMethodArgumentSizeIsNot3() {
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
"accesslog=true&group=dubbo&version=1.1");
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult(new Person("person", 10)));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10)));
when(invoker.getUrl()).thenReturn(url);
when(invoker.getInterface()).thenReturn(DemoService.class);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericImplFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericImplFilterTest.java
index 5adbdb728ab..73e0d82b6c0 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericImplFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/GenericImplFilterTest.java
@@ -17,11 +17,12 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.service.GenericException;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.DemoService;
@@ -60,11 +61,14 @@ public void testInvoke() throws Exception {
person.put("name", "dubbo");
person.put("age", 10);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult(person));
+ AppResponse mockRpcResult = new AppResponse(person);
+ when(invoker.invoke(any(Invocation.class))).thenReturn(AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation));
when(invoker.getUrl()).thenReturn(url);
when(invoker.getInterface()).thenReturn(DemoService.class);
- Result result = genericImplFilter.invoke(invoker, invocation);
+ Result asyncResult = genericImplFilter.invoke(invoker, invocation);
+ Result result = asyncResult.get();
+ genericImplFilter.listener().onResponse(result, invoker, invocation);
Assertions.assertEquals(Person.class, result.getValue().getClass());
Assertions.assertEquals(10, ((Person) result.getValue()).getAge());
@@ -80,12 +84,14 @@ public void testInvokeWithException() throws Exception {
"accesslog=true&group=dubbo&version=1.1&generic=true");
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(
- new RpcResult(new GenericException(new RuntimeException("failed"))));
+ AppResponse mockRpcResult = new AppResponse(new GenericException(new RuntimeException("failed")));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(AsyncRpcResult.newDefaultAsyncResult(mockRpcResult, invocation));
when(invoker.getUrl()).thenReturn(url);
when(invoker.getInterface()).thenReturn(DemoService.class);
- Result result = genericImplFilter.invoke(invoker, invocation);
+ Result asyncResult = genericImplFilter.invoke(invoker, invocation);
+ Result result = asyncResult.get();
+ genericImplFilter.listener().onResponse(result, invoker, invocation);
Assertions.assertEquals(RuntimeException.class, result.getException().getClass());
}
@@ -105,7 +111,7 @@ public void testInvokeWithException() throws Exception {
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
"accesslog=true&group=dubbo&version=1.1&generic=true");
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult(new Person("person", 10)));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse(new Person("person", 10)));
when(invoker.getUrl()).thenReturn(url);
genericImplFilter.invoke(invoker, invocation);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TimeoutFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TimeoutFilterTest.java
index f99a0f35480..be853653335 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TimeoutFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TimeoutFilterTest.java
@@ -17,10 +17,10 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.BlockMyInvoker;
import org.junit.jupiter.api.Assertions;
@@ -39,7 +39,7 @@ public void testInvokeWithoutTimeout() throws Exception {
int timeout = 3000;
Invoker invoker = Mockito.mock(Invoker.class);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult("result"));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse("result"));
when(invoker.getUrl()).thenReturn(URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&timeout=" + timeout));
Invocation invocation = Mockito.mock(Invocation.class);
@@ -60,7 +60,7 @@ public void testInvokeWithTimeout() throws Exception {
when(invocation.getMethodName()).thenReturn("testInvokeWithTimeout");
Result result = timeoutFilter.invoke(invoker, invocation);
- Assertions.assertEquals("alibaba", result.getValue());
+ Assertions.assertEquals("Dubbo", result.getValue());
}
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TokenFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TokenFilterTest.java
index 275ddabcdc6..839416fa9c9 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TokenFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/TokenFilterTest.java
@@ -17,11 +17,11 @@
package org.apache.dubbo.rpc.filter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -46,7 +46,7 @@ public void testInvokeWithToken() throws Exception {
Invoker invoker = Mockito.mock(Invoker.class);
URL url = URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&token=" + token);
when(invoker.getUrl()).thenReturn(url);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult("result"));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse("result"));
Map attachments = new HashMap();
attachments.put(TOKEN_KEY, token);
@@ -65,7 +65,7 @@ public void testInvokeWithWrongToken() throws Exception {
Invoker invoker = Mockito.mock(Invoker.class);
URL url = URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&token=" + token);
when(invoker.getUrl()).thenReturn(url);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult("result"));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse("result"));
Map attachments = new HashMap();
attachments.put(TOKEN_KEY, "wrongToken");
@@ -84,7 +84,7 @@ public void testInvokeWithoutToken() throws Exception {
Invoker invoker = Mockito.mock(Invoker.class);
URL url = URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&token=" + token);
when(invoker.getUrl()).thenReturn(url);
- when(invoker.invoke(any(Invocation.class))).thenReturn(new RpcResult("result"));
+ when(invoker.invoke(any(Invocation.class))).thenReturn(new AppResponse("result"));
Invocation invocation = Mockito.mock(Invocation.class);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java
index 28baacbf611..7fec8d49fdb 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/BlockMyInvoker.java
@@ -17,10 +17,11 @@
package org.apache.dubbo.rpc.support;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
public class BlockMyInvoker extends MyInvoker {
@@ -38,19 +39,18 @@ public BlockMyInvoker(URL url, boolean hasException, long blockTime) {
@Override
public Result invoke(Invocation invocation) throws RpcException {
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
if (hasException == false) {
try {
Thread.sleep(blockTime);
} catch (InterruptedException e) {
}
- result.setValue("alibaba");
- return result;
+ result.setValue("Dubbo");
} else {
result.setException(new RuntimeException("mocked exception"));
- return result;
}
+ return AsyncRpcResult.newDefaultAsyncResult(result, invocation);
}
public long getBlockTime() {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
index 44e330724c8..f28022dca38 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
@@ -57,6 +57,16 @@ public Map getAttachments() {
return attachments;
}
+ @Override
+ public void setAttachment(String key, String value) {
+
+ }
+
+ @Override
+ public void setAttachmentIfAbsent(String key, String value) {
+
+ }
+
public Invoker> getInvoker() {
return null;
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java
index eb944c9bc1a..57f1f1e6cc5 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java
@@ -17,11 +17,12 @@
package org.apache.dubbo.rpc.support;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
/**
* MockInvoker.java
@@ -58,15 +59,14 @@ public boolean isAvailable() {
}
public Result invoke(Invocation invocation) throws RpcException {
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
if (hasException == false) {
result.setValue("alibaba");
- return result;
} else {
result.setException(new RuntimeException("mocked exception"));
- return result;
}
+ return AsyncRpcResult.newDefaultAsyncResult(result, invocation);
}
@Override
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
index 7e26606bd99..0ebe357f780 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
@@ -30,6 +30,7 @@
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker;
import java.io.IOException;
import java.util.HashMap;
@@ -155,7 +156,7 @@ private static Object referOrDestroyCallbackService(Channel channel, URL url, Cl
if (!isInstancesOverLimit(channel, referurl, clazz.getName(), instid, true)) {
@SuppressWarnings("rawtypes")
Invoker> invoker = new ChannelWrappedInvoker(clazz, channel, referurl, String.valueOf(instid));
- proxy = PROXY_FACTORY.getProxy(invoker);
+ proxy = PROXY_FACTORY.getProxy(new AsyncToSyncInvoker<>(invoker));
channel.setAttribute(proxyCacheKey, proxy);
channel.setAttribute(invokerCacheKey, invoker);
increaseInstanceCount(channel, countkey);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java
index 54d74d3ef6c..101851240c0 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java
@@ -24,25 +24,27 @@
import org.apache.dubbo.remoting.exchange.ExchangeClient;
import org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeClient;
import org.apache.dubbo.remoting.transport.ClientDelegate;
+import org.apache.dubbo.rpc.AppResponse;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
+import org.apache.dubbo.rpc.support.RpcUtils;
import java.net.InetSocketAddress;
+import java.util.concurrent.CompletableFuture;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
import static org.apache.dubbo.remoting.Constants.SENT_KEY;
-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;
-import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;
/**
+ * Server push uses this Invoker to continuously push data to client.
* Wrap the existing invoker on the channel.
*/
class ChannelWrappedInvoker extends AbstractInvoker {
@@ -66,15 +68,20 @@ protected Result doInvoke(Invocation invocation) throws Throwable {
inv.setAttachment(CALLBACK_SERVICE_KEY, serviceKey);
try {
- if (getUrl().getMethodParameter(invocation.getMethodName(), ASYNC_KEY, false)) { // may have concurrency issue
+ if (RpcUtils.isOneway(getUrl(), inv)) { // may have concurrency issue
currentClient.send(inv, getUrl().getMethodParameter(invocation.getMethodName(), SENT_KEY, false));
- return new RpcResult();
- }
- int timeout = getUrl().getMethodParameter(invocation.getMethodName(), TIMEOUT_KEY, DEFAULT_TIMEOUT);
- if (timeout > 0) {
- return (Result) currentClient.request(inv, timeout).get();
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
- return (Result) currentClient.request(inv).get();
+ CompletableFuture responseFuture = currentClient.request(inv);
+ AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
+ responseFuture.whenComplete((appResponse, t) -> {
+ if (t != null) {
+ asyncRpcResult.completeExceptionally(t);
+ } else {
+ asyncRpcResult.complete((AppResponse) appResponse);
+ }
+ });
+ return asyncRpcResult;
}
} catch (RpcException e) {
throw e;
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
index 0edfdb8f3a3..9515a1ba51d 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
@@ -28,8 +28,8 @@
import org.apache.dubbo.remoting.Decodeable;
import org.apache.dubbo.remoting.exchange.Response;
import org.apache.dubbo.remoting.transport.CodecSupport;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.io.IOException;
@@ -38,7 +38,7 @@
import java.lang.reflect.Type;
import java.util.Map;
-public class DecodeableRpcResult extends RpcResult implements Codec, Decodeable {
+public class DecodeableRpcResult extends AppResponse implements Codec, Decodeable {
private static final Logger log = LoggerFactory.getLogger(DecodeableRpcResult.class);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java
index fab4dd82b9c..1b1cd1414fd 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java
@@ -23,8 +23,8 @@
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.remoting.exchange.Response;
import org.apache.dubbo.remoting.exchange.support.MultiMessage;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import java.io.IOException;
@@ -76,7 +76,7 @@ private void logMessageLength(Object result, int bytes) {
}
} else if (result instanceof Response) {
try {
- ((RpcResult) ((Response) result).getResult()).setAttachment(OUTPUT_KEY, String.valueOf(bytes));
+ ((AppResponse) ((Response) result).getResult()).setAttachment(OUTPUT_KEY, String.valueOf(bytes));
} catch (Throwable e) {
/* ignore */
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
index cc0b9e7e225..f40b664e160 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
@@ -23,7 +23,7 @@
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.TimeoutException;
import org.apache.dubbo.remoting.exchange.ExchangeClient;
-import org.apache.dubbo.remoting.exchange.ResponseFuture;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
@@ -31,12 +31,11 @@
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
-import org.apache.dubbo.rpc.SimpleAsyncRpcResult;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
@@ -88,32 +87,25 @@ protected Result doInvoke(final Invocation invocation) throws Throwable {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
- boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
- boolean isAsyncFuture = RpcUtils.isReturnTypeFuture(inv);
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
int timeout = getUrl().getMethodParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
if (isOneway) {
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
currentClient.send(inv, isSent);
RpcContext.getContext().setFuture(null);
- return new RpcResult();
- } else if (isAsync) {
- ResponseFuture future = currentClient.request(inv, timeout);
- // For compatibility
- FutureAdapter futureAdapter = new FutureAdapter<>(future);
- RpcContext.getContext().setFuture(futureAdapter);
-
- Result result;
- if (isAsyncFuture) {
- // register resultCallback, sometimes we need the async result being processed by the filter chain.
- result = new AsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
- } else {
- result = new SimpleAsyncRpcResult(futureAdapter, futureAdapter.getResultFuture(), false);
- }
- return result;
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
- RpcContext.getContext().setFuture(null);
- return (Result) currentClient.request(inv, timeout).get();
+ AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
+ CompletableFuture responseFuture = currentClient.request(inv, timeout);
+ responseFuture.whenComplete((obj, t) -> {
+ if (t != null) {
+ asyncRpcResult.completeExceptionally(t);
+ } else {
+ asyncRpcResult.complete((AppResponse) obj);
+ }
+ });
+ RpcContext.getContext().setFuture(new FutureAdapter(asyncRpcResult));
+ return asyncRpcResult;
}
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index f1a627d8c7a..7f9281cc5da 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -36,7 +36,6 @@
import org.apache.dubbo.remoting.exchange.ExchangeServer;
import org.apache.dubbo.remoting.exchange.Exchangers;
import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;
-import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
@@ -57,6 +56,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
@@ -148,16 +148,9 @@ public CompletableFuture reply(ExchangeChannel channel, Object message)
return null;
}
}
- RpcContext rpcContext = RpcContext.getContext();
- rpcContext.setRemoteAddress(channel.getRemoteAddress());
+ RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
Result result = invoker.invoke(inv);
-
- if (result instanceof AsyncRpcResult) {
- return ((AsyncRpcResult) result).getResultFuture().thenApply(r -> (Object) r);
-
- } else {
- return CompletableFuture.completedFuture(result);
- }
+ return result.completionFuture().thenApply(Function.identity());
}
@Override
@@ -407,7 +400,7 @@ private void optimizeSerialization(URL url) throws RpcException {
}
@Override
- public Invoker refer(Class serviceType, URL url) throws RpcException {
+ public Invoker protocolBindingRefer(Class serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// create rpc invoker.
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/FutureAdapter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/FutureAdapter.java
index 28645410d42..03954d1b345 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/FutureAdapter.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/FutureAdapter.java
@@ -16,12 +16,11 @@
*/
package org.apache.dubbo.rpc.protocol.dubbo;
-import org.apache.dubbo.remoting.exchange.ResponseCallback;
-import org.apache.dubbo.remoting.exchange.ResponseFuture;
-import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.RpcException;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -31,45 +30,35 @@
*/
public class FutureAdapter extends CompletableFuture {
- private final ResponseFuture future;
- private CompletableFuture resultFuture;
+ private CompletableFuture appResponseFuture;
- public FutureAdapter(ResponseFuture future) {
- this.future = future;
- this.resultFuture = new CompletableFuture<>();
- future.setCallback(new ResponseCallback() {
- @Override
- public void done(Object response) {
- Result result = (Result) response;
- FutureAdapter.this.resultFuture.complete(result);
- V value = null;
- try {
- value = (V) result.recreate();
- } catch (Throwable t) {
- FutureAdapter.this.completeExceptionally(t);
+ public FutureAdapter(CompletableFuture future) {
+ this.appResponseFuture = future;
+ future.whenComplete((appResponse, t) -> {
+ if (t != null) {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ this.completeExceptionally(t);
+ } else {
+ if (appResponse.hasException()) {
+ this.completeExceptionally(appResponse.getException());
+ } else {
+ this.complete((V) appResponse.getValue());
}
- FutureAdapter.this.complete(value);
- }
-
- @Override
- public void caught(Throwable exception) {
- FutureAdapter.this.completeExceptionally(exception);
}
});
}
- public ResponseFuture getFuture() {
- return future;
- }
-
+ // TODO figure out the meaning of cancel in DefaultFuture.
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
- return false;
+ return appResponseFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
- return false;
+ return appResponseFuture.isCancelled();
}
@Override
@@ -101,15 +90,4 @@ public V get(long timeout, TimeUnit unit) throws InterruptedException, Execution
}
}
- /**
- * FIXME
- * This method has no need open to the the end user.
- * Mostly user use RpcContext.getFuture() to refer the instance of this class, so the user will get a CompletableFuture, this method will rarely be noticed.
- *
- * @return
- */
- public CompletableFuture getResultFuture() {
- return resultFuture;
- }
-
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
index eadbf20681a..a495775d111 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java
@@ -26,9 +26,9 @@
import org.apache.dubbo.remoting.exchange.ExchangeClient;
import org.apache.dubbo.remoting.exchange.ExchangeHandler;
import org.apache.dubbo.remoting.exchange.Exchangers;
-import org.apache.dubbo.remoting.exchange.ResponseFuture;
import java.net.InetSocketAddress;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -87,7 +87,7 @@ private void initClient() throws RemotingException {
}
@Override
- public ResponseFuture request(Object request) throws RemotingException {
+ public CompletableFuture request(Object request) throws RemotingException {
warning();
initClient();
return client.request(request);
@@ -108,7 +108,7 @@ public InetSocketAddress getRemoteAddress() {
}
@Override
- public ResponseFuture request(Object request, int timeout) throws RemotingException {
+ public CompletableFuture request(Object request, int timeout) throws RemotingException {
warning();
initClient();
return client.request(request, timeout);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java
index fd32951b320..c7074aa9dbe 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java
@@ -24,9 +24,9 @@
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.exchange.ExchangeClient;
import org.apache.dubbo.remoting.exchange.ExchangeHandler;
-import org.apache.dubbo.remoting.exchange.ResponseFuture;
import java.net.InetSocketAddress;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.dubbo.remoting.Constants.RECONNECT_KEY;
@@ -56,7 +56,7 @@ public void reset(URL url) {
}
@Override
- public ResponseFuture request(Object request) throws RemotingException {
+ public CompletableFuture request(Object request) throws RemotingException {
return client.request(request);
}
@@ -76,7 +76,7 @@ public ChannelHandler getChannelHandler() {
}
@Override
- public ResponseFuture request(Object request, int timeout) throws RemotingException {
+ public CompletableFuture request(Object request, int timeout) throws RemotingException {
return client.request(request, timeout);
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
index a64dc2b66e7..7b1c17c7517 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
@@ -20,10 +20,9 @@
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.rpc.AsyncRpcResult;
-import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -39,10 +38,14 @@
* EventFilter
*/
@Activate(group = CommonConstants.CONSUMER)
-public class FutureFilter implements Filter {
+public class FutureFilter extends ListenableFilter {
protected static final Logger logger = LoggerFactory.getLogger(FutureFilter.class);
+ public FutureFilter() {
+ super.listener = new FutureListener();
+ }
+
@Override
public Result invoke(final Invoker> invoker, final Invocation invocation) throws RpcException {
fireInvokeCallback(invoker, invocation);
@@ -51,37 +54,6 @@ public Result invoke(final Invoker> invoker, final Invocation invocation) thro
return invoker.invoke(invocation);
}
- @Override
- public Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- if (result instanceof AsyncRpcResult) {
- AsyncRpcResult asyncResult = (AsyncRpcResult) result;
- asyncResult.thenApplyWithContext(r -> {
- asyncCallback(invoker, invocation, r);
- return r;
- });
- return asyncResult;
- } else {
- syncCallback(invoker, invocation, result);
- return result;
- }
- }
-
- private void syncCallback(final Invoker> invoker, final Invocation invocation, final Result result) {
- if (result.hasException()) {
- fireThrowCallback(invoker, invocation, result.getException());
- } else {
- fireReturnCallback(invoker, invocation, result.getValue());
- }
- }
-
- private void asyncCallback(final Invoker> invoker, final Invocation invocation, Result result) {
- if (result.hasException()) {
- fireThrowCallback(invoker, invocation, result.getException());
- } else {
- fireReturnCallback(invoker, invocation, result.getValue());
- }
- }
-
private void fireInvokeCallback(final Invoker> invoker, final Invocation invocation) {
final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
if (asyncMethodInfo == null) {
@@ -226,4 +198,20 @@ private ConsumerMethodModel.AsyncMethodInfo getAsyncMethodInfo(Invoker> invoke
return asyncMethodInfo;
}
+
+ class FutureListener implements Listener {
+ @Override
+ public void onResponse(Result result, Invoker> invoker, Invocation invocation) {
+ if (result.hasException()) {
+ fireThrowCallback(invoker, invocation, result.getException());
+ } else {
+ fireReturnCallback(invoker, invocation, result.getValue());
+ }
+ }
+
+ @Override
+ public void onError(Throwable t, Invoker> invoker, Invocation invocation) {
+
+ }
+ }
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
index 56fe5b8e564..3998026b70b 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.protocol.dubbo.telnet;
-import com.alibaba.fastjson.JSON;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
@@ -24,11 +23,13 @@
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.telnet.TelnetHandler;
import org.apache.dubbo.remoting.telnet.support.Help;
-import org.apache.dubbo.rpc.RpcResult;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ProviderMethodModel;
import org.apache.dubbo.rpc.model.ProviderModel;
+import com.alibaba.fastjson.JSON;
+
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
@@ -124,7 +125,7 @@ public String telnet(Channel channel, String message) {
Object[] array = realize(list.toArray(), invokeMethod.getParameterTypes(),
invokeMethod.getGenericParameterTypes());
long start = System.currentTimeMillis();
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
try {
Object o = invokeMethod.invoke(selectedProvider.getServiceInstance(), array);
result.setValue(o);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
index 804f05856b7..7c6a34c40bf 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
@@ -24,6 +24,7 @@
import org.apache.dubbo.remoting.exchange.ExchangeClient;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker;
import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
import org.junit.jupiter.api.AfterAll;
@@ -63,7 +64,7 @@ public void test_Normal_available() {
URL url = URL.valueOf("dubbo://127.0.0.1:20883/org.apache.dubbo.rpc.protocol.dubbo.IDemoService");
ProtocolUtils.export(new DemoServiceImpl(), IDemoService.class, url);
- DubboInvoker> invoker = (DubboInvoker>) protocol.refer(IDemoService.class, url);
+ DubboInvoker> invoker = (DubboInvoker>) protocol.protocolBindingRefer(IDemoService.class, url);
Assertions.assertEquals(true, invoker.isAvailable());
invoker.destroy();
Assertions.assertEquals(false, invoker.isAvailable());
@@ -74,7 +75,7 @@ public void test_Normal_ChannelReadOnly() throws Exception {
URL url = URL.valueOf("dubbo://127.0.0.1:20883/org.apache.dubbo.rpc.protocol.dubbo.IDemoService");
ProtocolUtils.export(new DemoServiceImpl(), IDemoService.class, url);
- DubboInvoker> invoker = (DubboInvoker>) protocol.refer(IDemoService.class, url);
+ DubboInvoker> invoker = (DubboInvoker>) protocol.protocolBindingRefer(IDemoService.class, url);
Assertions.assertEquals(true, invoker.isAvailable());
getClients(invoker)[0].setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
@@ -92,7 +93,7 @@ public void test_normal_channel_close_wait_gracefully() throws Exception {
Exporter exporter = ProtocolUtils.export(new DemoServiceImpl(), IDemoService.class, url);
Exporter exporter0 = ProtocolUtils.export(new DemoServiceImpl0(), IDemoService.class, url);
- DubboInvoker> invoker = (DubboInvoker>) protocol.refer(IDemoService.class, url);
+ DubboInvoker> invoker = (DubboInvoker>) protocol.protocolBindingRefer(IDemoService.class, url);
long start = System.currentTimeMillis();
@@ -114,7 +115,7 @@ public void test_NoInvokers() throws Exception {
URL url = URL.valueOf("dubbo://127.0.0.1:20883/org.apache.dubbo.rpc.protocol.dubbo.IDemoService?connections=1");
ProtocolUtils.export(new DemoServiceImpl(), IDemoService.class, url);
- DubboInvoker> invoker = (DubboInvoker>) protocol.refer(IDemoService.class, url);
+ DubboInvoker> invoker = (DubboInvoker>) protocol.protocolBindingRefer(IDemoService.class, url);
ExchangeClient[] clients = getClients(invoker);
clients[0].close();
@@ -127,11 +128,10 @@ public void test_Lazy_ChannelReadOnly() throws Exception {
URL url = URL.valueOf("dubbo://127.0.0.1:20883/org.apache.dubbo.rpc.protocol.dubbo.IDemoService?lazy=true&connections=1&timeout=10000");
ProtocolUtils.export(new DemoServiceImpl(), IDemoService.class, url);
- DubboInvoker> invoker = (DubboInvoker>) protocol.refer(IDemoService.class, url);
+ AsyncToSyncInvoker> invoker = (AsyncToSyncInvoker) protocol.refer(IDemoService.class, url);
Assertions.assertEquals(true, invoker.isAvailable());
-
try {
- getClients(invoker)[0].setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
+ getClients((DubboInvoker>) invoker.getInvoker())[0].setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
fail();
} catch (IllegalStateException e) {
@@ -141,7 +141,7 @@ public void test_Lazy_ChannelReadOnly() throws Exception {
Assertions.assertEquals("ok", service.get());
Assertions.assertEquals(true, invoker.isAvailable());
- getClients(invoker)[0].setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
+ getClients((DubboInvoker>) invoker.getInvoker())[0].setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
Assertions.assertEquals(false, invoker.isAvailable());
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java
index 2429b4b9580..500a95eeacb 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/FutureFilterTest.java
@@ -17,12 +17,12 @@
package org.apache.dubbo.rpc.protocol.dubbo;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter;
import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService;
@@ -57,7 +57,7 @@ public void testSyncCallback() {
Invoker invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setValue("High");
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
@@ -74,7 +74,7 @@ public void testSyncCallbackHasException() throws RpcException, Throwable {
Invoker invoker = mock(Invoker.class);
given(invoker.isAvailable()).willReturn(true);
given(invoker.getInterface()).willReturn(DemoService.class);
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setException(new RuntimeException());
given(invoker.invoke(invocation)).willReturn(result);
URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1&" + ON_THROW_METHOD_KEY + "=echo");
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java
index fd5979b7469..0a3a9d161b5 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java
@@ -236,7 +236,7 @@ public void test_Sync_NoFuture() throws Exception {
Person ret = demoProxy.get(requestId);
Assertions.assertEquals(requestId, ret.getId());
Future pFuture = RpcContext.getContext().getFuture();
- Assertions.assertEquals(null, pFuture);
+ Assertions.assertEquals(ret, pFuture.get());
destroyService();
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClientTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClientTest.java
index 1f01e658c45..ca5a306df43 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClientTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClientTest.java
@@ -25,7 +25,9 @@
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker;
import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
+
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -273,8 +275,7 @@ private ExchangeClient getInvokerClient(Invoker> invoker) {
}
private List getInvokerClientList(Invoker> invoker) {
- @SuppressWarnings("rawtypes")
- DubboInvoker dInvoker = (DubboInvoker) invoker;
+ @SuppressWarnings("rawtypes") DubboInvoker dInvoker = (DubboInvoker) ((AsyncToSyncInvoker) invoker).getInvoker();
try {
Field clientField = DubboInvoker.class.getDeclaredField("clients");
clientField.setAccessible(true);
diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java b/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java
index abbfe82dac6..7d621913928 100644
--- a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java
@@ -47,8 +47,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
+import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
import static org.apache.dubbo.common.constants.RpcConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocol.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocol.java
index cc273aafbe3..3e681b27117 100644
--- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmProtocol.java
@@ -93,7 +93,7 @@ public Exporter export(Invoker invoker) throws RpcException {
}
@Override
- public Invoker refer(Class serviceType, URL url) throws RpcException {
+ public Invoker protocolBindingRefer(Class serviceType, URL url) throws RpcException {
return new InjvmInvoker(serviceType, url, url.getServiceKey(), exporterMap);
}
diff --git a/dubbo-rpc/dubbo-rpc-memcached/src/main/java/org/apache/dubbo/rpc/protocol/memcached/MemcachedProtocol.java b/dubbo-rpc/dubbo-rpc-memcached/src/main/java/org/apache/dubbo/rpc/protocol/memcached/MemcachedProtocol.java
index 2633e961d85..b056a795ee9 100644
--- a/dubbo-rpc/dubbo-rpc-memcached/src/main/java/org/apache/dubbo/rpc/protocol/memcached/MemcachedProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-memcached/src/main/java/org/apache/dubbo/rpc/protocol/memcached/MemcachedProtocol.java
@@ -18,12 +18,12 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.RemotingConstants;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
import org.apache.dubbo.rpc.protocol.AbstractProtocol;
@@ -56,7 +56,7 @@ public Exporter export(final Invoker invoker) throws RpcException {
}
@Override
- public Invoker refer(final Class type, final URL url) throws RpcException {
+ public Invoker protocolBindingRefer(final Class type, final URL url) throws RpcException {
try {
String address = url.getAddress();
String backup = url.getParameter(RemotingConstants.BACKUP_KEY);
@@ -73,26 +73,26 @@ public Invoker refer(final Class type, final URL url) throws RpcExcept
@Override
protected Result doInvoke(Invocation invocation) throws Throwable {
try {
+ Object value = null;
if (get.equals(invocation.getMethodName())) {
if (invocation.getArguments().length != 1) {
throw new IllegalArgumentException("The memcached get method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
}
- return new RpcResult(memcachedClient.get(String.valueOf(invocation.getArguments()[0])));
+ value = memcachedClient.get(String.valueOf(invocation.getArguments()[0]));
} else if (set.equals(invocation.getMethodName())) {
if (invocation.getArguments().length != 2) {
throw new IllegalArgumentException("The memcached set method arguments mismatch, must be two arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
}
memcachedClient.set(String.valueOf(invocation.getArguments()[0]), expiry, invocation.getArguments()[1]);
- return new RpcResult();
} else if (delete.equals(invocation.getMethodName())) {
if (invocation.getArguments().length != 1) {
throw new IllegalArgumentException("The memcached delete method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
}
memcachedClient.delete(String.valueOf(invocation.getArguments()[0]));
- return new RpcResult();
} else {
throw new UnsupportedOperationException("Unsupported method " + invocation.getMethodName() + " in memcached service.");
}
+ return AsyncRpcResult.newDefaultAsyncResult(value, invocation);
} catch (Throwable t) {
RpcException re = new RpcException("Failed to invoke memcached service method. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url + ", cause: " + t.getMessage(), t);
if (t instanceof TimeoutException || t instanceof SocketTimeoutException) {
diff --git a/dubbo-rpc/dubbo-rpc-native-thrift/pom.xml b/dubbo-rpc/dubbo-rpc-native-thrift/pom.xml
index 524cd1a706b..bcc3cf9ec8a 100644
--- a/dubbo-rpc/dubbo-rpc-native-thrift/pom.xml
+++ b/dubbo-rpc/dubbo-rpc-native-thrift/pom.xml
@@ -28,7 +28,7 @@
false
-
+
org.apache.dubbo
diff --git a/dubbo-rpc/dubbo-rpc-native-thrift/src/main/java/org/apache/dubbo/rpc/protocol/nativethrift/ThriftProtocol.java b/dubbo-rpc/dubbo-rpc-native-thrift/src/main/java/org/apache/dubbo/rpc/protocol/nativethrift/ThriftProtocol.java
index c869c60337b..028d3cf42e2 100644
--- a/dubbo-rpc/dubbo-rpc-native-thrift/src/main/java/org/apache/dubbo/rpc/protocol/nativethrift/ThriftProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-native-thrift/src/main/java/org/apache/dubbo/rpc/protocol/nativethrift/ThriftProtocol.java
@@ -20,6 +20,7 @@
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
+
import org.apache.thrift.TException;
import org.apache.thrift.TMultiplexedProcessor;
import org.apache.thrift.TProcessor;
diff --git a/dubbo-rpc/dubbo-rpc-redis/src/main/java/org/apache/dubbo/rpc/protocol/redis/RedisProtocol.java b/dubbo-rpc/dubbo-rpc-redis/src/main/java/org/apache/dubbo/rpc/protocol/redis/RedisProtocol.java
index 2601a09b48f..b5081887c2c 100644
--- a/dubbo-rpc/dubbo-rpc-redis/src/main/java/org/apache/dubbo/rpc/protocol/redis/RedisProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-redis/src/main/java/org/apache/dubbo/rpc/protocol/redis/RedisProtocol.java
@@ -23,12 +23,12 @@
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
import org.apache.dubbo.rpc.protocol.AbstractProtocol;
@@ -71,7 +71,7 @@ private Serialization getSerialization(URL url) {
}
@Override
- public Invoker refer(final Class type, final URL url) throws RpcException {
+ protected Invoker protocolBindingRefer(final Class type, final URL url) throws RpcException {
try {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setTestOnBorrow(url.getParameter("test.on.borrow", true));
@@ -122,10 +122,10 @@ protected Result doInvoke(Invocation invocation) throws Throwable {
}
byte[] value = jedis.get(String.valueOf(invocation.getArguments()[0]).getBytes());
if (value == null) {
- return new RpcResult();
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
}
ObjectInput oin = getSerialization(url).deserialize(url, new ByteArrayInputStream(value));
- return new RpcResult(oin.readObject());
+ return AsyncRpcResult.newDefaultAsyncResult(oin.readObject(), invocation);
} else if (set.equals(invocation.getMethodName())) {
if (invocation.getArguments().length != 2) {
throw new IllegalArgumentException("The redis set method arguments mismatch, must be two arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
@@ -138,13 +138,13 @@ protected Result doInvoke(Invocation invocation) throws Throwable {
if (expiry > 1000) {
jedis.expire(key, expiry / 1000);
}
- return new RpcResult();
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else if (delete.equals(invocation.getMethodName())) {
if (invocation.getArguments().length != 1) {
throw new IllegalArgumentException("The redis delete method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url);
}
jedis.del(String.valueOf(invocation.getArguments()[0]).getBytes());
- return new RpcResult();
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
throw new UnsupportedOperationException("Unsupported method " + invocation.getMethodName() + " in redis service.");
}
diff --git a/dubbo-rpc/dubbo-rpc-rest/pom.xml b/dubbo-rpc/dubbo-rpc-rest/pom.xml
index c1d9e4e727b..b162030fd8d 100644
--- a/dubbo-rpc/dubbo-rpc-rest/pom.xml
+++ b/dubbo-rpc/dubbo-rpc-rest/pom.xml
@@ -91,22 +91,22 @@
io.swaggerswagger-annotations
-
-
- javax.ws.rs
- jsr311-api
-
-
+
+
+ javax.ws.rs
+ jsr311-api
+
+ io.swaggerswagger-jaxrs
-
-
- javax.ws.rs
- jsr311-api
-
-
+
+
+ javax.ws.rs
+ jsr311-api
+
+
diff --git a/dubbo-rpc/dubbo-rpc-rmi/src/main/java/org/apache/dubbo/rpc/protocol/rmi/RmiProtocol.java b/dubbo-rpc/dubbo-rpc-rmi/src/main/java/org/apache/dubbo/rpc/protocol/rmi/RmiProtocol.java
index cbf16872840..d570b2f01f4 100644
--- a/dubbo-rpc/dubbo-rpc-rmi/src/main/java/org/apache/dubbo/rpc/protocol/rmi/RmiProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-rmi/src/main/java/org/apache/dubbo/rpc/protocol/rmi/RmiProtocol.java
@@ -21,6 +21,7 @@
import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
+
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.remoting.rmi.RmiServiceExporter;
@@ -30,11 +31,11 @@
import java.net.SocketTimeoutException;
import java.rmi.RemoteException;
+import static org.apache.dubbo.common.Version.isRelease263OrHigher;
+import static org.apache.dubbo.common.Version.isRelease270OrHigher;
import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
import static org.apache.dubbo.common.constants.RpcConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
-import static org.apache.dubbo.common.Version.isRelease263OrHigher;
-import static org.apache.dubbo.common.Version.isRelease270OrHigher;
/**
* RmiProtocol.
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java
index e37fab6a68b..14c2947017a 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java
@@ -25,9 +25,9 @@
import org.apache.dubbo.remoting.buffer.ChannelBufferInputStream;
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.remoting.exchange.Response;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream;
import org.apache.thrift.TApplicationException;
@@ -287,7 +287,7 @@ private Object decode(TProtocol protocol)
throw new IOException(e.getMessage(), e);
}
- RpcResult result = new RpcResult();
+ AppResponse result = new AppResponse();
result.setException(new RpcException(exception.getMessage()));
@@ -378,15 +378,15 @@ private Object decode(TProtocol protocol)
response.setId(id);
- RpcResult rpcResult = new RpcResult();
+ AppResponse appResponse = new AppResponse();
if (realResult instanceof Throwable) {
- rpcResult.setException((Throwable) realResult);
+ appResponse.setException((Throwable) realResult);
} else {
- rpcResult.setValue(realResult);
+ appResponse.setValue(realResult);
}
- response.setResult(rpcResult);
+ response.setResult(appResponse);
return response;
@@ -539,7 +539,7 @@ private void encodeRequest(Channel channel, ChannelBuffer buffer, Request reques
private void encodeResponse(Channel channel, ChannelBuffer buffer, Response response)
throws IOException {
- RpcResult result = (RpcResult) response.getResult();
+ AppResponse result = (AppResponse) response.getResult();
RequestData rd = CACHED_REQUEST.get(response.getId());
@@ -613,7 +613,7 @@ private void encodeResponse(Channel channel, ChannelBuffer buffer, Response resp
}
} else {
- Object realResult = result.getResult();
+ Object realResult = result.getValue();
// result field id is 0
String fieldName = resultObj.fieldForId(0).getFieldName();
String setMethodName = ThriftUtils.generateSetMethodName(fieldName);
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java
index 7d29f5813af..3b0e3d9352f 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java
@@ -22,6 +22,7 @@
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.TimeoutException;
import org.apache.dubbo.remoting.exchange.ExchangeClient;
+import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
@@ -29,8 +30,10 @@
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
+import org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
@@ -91,10 +94,11 @@ protected Result doInvoke(Invocation invocation) throws Throwable {
try {
int timeout = getUrl().getMethodParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
- RpcContext.getContext().setFuture(null);
-
- return (Result) currentClient.request(inv, timeout).get();
-
+ AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
+ CompletableFuture responseFuture = currentClient.request(inv, timeout);
+ asyncRpcResult.subscribeTo(responseFuture);
+ RpcContext.getContext().setFuture(new FutureAdapter(asyncRpcResult));
+ return asyncRpcResult;
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, e.getMessage(), e);
} catch (RemotingException e) {
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
index 0da5ee8be6f..d6a88cbe4e4 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftProtocol.java
@@ -32,6 +32,7 @@
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.protocol.AbstractProtocol;
@@ -42,10 +43,11 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
-import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;
import static org.apache.dubbo.common.constants.RpcConstants.CONNECTIONS_KEY;
+import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;
/**
* @since 2.7.0, use https://github.com/dubbo/dubbo-rpc-native-thrift instead
@@ -88,8 +90,8 @@ public CompletableFuture reply(ExchangeChannel channel, Object msg) thro
RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
- return CompletableFuture.completedFuture(exporter.getInvoker().invoke(inv));
-
+ Result result = exporter.getInvoker().invoke(inv);
+ return result.completionFuture().thenApply(Function.identity());
}
throw new RemotingException(channel,
@@ -162,7 +164,7 @@ public void destroy() {
} // ~ end of method destroy
@Override
- public Invoker refer(Class type, URL url) throws RpcException {
+ protected Invoker protocolBindingRefer(Class type, URL url) throws RpcException {
ThriftInvoker invoker = new ThriftInvoker(type, url, getClients(url), invokers);
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/test/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodecTest.java b/dubbo-rpc/dubbo-rpc-thrift/src/test/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodecTest.java
index 93421c4bcfb..8cdbae7f99e 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/test/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodecTest.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/test/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodecTest.java
@@ -23,9 +23,9 @@
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.remoting.exchange.Response;
import org.apache.dubbo.remoting.exchange.support.DefaultFuture;
+import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
-import org.apache.dubbo.rpc.RpcResult;
import org.apache.dubbo.rpc.gen.thrift.Demo;
import org.apache.dubbo.rpc.protocol.thrift.io.RandomAccessByteArrayOutputStream;
@@ -189,13 +189,13 @@ public void testDecodeReplyResponse() throws Exception {
Assertions.assertEquals(request.getId(), response.getId());
- Assertions.assertTrue(response.getResult() instanceof RpcResult);
+ Assertions.assertTrue(response.getResult() instanceof AppResponse);
- RpcResult result = (RpcResult) response.getResult();
+ AppResponse result = (AppResponse) response.getResult();
- Assertions.assertTrue(result.getResult() instanceof String);
+ Assertions.assertTrue(result.getValue() instanceof String);
- Assertions.assertEquals(methodResult.success, result.getResult());
+ Assertions.assertEquals(methodResult.success, result.getValue());
}
@@ -259,9 +259,9 @@ public void testDecodeExceptionResponse() throws Exception {
Response response = (Response) obj;
- Assertions.assertTrue(response.getResult() instanceof RpcResult);
+ Assertions.assertTrue(response.getResult() instanceof AppResponse);
- RpcResult result = (RpcResult) response.getResult();
+ AppResponse result = (AppResponse) response.getResult();
Assertions.assertTrue(result.hasException());
@@ -278,11 +278,11 @@ public void testEncodeReplyResponse() throws Exception {
Request request = createRequest();
- RpcResult rpcResult = new RpcResult();
- rpcResult.setResult("Hello, World!");
+ AppResponse appResponse = new AppResponse();
+ appResponse.setValue("Hello, World!");
Response response = new Response();
- response.setResult(rpcResult);
+ response.setResult(appResponse);
response.setId(request.getId());
ChannelBuffer bos = ChannelBuffers.dynamicBuffer(1024);
@@ -324,7 +324,7 @@ public void testEncodeReplyResponse() throws Exception {
result.read(protocol);
protocol.readMessageEnd();
- Assertions.assertEquals(rpcResult.getValue(), result.getSuccess());
+ Assertions.assertEquals(appResponse.getValue(), result.getSuccess());
}
@Test
@@ -336,12 +336,12 @@ public void testEncodeExceptionResponse() throws Exception {
Request request = createRequest();
- RpcResult rpcResult = new RpcResult();
+ AppResponse appResponse = new AppResponse();
String exceptionMessage = "failed";
- rpcResult.setException(new RuntimeException(exceptionMessage));
+ appResponse.setException(new RuntimeException(exceptionMessage));
Response response = new Response();
- response.setResult(rpcResult);
+ response.setResult(appResponse);
response.setId(request.getId());
ChannelBuffer bos = ChannelBuffers.dynamicBuffer(1024);
diff --git a/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java b/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
index c62bd8c85b8..68927d7bd1f 100644
--- a/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
@@ -16,16 +16,6 @@
*/
package org.apache.dubbo.xml.rpc.protocol.xmlrpc;
-import java.io.IOException;
-import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import org.apache.dubbo.common.URL;
import org.apache.dubbo.remoting.http.HttpBinder;
import org.apache.dubbo.remoting.http.HttpHandler;
@@ -33,6 +23,7 @@
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
+
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.server.PropertyHandlerMapping;
@@ -41,6 +32,15 @@
import org.apache.xmlrpc.webserver.XmlRpcServletServer;
import org.springframework.remoting.RemoteAccessException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
public class XmlRpcProtocol extends AbstractProxyProtocol {
public static final String ACCESS_CONTROL_ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin";