From 1f526682a3b428bf642d17c7bfbff0447a75ee92 Mon Sep 17 00:00:00 2001
From: "ken.lj"
Date: Fri, 12 Apr 2019 10:29:30 +0800
Subject: [PATCH] Async optimization (#3738)
* Result implement CF
* Result implement CF
* Result implement CF
* Add AsyncRpcResult
* Fix bugs and refactor Filter
* Try to add onSend onError for Filter
* invoke different filter method according to result status.
* make generic work with async call, including add $invokeAsync
* refactor legacy Filter implementation to work with onResponse.
* demo changes
* Fixes #3620, provider attachment lose on consumer side, fix this by reverting RpcContext copy
* AsyncRpcResult should always holds an Invocation instance
* refactor filter signature
* reimplement embedded Filters
* use ProviderModel modification in 3.x
* Fix address notification processing workflow after merging 3.x branch
* Fix UT
* Fix UT
* Unit test of JValidator; Clean code of JValidator (#3723)
* Fixes #3625 (#3730)
use constant to replace magic number
* Fix conflict when merging master and 3.x
* Fix conflict when merging master and 3.x
* Result interface itself has Future status.
* Fix DefaultFuture UT
* Wrap all protocol Invoker with AsyncToSyncInvoker & Fix UT
* Add license
* fix UT
* Fix ut in MonitorFilterTest
* avoid duplicate async to sync wrapper
* return async result in CacheFilter.
* fix UT in CacheFilterTest
* Add generic condition check to GenericFilter callback.
* Fix UT
* Get generic from RpcContext if the value in Invocation is empty.
* Fix RSocketProtocol to meet AbstractProtocol adjustment
* rename RpcResult to AppResponse to help avoid confusion with AsyncRpcResult.
* RSocket module switch to AsyncRpcResult
---
.../support/FailbackClusterInvoker.java | 4 +-
.../support/FailsafeClusterInvoker.java | 4 +-
.../support/ForkingClusterInvoker.java | 3 +-
.../support/MergeableClusterInvoker.java | 32 ++-
.../support/wrapper/MockClusterInvoker.java | 4 +-
.../apache/dubbo/rpc/cluster/StickyTest.java | 4 +-
.../cluster/directory/MockDirInvocation.java | 10 +
.../router/file/FileRouterEngineTest.java | 4 +-
.../support/FailSafeClusterInvokerTest.java | 4 +-
.../support/FailbackClusterInvokerTest.java | 4 +-
.../support/FailfastClusterInvokerTest.java | 4 +-
.../support/FailoverClusterInvokerTest.java | 4 +-
.../support/ForkingClusterInvokerTest.java | 6 +-
.../support/MergeableClusterInvokerTest.java | 11 +-
.../org/apache/dubbo/common/Constants.java | 7 +
.../apache/dubbo/common/logger/Logger.java | 2 +-
.../dubbo/common/utils/ReflectUtils.java | 23 ++
.../config/PropertiesConfigurationTest.java | 31 +++
.../com/alibaba/dubbo/rpc/Invocation.java | 9 +
.../java/com/alibaba/dubbo/rpc/Result.java | 36 +++-
.../apache/dubbo/filter/LegacyInvoker.java | 4 +-
.../apache/dubbo/service/MockInvocation.java | 10 +
.../consumer/comp/DemoServiceComponent.java | 7 +
.../dubbo/demo/provider/DemoServiceImpl.java | 7 +
.../dubbo/demo/provider/DemoServiceImpl.java | 7 +
.../org/apache/dubbo/demo/DemoService.java | 3 +
.../dubbo/demo/consumer/Application.java | 11 +-
.../main/resources/spring/dubbo-consumer.xml | 2 +-
.../dubbo/demo/provider/DemoServiceImpl.java | 12 ++
.../dubbo/cache/filter/CacheFilter.java | 6 +-
.../dubbo/cache/filter/CacheFilterTest.java | 31 +--
.../validation/filter/ValidationFilter.java | 4 +-
.../filter/ValidationFilterTest.java | 12 +-
.../apache/dubbo/monitor/MonitorService.java | 1 +
.../dubbo/monitor/support/MonitorFilter.java | 197 +++++++++--------
.../monitor/support/MonitorFilterTest.java | 16 +-
.../dubbo/registry/dubbo/MockChannel.java | 8 +-
.../dubbo/registry/dubbo/MockedClient.java | 18 +-
.../dubbo/remoting/RemotingException.java | 3 +-
.../dubbo/remoting/TimeoutException.java | 3 +-
.../remoting/exchange/ExchangeChannel.java | 6 +-
.../dubbo/remoting/exchange/Response.java | 61 ++++++
.../remoting/exchange/ResponseFuture.java | 58 -----
.../exchange/support/DefaultFuture.java | 196 ++++-------------
.../exchange/support/SimpleFuture.java | 54 -----
.../support/header/HeaderExchangeChannel.java | 6 +-
.../support/header/HeaderExchangeClient.java | 6 +-
.../support/header/HeaderExchangeHandler.java | 15 +-
.../java/org/apache/dubbo/remoting/Main.java | 4 +-
.../dubbo/remoting/PerformanceServerTest.java | 1 -
.../exchange/support/DefaultFutureTest.java | 4 +-
.../handler/HeaderExchangeHandlerTest.java | 2 +-
.../transport/mina/ClientToServerTest.java | 5 +-
.../support/header/HeartbeatHandlerTest.java | 1 +
.../transport/netty/ClientToServerTest.java | 6 +-
.../transport/netty4/ClientToServerTest.java | 5 +-
.../org/apache/dubbo/rpc/AbstractResult.java | 74 -------
.../org/apache/dubbo/rpc/AppResponse.java | 160 ++++++++++++++
.../org/apache/dubbo/rpc/AsyncRpcResult.java | 201 +++++++++---------
.../java/org/apache/dubbo/rpc/Filter.java | 31 +--
.../org/apache/dubbo/rpc/FutureContext.java | 52 +++++
.../java/org/apache/dubbo/rpc/Invocation.java | 4 +
.../java/org/apache/dubbo/rpc/InvokeMode.java | 23 ++
.../apache/dubbo/rpc/ListenableFilter.java | 67 +++---
.../java/org/apache/dubbo/rpc/Result.java | 23 +-
.../java/org/apache/dubbo/rpc/RpcContext.java | 35 +--
.../org/apache/dubbo/rpc/RpcInvocation.java | 21 ++
.../java/org/apache/dubbo/rpc/RpcResult.java | 128 -----------
.../dubbo/rpc/SimpleAsyncRpcResult.java | 50 -----
.../dubbo/rpc/filter/ActiveLimitFilter.java | 72 +++++--
.../dubbo/rpc/filter/CompatibleFilter.java | 70 +++---
.../rpc/filter/ConsumerContextFilter.java | 26 ++-
.../dubbo/rpc/filter/ContextFilter.java | 24 ++-
.../apache/dubbo/rpc/filter/EchoFilter.java | 4 +-
.../dubbo/rpc/filter/ExceptionFilter.java | 126 ++++++-----
.../dubbo/rpc/filter/ExecuteLimitFilter.java | 34 ++-
.../dubbo/rpc/filter/GenericFilter.java | 62 ++++--
.../dubbo/rpc/filter/GenericImplFilter.java | 176 ++++++++-------
.../dubbo/rpc/filter/TimeoutFilter.java | 49 ++---
.../dubbo/rpc/protocol/AbstractInvoker.java | 16 +-
.../dubbo/rpc/protocol/AbstractProtocol.java | 8 +
.../rpc/protocol/AbstractProxyProtocol.java | 7 +-
.../rpc/protocol/AsyncToSyncInvoker.java | 89 ++++++++
.../rpc/protocol/ProtocolFilterWrapper.java | 31 ++-
.../dubbo/rpc/proxy/AbstractProxyInvoker.java | 46 ++--
.../rpc/proxy/InvokerInvocationHandler.java | 14 +-
.../dubbo/rpc/service/GenericService.java | 10 +
.../apache/dubbo/rpc/support/MockInvoker.java | 6 +-
.../dubbo/rpc/support/MockProtocol.java | 2 +-
.../apache/dubbo/rpc/support/RpcUtils.java | 40 ++--
...pcResultTest.java => AppResponseTest.java} | 0
.../rpc/filter/ActiveLimitFilterTest.java | 24 ++-
.../filter/CompatibleFilterFilterTest.java | 39 ++--
.../rpc/filter/ConsumerContextFilterTest.java | 15 +-
.../dubbo/rpc/filter/ContextFilterTest.java | 4 +-
.../dubbo/rpc/filter/EchoFilterTest.java | 6 +-
.../dubbo/rpc/filter/ExceptionFilterTest.java | 37 ++--
.../rpc/filter/ExecuteLimitFilterTest.java | 7 +-
.../dubbo/rpc/filter/GenericFilterTest.java | 24 ++-
.../rpc/filter/GenericImplFilterTest.java | 21 +-
.../dubbo/rpc/filter/TimeoutFilterTest.java | 6 +-
.../dubbo/rpc/filter/TokenFilterTest.java | 8 +-
.../dubbo/rpc/support/BlockMyInvoker.java | 10 +-
.../dubbo/rpc/support/MockInvocation.java | 10 +
.../apache/dubbo/rpc/support/MyInvoker.java | 10 +-
.../protocol/dubbo/CallbackServiceCodec.java | 3 +-
.../protocol/dubbo/ChannelWrappedInvoker.java | 17 +-
.../protocol/dubbo/DecodeableRpcResult.java | 4 +-
.../rpc/protocol/dubbo/DubboCountCodec.java | 4 +-
.../rpc/protocol/dubbo/DubboInvoker.java | 28 +--
.../rpc/protocol/dubbo/DubboProtocol.java | 15 +-
.../rpc/protocol/dubbo/FutureAdapter.java | 56 ++---
.../dubbo/LazyConnectExchangeClient.java | 6 +-
.../dubbo/ReferenceCountExchangeClient.java | 6 +-
.../protocol/dubbo/filter/FutureFilter.java | 56 ++---
.../dubbo/telnet/InvokeTelnetHandler.java | 7 +-
.../dubbo/DubboInvokerAvilableTest.java | 20 +-
.../rpc/protocol/dubbo/FutureFilterTest.java | 6 +-
.../protocol/dubbo/ImplicitCallBackTest.java | 2 +-
.../ReferenceCountExchangeClientTest.java | 5 +-
.../rpc/protocol/hessian/HessianProtocol.java | 2 +-
.../dubbo/rpc/protocol/http/HttpProtocol.java | 4 +-
.../rpc/protocol/injvm/InjvmProtocol.java | 2 +-
.../protocol/memcached/MemcachedProtocol.java | 10 +-
.../rpc/protocol/redis/RedisProtocol.java | 12 +-
.../dubbo/rpc/protocol/rest/RestProtocol.java | 2 +-
.../dubbo/rpc/protocol/rmi/RmiProtocol.java | 3 +-
.../rpc/protocol/thrift/ThriftCodec.java | 10 +-
.../rpc/protocol/thrift/ThriftInvoker.java | 11 +-
.../rpc/protocol/thrift/ThriftProtocol.java | 9 +-
.../rpc/protocol/thrift/ThriftCodecTest.java | 20 +-
.../webservice/WebServiceProtocol.java | 2 +-
132 files changed, 1751 insertions(+), 1571 deletions(-)
create mode 100644 dubbo-common/src/test/java/org/apache/dubbo/common/config/PropertiesConfigurationTest.java
delete mode 100644 dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ResponseFuture.java
delete mode 100644 dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/SimpleFuture.java
delete mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AbstractResult.java
create mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AppResponse.java
create mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/FutureContext.java
create mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java
rename dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ResponseCallback.java => dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java (71%)
delete mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcResult.java
delete mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/SimpleAsyncRpcResult.java
create mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AsyncToSyncInvoker.java
rename dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/{RpcResultTest.java => AppResponseTest.java} (100%)
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 dd68d7ef3dd..e9d090c4133 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
@@ -24,11 +24,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;
@@ -99,7 +99,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..061068a71b0 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,11 +18,11 @@
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;
@@ -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 184a7b63df6..6b02731304a 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
@@ -36,6 +36,8 @@
import java.util.concurrent.atomic.AtomicInteger;
/**
+ * 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
@@ -66,7 +68,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 82a0e8a2cb7..400a2c487a6 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
@@ -23,12 +23,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;
@@ -41,12 +41,13 @@
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;
+/**
+ * NOTICE! Does not work with async call.
+ * @param
+ */
@SuppressWarnings("unchecked")
public class MergeableClusterInvoker extends AbstractClusterInvoker {
@@ -86,26 +87,19 @@ 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);
+ results.put(invoker.getUrl().getServiceKey(), invoker.invoke(new RpcInvocation(invocation, invoker)));
}
Object result = null;
List resultList = new ArrayList(results.size());
- int timeout = getUrl().getMethodParameter(invocation.getMethodName(), Constants.TIMEOUT_KEY, Constants.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(),
@@ -119,13 +113,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(".")) {
@@ -173,7 +167,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 59303142d85..1628600a91f 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
@@ -22,12 +22,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;
@@ -113,7 +113,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 b10fa01c802..0fce016fbf1 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
@@ -20,12 +20,12 @@
import org.apache.dubbo.common.Constants;
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 279160e7167..07e115d803b 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
@@ -51,6 +51,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 c4cb85daf8b..74056f38a5b 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
@@ -19,12 +19,12 @@
import org.apache.dubbo.common.Constants;
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 8a4089c9049..a79a9facc09 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
@@ -18,10 +18,11 @@
import org.apache.dubbo.common.Constants;
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;
@@ -119,7 +120,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;
}
@@ -135,7 +136,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;
}
@@ -195,14 +196,14 @@ public void testAddMenu() throws Exception {
given(firstInvoker.getUrl()).willReturn(
url.addParameter(Constants.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(Constants.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.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index c89a31421fa..3dc4a7c2aa9 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@ -99,6 +99,8 @@ public class Constants {
public static final String $INVOKE = "$invoke";
+ public static final String $INVOKE_ASYNC = "$invokeAsync";
+
public static final String $ECHO = "$echo";
public static final int DEFAULT_IO_THREADS = Math.min(Runtime.getRuntime().availableProcessors() + 1, 32);
@@ -847,6 +849,11 @@ public class Constants {
*/
public static final String DEVELOPMENT_ENVIRONMENT = "develop";
+ /**
+ * Consumer side 's proxy class
+ */
+ public static final String PROXY_CLASS_REF = "refClass";
+
/**
* Production environment key.
*/
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/config/PropertiesConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/PropertiesConfigurationTest.java
new file mode 100644
index 00000000000..30b81f0a67f
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/PropertiesConfigurationTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.common.config;
+
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class PropertiesConfigurationTest {
+
+ @Test
+ public void testOrderPropertiesProviders() {
+ PropertiesConfiguration configuration = new PropertiesConfiguration("test", null);
+ Assertions.assertTrue(configuration.getInternalProperty("testKey").equals("999"));
+ }
+
+}
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 b96d14d1ee4..591af2c6203 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 {
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..22531301be1 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
@@ -17,11 +17,42 @@
package com.alibaba.dubbo.rpc;
+import org.apache.dubbo.rpc.AppResponse;
+
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
@Deprecated
public interface Result extends org.apache.dubbo.rpc.Result {
+ @Override
+ default void setValue(Object value) {
+
+ }
+
+ @Override
+ default void setException(Throwable t) {
+
+ }
+
+ @Override
+ default org.apache.dubbo.rpc.Result thenApplyWithContext(Function fn) {
+ return this;
+ }
+
+ @Override
+ default CompletableFuture thenApply(Function fn) {
+ return null;
+ }
+
+ @Override
+ default org.apache.dubbo.rpc.Result get() throws InterruptedException, ExecutionException {
+ return this;
+ }
+
+
class CompatibleResult implements Result {
private org.apache.dubbo.rpc.Result delegate;
@@ -53,11 +84,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/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 148b5bce5f5..73706a087ba 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
@@ -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-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java
index 4305ed6c05f..db6b7559a76 100644
--- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java
+++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-consumer/src/main/java/org/apache/dubbo/demo/consumer/comp/DemoServiceComponent.java
@@ -24,6 +24,8 @@
import org.springframework.stereotype.Component;
+import java.util.concurrent.CompletableFuture;
+
@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
@Reference
@@ -33,4 +35,9 @@ public class DemoServiceComponent implements DemoService {
public String sayHello(String name) {
return demoService.sayHello(name);
}
+
+ @Override
+ public CompletableFuture sayHelloAsync(String name) {
+ return null;
+ }
}
diff --git a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
index cb06537ae01..137fa23ead6 100644
--- a/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
+++ b/dubbo-demo/dubbo-demo-annotation/dubbo-demo-annotation-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
@@ -25,6 +25,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.CompletableFuture;
+
@Service
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@@ -35,4 +37,9 @@ public String sayHello(String name) {
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
+ @Override
+ public CompletableFuture sayHelloAsync(String name) {
+ return null;
+ }
+
}
diff --git a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
index 5e2ef2350d2..2f13a5c6714 100644
--- a/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
+++ b/dubbo-demo/dubbo-demo-api/dubbo-demo-api-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
@@ -22,6 +22,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.CompletableFuture;
+
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@@ -31,4 +33,9 @@ public String sayHello(String name) {
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
+ @Override
+ public CompletableFuture sayHelloAsync(String name) {
+ return null;
+ }
+
}
diff --git a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java
index 1172c9be0fc..bd9c9287de7 100644
--- a/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java
+++ b/dubbo-demo/dubbo-demo-interface/src/main/java/org/apache/dubbo/demo/DemoService.java
@@ -16,8 +16,11 @@
*/
package org.apache.dubbo.demo;
+import java.util.concurrent.CompletableFuture;
+
public interface DemoService {
String sayHello(String name);
+ CompletableFuture sayHelloAsync(String name);
}
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java
index 90ed7c0b6a6..ad34442a436 100644
--- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java
+++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/java/org/apache/dubbo/demo/consumer/Application.java
@@ -20,16 +20,21 @@
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import java.util.concurrent.CompletableFuture;
+
public class Application {
/**
* In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before
* launch the application
*/
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
DemoService demoService = context.getBean("demoService", DemoService.class);
- String hello = demoService.sayHello("world");
- System.out.println("result: " + hello);
+// String hello = demoService.sayHello("world");
+ CompletableFuture helloFuture = demoService.sayHelloAsync("world");
+// System.out.println("result: " + hello);
+ System.out.println("result: " + helloFuture.get());
+ System.in.read();
}
}
diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml
index 6b5efc32f00..286b24b3f15 100644
--- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml
+++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/src/main/resources/spring/dubbo-consumer.xml
@@ -27,6 +27,6 @@
-
+
diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
index d0d315c9b4e..e95caa60444 100644
--- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
+++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/src/main/java/org/apache/dubbo/demo/provider/DemoServiceImpl.java
@@ -22,6 +22,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.CompletableFuture;
+
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@@ -31,4 +33,14 @@ public String sayHello(String name) {
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
+ @Override
+ public CompletableFuture sayHelloAsync(String name) {
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ return CompletableFuture.completedFuture("future return value!");
+ }
+
}
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 4de9f5a170c..2f207b83b08 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
@@ -22,12 +22,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;
@@ -95,9 +95,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);
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 2af761a0958..84950c395e1 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
@@ -19,12 +19,12 @@
import org.apache.dubbo.common.Constants;
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;
@@ -87,7 +87,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 e6b90501264..06280ceaf25 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
@@ -86,4 +86,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 10eb31e42fc..5358719e75e 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
@@ -25,9 +25,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;
@@ -41,10 +41,14 @@
* MonitorFilter. (SPI, Singleton, ThreadSafe)
*/
@Activate(group = {Constants.PROVIDER, Constants.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
*/
@@ -59,6 +63,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
*
@@ -70,105 +75,10 @@ public void setMonitorFactory(MonitorFactory monitorFactory) {
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
if (invoker.getUrl().hasParameter(Constants.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(Constants.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(Constants.APPLICATION_KEY);
- String service = invoker.getInterface().getName(); // service name
- String method = RpcUtils.getMethodName(invocation); // method name
- String group = invoker.getUrl().getParameter(Constants.GROUP_KEY);
- String version = invoker.getUrl().getParameter(Constants.VERSION_KEY);
-
- int localPort;
- String remoteKey, remoteValue;
- if (Constants.CONSUMER_SIDE.equals(invoker.getUrl().getParameter(Constants.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(Constants.INPUT_KEY) != null) {
- input = invocation.getAttachment(Constants.INPUT_KEY);
- }
- if (result != null && result.getAttachment(Constants.OUTPUT_KEY) != null) {
- output = result.getAttachment(Constants.OUTPUT_KEY);
- }
-
- return new URL(Constants.COUNT_PROTOCOL,
- NetUtils.getLocalHost(), localPort,
- service + Constants.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),
- Constants.INPUT_KEY, input,
- Constants.OUTPUT_KEY, output,
- Constants.GROUP_KEY, group,
- Constants.VERSION_KEY, version);
+ return invoker.invoke(invocation); // proceed invocation chain
}
// concurrent counter
@@ -182,4 +92,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(Constants.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(Constants.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(Constants.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(Constants.APPLICATION_KEY);
+ String service = invoker.getInterface().getName(); // service name
+ String method = RpcUtils.getMethodName(invocation); // method name
+ String group = invoker.getUrl().getParameter(Constants.GROUP_KEY);
+ String version = invoker.getUrl().getParameter(Constants.VERSION_KEY);
+
+ int localPort;
+ String remoteKey, remoteValue;
+ if (Constants.CONSUMER_SIDE.equals(invoker.getUrl().getParameter(Constants.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(Constants.INPUT_KEY) != null) {
+ input = invocation.getAttachment(Constants.INPUT_KEY);
+ }
+ if (result != null && result.getAttachment(Constants.OUTPUT_KEY) != null) {
+ output = result.getAttachment(Constants.OUTPUT_KEY);
+ }
+
+ return new URL(Constants.COUNT_PROTOCOL, NetUtils.getLocalHost(), localPort, service + Constants.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), Constants.INPUT_KEY, input, Constants.OUTPUT_KEY, output, Constants.GROUP_KEY, group, Constants.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 01ba57dd7b8..730ab28e483 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
@@ -22,12 +22,14 @@
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;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
+
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@@ -73,7 +75,7 @@ public boolean isAvailable() {
public Result invoke(Invocation invocation) throws RpcException {
lastInvocation = invocation;
- return null;
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
}
@Override
@@ -115,7 +117,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);
}
@@ -151,7 +157,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-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.
- */
-public class AsyncRpcResult extends AbstractResult {
+public class AsyncRpcResult implements Result {
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;
+ private CompletableFuture responseFuture;
+ private Invocation invocation;
- protected CompletableFuture resultFuture;
-
- public AsyncRpcResult(CompletableFuture future) {
- this(future, true);
- }
-
- public AsyncRpcResult(CompletableFuture future, boolean registerCallback) {
- this(future, new CompletableFuture<>(), registerCallback);
- }
-
- /**
- * @param future
- * @param rFuture
- * @param registerCallback
- */
- 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();
+ public AsyncRpcResult(CompletableFuture future, Invocation invocation) {
+ this.responseFuture = future;
+ this.invocation = invocation;
+ this.storedContext = RpcContext.getContext();
+ this.storedServerContext = RpcContext.getServerContext();
}
@Override
@@ -120,51 +51,86 @@ public Object getValue() {
}
@Override
- public Throwable getException() {
- return getRpcResult().getException();
+ public void setValue(Object value) {
+
}
@Override
- public boolean hasException() {
- return getRpcResult().hasException();
+ public Throwable getException() {
+ return getRpcResult().getException();
}
@Override
- public Object getResult() {
- return getRpcResult().getResult();
+ public void setException(Throwable t) {
+
}
- public CompletableFuture getValueFuture() {
- return valueFuture;
+ @Override
+ public boolean hasException() {
+ return getRpcResult().hasException();
}
- public CompletableFuture getResultFuture() {
- return resultFuture;
+ public CompletableFuture getResponseFuture() {
+ return responseFuture;
}
- public void setResultFuture(CompletableFuture resultFuture) {
- this.resultFuture = resultFuture;
+ public void setResponseFuture(CompletableFuture responseFuture) {
+ this.responseFuture = responseFuture;
}
public Result getRpcResult() {
try {
- if (resultFuture.isDone()) {
- return resultFuture.get();
+ if (responseFuture.isDone()) {
+ return responseFuture.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 rpcResult = new AppResponse();
+ CompletableFuture future = new CompletableFuture<>();
+ rpcResult.setValue(future);
+ responseFuture.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 rpcResult.recreate();
+ } else if (responseFuture.isDone()) {
+ return responseFuture.get().recreate();
+ }
+ return (new AppResponse()).recreate();
}
- public void thenApplyWithContext(Function fn) {
- this.resultFuture = resultFuture.thenApply(fn.compose(beforeContext).andThen(afterContext));
+ public Result get() throws InterruptedException, ExecutionException {
+ return responseFuture.get();
+ }
+
+ @Override
+ public Result thenApplyWithContext(Function fn) {
+ this.responseFuture = responseFuture.thenApply(fn.compose(beforeContext).andThen(afterContext));
+ return this;
+ }
+
+ @Override
+ public CompletableFuture thenApply(Function fn) {
+ return this.responseFuture.thenApply(fn);
}
@Override
@@ -203,18 +169,49 @@ 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 result, Invocation invocation) {
+ return new AsyncRpcResult(CompletableFuture.completedFuture(result), invocation);
+ }
+
+ 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) {
+ CompletableFuture future = new CompletableFuture<>();
+ AppResponse result = new AppResponse();
+ if (t != null) {
+ result.setException(t);
+ } else {
+ result.setValue(value);
+ }
+ future.complete(result);
+ return new AsyncRpcResult(future, invocation);
+ }
}
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..7c634481d7e 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,16 @@
*/
@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
- *
- * @param result result
- * @param invoker invoker
- * @param invocation invocation
- * @return Return {@link Result}
- */
- default Result onResponse(Result result, Invoker> invoker, Invocation invocation) {
- return result;
+ interface Listener {
+
+ void onResponse(Result result, 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..2468837958c
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/FutureContext.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+/**
+ * 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 ThreadLocal> futureTL = new ThreadLocal<>();
+
+ /**
+ * 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-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java
new file mode 100644
index 00000000000..a97a0be61f4
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/InvokeMode.java
@@ -0,0 +1,23 @@
+/*
+ * 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;
+
+public enum InvokeMode {
+
+ SYNC, ASYNC, FUTURE;
+
+}
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ResponseCallback.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java
similarity index 71%
rename from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ResponseCallback.java
rename to dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java
index 37fe6cc6e34..622ef1f0309 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/ResponseCallback.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ListenableFilter.java
@@ -1,38 +1,29 @@
-/*
- * 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.remoting.exchange;
-
-/**
- * Callback
- */
-public interface ResponseCallback {
-
- /**
- * done.
- *
- * @param response
- */
- void done(Object response);
-
- /**
- * caught exception.
- *
- * @param exception
- */
- void caught(Throwable exception);
-
-}
\ No newline at end of file
+/*
+ * 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;
+
+/**
+ *
+ */
+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..1ecd9dae771 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,6 +18,9 @@
import java.io.Serializable;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
/**
@@ -25,7 +28,7 @@
*
* @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 {
@@ -36,6 +39,8 @@ public interface Result extends Serializable {
*/
Object getValue();
+ void setValue(Object value);
+
/**
* Get exception.
*
@@ -43,6 +48,8 @@ public interface Result extends Serializable {
*/
Throwable getException();
+ void setException(Throwable t);
+
/**
* Has exception.
*
@@ -66,14 +73,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 +110,10 @@ public interface Result extends Serializable {
void setAttachment(String key, String value);
+ Result thenApplyWithContext(Function fn);
+
+ CompletableFuture thenApply(Function fn);
+
+ Result get() throws InterruptedException, ExecutionException;
+
}
\ 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 fa63b7e4c1a..c585c178ce9 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
@@ -70,7 +70,6 @@ protected RpcContext initialValue() {
private final Map attachments = new HashMap();
private final Map values = new HashMap();
- private Future> future;
private List urls;
@@ -139,32 +138,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.
*
@@ -246,7 +219,7 @@ public boolean isConsumerSide() {
*/
@SuppressWarnings("unchecked")
public CompletableFuture getCompletableFuture() {
- return (CompletableFuture) future;
+ return FutureContext.getCompletableFuture();
}
/**
@@ -257,7 +230,7 @@ public CompletableFuture getCompletableFuture() {
*/
@SuppressWarnings("unchecked")
public Future getFuture() {
- return (Future) future;
+ return FutureContext.getCompletableFuture();
}
/**
@@ -265,8 +238,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 707bf3b77ad..207239d11ef 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
@@ -45,6 +45,10 @@ public class RpcInvocation implements Invocation, Serializable {
private transient Invoker> invoker;
+ private transient Class> returnType;
+
+ private transient InvokeMode invokeMode;
+
public RpcInvocation() {
}
@@ -87,6 +91,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) {
@@ -205,6 +210,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 1c2f69fecb9..fe692af565f 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
@@ -19,14 +19,17 @@
import org.apache.dubbo.common.Constants;
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;
/**
+ *
* ActiveLimitFilter restrict the concurrent client invocation for a service or service's method from client side.
* To use active limit filter, configured url with actives and provide valid >0 integer value.
*
@@ -39,50 +42,75 @@
* @see Filter
*/
@Activate(group = Constants.CONSUMER, value = Constants.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, Constants.ACTIVES_KEY, 0);
- RpcStatus count = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
- if (!count.beginCount(url, methodName, max)) {
+ RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
+ if (!RpcStatus.beginCount(url, methodName, max)) {
long timeout = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.TIMEOUT_KEY, 0);
long start = System.currentTimeMillis();
long remain = timeout;
- synchronized (count) {
- while (!count.beginCount(url, methodName, max)) {
+ 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 {
- count.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 result, Invoker> invoker, Invocation invocation) {
+ String methodName = invocation.getMethodName();
+ URL url = invoker.getUrl();
+ int max = invoker.getUrl().getMethodParameter(methodName, Constants.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, Constants.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 ace832ca33c..ad1a8a2492b 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
@@ -24,9 +24,9 @@
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;
@@ -45,44 +45,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 result, Invoker> invoker, Invocation 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);
+
+ } else {
+ newValue = value;
+ }
+ if (newValue != value) {
+ result.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 5db6b889d35..a2005e21e1a 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
@@ -19,9 +19,9 @@
import org.apache.dubbo.common.Constants;
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;
@@ -35,7 +35,11 @@
* @see RpcContext
*/
@Activate(group = Constants.CONSUMER, order = -10000)
-public class ConsumerContextFilter implements Filter {
+public class ConsumerContextFilter extends ListenableFilter {
+
+ public ConsumerContextFilter() {
+ super.listener = new ConsumerContextListener();
+ }
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
@@ -49,18 +53,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 result, Invoker> invoker, Invocation invocation) {
+ RpcContext.getServerContext().setAttachments(result.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 fe85da0386a..df135a64894 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
@@ -18,9 +18,9 @@
import org.apache.dubbo.common.Constants;
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;
@@ -38,7 +38,11 @@
* @see RpcContext
*/
@Activate(group = Constants.PROVIDER, order = -10000)
-public class ContextFilter implements Filter {
+public class ContextFilter extends ListenableFilter {
+
+ public ContextFilter() {
+ super.listener = new ContextListener();
+ }
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
@@ -86,10 +90,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 result, Invoker> invoker, Invocation invocation) {
+ // pass attachments to result
+ result.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 cba9e7f4f46..7e3e5b8dda0 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;
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;
/**
* Dubbo provided default Echo echo service, which is available for all dubbo provider service interface.
@@ -34,7 +34,7 @@ public class EchoFilter implements Filter {
@Override
public Result invoke(Invoker> invoker, Invocation inv) throws RpcException {
if (inv.getMethodName().equals(Constants.$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 7715348f827..1cb9f87d488 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 = Constants.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 result, Invoker> invoker, Invocation invocation) {
+ if (result.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 = result.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
+ result.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 b335a4141ff..c1b2eb5e6bc 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,21 +19,29 @@
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
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;
/**
+ *
* 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 = Constants.PROVIDER, value = Constants.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 {
@@ -46,20 +54,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 result, 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 ae7b92c40f1..5c86cae6577 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;
@@ -47,11 +46,15 @@
* GenericInvokerFilter.
*/
@Activate(group = Constants.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(Constants.$INVOKE)
+ if ((inv.getMethodName().equals(Constants.$INVOKE) || inv.getMethodName().equals(Constants.$INVOKE_ASYNC))
&& inv.getArguments() != null
&& inv.getArguments().length == 3
&& !GenericService.class.isAssignableFrom(invoker.getInterface())) {
@@ -108,33 +111,52 @@ public Result invoke(Invoker> invoker, Invocation inv) throws RpcException {
}
}
}
- 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 result, Invoker> invoker, Invocation inv) {
+ if ((inv.getMethodName().equals(Constants.$INVOKE) || inv.getMethodName().equals(Constants.$INVOKE_ASYNC))
+ && inv.getArguments() != null
+ && inv.getArguments().length == 3
+ && !GenericService.class.isAssignableFrom(invoker.getInterface())) {
+
+ String generic = inv.getAttachment(Constants.GENERIC_KEY);
+ if (StringUtils.isBlank(generic)) {
+ generic = RpcContext.getContext().getAttachment(Constants.GENERIC_KEY);
+ }
+
+ if (result.hasException() && !(result.getException() instanceof GenericException)) {
+ result.setException(new GenericException(result.getException()));
}
if (ProtocolUtils.isJavaGenericSerialization(generic)) {
try {
UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(512);
- ExtensionLoader.getExtensionLoader(Serialization.class)
- .getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
- .serialize(null, os).writeObject(result.getValue());
- return new RpcResult(os.toByteArray());
+ ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA).serialize(null, os).writeObject(result.getValue());
+ result.setValue(os.toByteArray());
} catch (IOException e) {
throw new RpcException("Serialize result failed.", e);
}
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
- return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
+ result.setValue(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
} else {
- return new RpcResult(PojoUtils.generalize(result.getValue()));
+ result.setValue(PojoUtils.generalize(result.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 6df1262fbef..f9caf44f069 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,37 +25,42 @@
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;
/**
* GenericImplInvokerFilter
*/
@Activate(group = Constants.CONSUMER, value = Constants.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(Constants.GENERIC_KEY);
if (ProtocolUtils.isGeneric(generic)
- && !Constants.$INVOKE.equals(invocation.getMethodName())
+ && (!Constants.$INVOKE.equals(invocation.getMethodName()) && !Constants.$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();
@@ -75,77 +80,15 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
args = PojoUtils.generalize(arguments);
}
- invocation2.setMethodName(Constants.$INVOKE);
+ if (RpcUtils.isReturnTypeFuture(invocation)) {
+ invocation2.setMethodName(Constants.$INVOKE_ASYNC);
+ } else {
+ invocation2.setMethodName(Constants.$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(Constants.$INVOKE)
+ return invoker.invoke(invocation2);
+ } else if ((invocation.getMethodName().equals(Constants.$INVOKE) || invocation.getMethodName().equals(Constants.$INVOKE_ASYNC))
&& invocation.getArguments() != null
&& invocation.getArguments().length == 3
&& ProtocolUtils.isGeneric(generic)) {
@@ -166,20 +109,89 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
}
}
- ((RpcInvocation) invocation).setAttachment(
+ invocation.setAttachment(
Constants.GENERIC_KEY, invoker.getUrl().getParameter(Constants.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 result, Invoker> invoker, Invocation invocation) {
+ String generic = invoker.getUrl().getParameter(Constants.GENERIC_KEY);
+ String methodName = invocation.getMethodName();
+ Class>[] parameterTypes = invocation.getParameterTypes();
+ if (ProtocolUtils.isGeneric(generic)
+ && (!Constants.$INVOKE.equals(invocation.getMethodName()) && !Constants.$INVOKE_ASYNC.equals(invocation.getMethodName()))
+ && invocation instanceof RpcInvocation) {
+ if (!result.hasException()) {
+ Object value = result.getValue();
+ try {
+ Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
+ if (ProtocolUtils.isBeanGenericSerialization(generic)) {
+ if (value == null) {
+ result.setValue(value);
+ } else if (value instanceof JavaBeanDescriptor) {
+ result.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);
+ result.setValue(PojoUtils.realize(value, (Class>) types[0], types[1]));
+ }
+ } 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.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 c00689fc1c8..b6335823d8e 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 = Constants.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 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.");
+ }
}
}
}
- 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 3df1f1d741e..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
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.protocol;
-import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.logger.Logger;
@@ -24,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;
@@ -148,9 +147,8 @@ public Result invoke(Invocation inv) throws RpcException {
*/
invocation.addAttachments(contextAttachments);
}
- if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) {
- invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
- }
+
+ invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
try {
@@ -158,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 814e9182280..a2a6ebb135f 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;
@@ -82,4 +83,11 @@ public void destroy() {
}
}
}
+
+ @Override
+ public Invoker refer(Class type, URL url) throws RpcException {
+ return new AsyncToSyncInvoker<>(doRefer(type, url));
+ }
+
+ protected abstract Invoker doRefer(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 a77a5bdc5f3..e03d3800984 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
@@ -92,13 +92,14 @@ public void unexport() {
}
@Override
- public Invoker refer(final Class type, final URL url) throws RpcException {
- final Invoker target = proxyFactory.getInvoker(doRefer(type, url), type, url);
+ public Invoker doRefer(final Class type, final URL url) throws RpcException {
+ final Invoker target = proxyFactory.getInvoker(getFrameworkProxy(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) {
@@ -143,6 +144,6 @@ protected int getErrorCode(Throwable e) {
protected abstract Runnable doExport(T impl, Class type, URL url) throws RpcException;
- protected abstract T doRefer(Class type, URL url) throws RpcException;
+ protected abstract T getFrameworkProxy(Class type, URL url) throws RpcException;
}
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 c5ed5943cd0..2106a4e0da8 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.Constants;
import org.apache.dubbo.common.URL;
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;
@@ -70,14 +70,29 @@ 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);
+ }
+ }
+ 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..aa813e1d1a5 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,47 @@ 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);
+ CompletableFuture appResponseFuture = future.handle((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);
+ }
+ return result;
+ });
+ return new AsyncRpcResult(appResponseFuture, invocation);
} 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 3cdb65c742f..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
@@ -16,12 +16,10 @@
*/
package org.apache.dubbo.rpc.proxy;
-import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.logger.Logger;
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;
@@ -54,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(Constants.FUTURE_RETURNTYPE_KEY, "true");
- invocation.setAttachment(Constants.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 923c7cb0fd1..a7f973a832a 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
@@ -19,18 +19,18 @@
import org.apache.dubbo.common.Constants;
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;
@@ -106,7 +106,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..ecf7a4524f5 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 doRefer(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 a5ae76133cf..ca55dfbe8ca 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
@@ -23,15 +23,14 @@
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;
/**
@@ -65,7 +64,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
@@ -80,24 +78,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) {
@@ -184,11 +165,22 @@ public static boolean isAsync(URL url, Invocation inv) {
}
public static boolean isReturnTypeFuture(Invocation inv) {
- return Boolean.TRUE.toString().equals(inv.getAttachment(Constants.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 Constants.$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 100%
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
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..e16dfbd8f61 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);
+ Result rpcResult = asyncResult.get();
+ compatibleFilter.listener().onResponse(rpcResult, invoker, invocation);
+ assertEquals(Type.High, rpcResult.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);
+ Result rpcResult = asyncResult.get();
+ compatibleFilter.listener().onResponse(rpcResult, invoker, invocation);
+ assertEquals(Type.High, rpcResult.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..964e06ecb15 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;
@@ -33,6 +33,8 @@
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
+import java.util.concurrent.CompletableFuture;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
@@ -51,18 +53,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,7 +80,7 @@ public void testJavaException() {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class>[]{String.class}, new Object[]{"world"});
- RpcResult rpcResult = new RpcResult();
+ AppResponse rpcResult = new AppResponse();
rpcResult.setException(new IllegalArgumentException("java"));
Invoker invoker = mock(Invoker.class);
@@ -96,7 +100,7 @@ public void testRuntimeException() {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class>[]{String.class}, new Object[]{"world"});
- RpcResult rpcResult = new RpcResult();
+ AppResponse rpcResult = new AppResponse();
rpcResult.setException(new LocalException("localException"));
Invoker invoker = mock(Invoker.class);
@@ -111,27 +115,28 @@ public void testRuntimeException() {
@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 = new AsyncRpcResult(CompletableFuture.completedFuture(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);
+ Result rpcResult = asyncResult.get();
+ exceptionFilter.listener().onResponse(rpcResult, invoker, invocation);
- Assertions.assertEquals(newResult.getException().getClass(), RuntimeException.class);
- Assertions.assertEquals(newResult.getException().getMessage(), StringUtils.toString(rpcResult.getException()));
+ Assertions.assertFalse(rpcResult.getException() instanceof HessianException);
+ Assertions.assertEquals(rpcResult.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 bd680e7502e..f2358ddaeca 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
@@ -18,7 +18,13 @@
import org.apache.dubbo.common.Constants;
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;
@@ -52,14 +58,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"));
+ Result rpcResult = asyncResult.get();
+ genericFilter.listener().onResponse(rpcResult, invoker, invocation);
+ Assertions.assertEquals(HashMap.class, rpcResult.getValue().getClass());
+ Assertions.assertEquals(10, ((HashMap) rpcResult.getValue()).get("age"));
}
@@ -79,7 +87,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);
@@ -102,7 +110,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);
@@ -126,7 +134,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 43930ef6605..469632b9ec3 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
@@ -18,11 +18,12 @@
import org.apache.dubbo.common.Constants;
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;
@@ -35,6 +36,7 @@
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;
@@ -58,11 +60,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(new AsyncRpcResult(CompletableFuture.completedFuture(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());
@@ -78,12 +83,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(new AsyncRpcResult(CompletableFuture.completedFuture(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());
}
@@ -103,7 +110,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 fea5c300e07..5b86459624a 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
@@ -18,11 +18,11 @@
import org.apache.dubbo.common.Constants;
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;
@@ -45,7 +45,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(Constants.TOKEN_KEY, token);
@@ -64,7 +64,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(Constants.TOKEN_KEY, "wrongToken");
@@ -83,7 +83,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 5b7261de7b4..13a2ae244f4 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
@@ -51,6 +51,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..1b74e6bc41b 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,14 @@
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;
+
+import java.util.concurrent.CompletableFuture;
/**
* MockInvoker.java
@@ -58,15 +61,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 new AsyncRpcResult(CompletableFuture.completedFuture(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 5eb4dd9205f..0c92aea5bf5 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
@@ -31,6 +31,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;
@@ -144,7 +145,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 4c78c1cceb9..5a22127d3ef 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
@@ -25,16 +25,20 @@
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;
/**
+ * Server push uses this Invoker to continuously push data to client.
* Wrap the existing invoker on the channel.
*/
class ChannelWrappedInvoker extends AbstractInvoker {
@@ -58,15 +62,12 @@ protected Result doInvoke(Invocation invocation) throws Throwable {
inv.setAttachment(Constants.CALLBACK_SERVICE_KEY, serviceKey);
try {
- if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) { // may have concurrency issue
+ if (RpcUtils.isOneway(getUrl(), inv)) { // may have concurrency issue
currentClient.send(inv, getUrl().getMethodParameter(invocation.getMethodName(), Constants.SENT_KEY, false));
- return new RpcResult();
- }
- int timeout = getUrl().getMethodParameter(invocation.getMethodName(), Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
- if (timeout > 0) {
- return (Result) currentClient.request(inv, timeout).get();
+ return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
- return (Result) currentClient.request(inv).get();
+ CompletableFuture appResponseFuture = currentClient.request(inv).thenApply(obj -> (AppResponse) obj);
+ return new AsyncRpcResult(appResponseFuture, inv);
}
} 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 fac7c64a6ca..e6d3f84a781 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 4093eb266d6..40c6e2912d3 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
@@ -24,8 +24,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;
@@ -75,7 +75,7 @@ private void logMessageLength(Object result, int bytes) {
}
} else if (result instanceof Response) {
try {
- ((RpcResult) ((Response) result).getResult()).setAttachment(
+ ((AppResponse) ((Response) result).getResult()).setAttachment(
Constants.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 5f2c61b1cae..d8513a31806 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;
/**
@@ -80,32 +79,17 @@ 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, Constants.TIMEOUT_KEY, Constants.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();
+ CompletableFuture appResponseFuture = currentClient.request(inv, timeout).thenApply(obj -> (AppResponse) obj);
+ RpcContext.getContext().setFuture(new FutureAdapter(appResponseFuture));
+ return new AsyncRpcResult(appResponseFuture, inv);
}
} 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 77443016cfb..926a940cd5d 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
@@ -37,7 +37,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;
@@ -59,6 +58,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Function;
/**
* dubbo protocol support.
@@ -123,16 +123,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.thenApply(Function.identity());
}
@Override
@@ -382,7 +375,7 @@ private void optimizeSerialization(URL url) throws RpcException {
}
@Override
- public Invoker refer(Class serviceType, URL url) throws RpcException {
+ public Invoker doRefer(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..9fc47f6f9c9 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.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;
- 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.resultFuture = future;
+ future.whenComplete((result, t) -> {
+ if (t != null) {
+ if (t instanceof CompletionException) {
+ t = t.getCause();
+ }
+ this.completeExceptionally(t);
+ } else {
+ if (result.hasException()) {
+ this.completeExceptionally(result.getException());
+ } else {
+ this.complete((V)result.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 resultFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
- return false;
+ return resultFuture.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 f2bc4534fdc..c11ffca421d 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
@@ -27,9 +27,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;
@@ -84,7 +84,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);
@@ -105,7 +105,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 faafe082852..cb589e228ec 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;
/**
@@ -52,7 +52,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);
}
@@ -72,7 +72,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 98283f450c8..737e7390048 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;
@@ -37,10 +36,14 @@
* EventFilter
*/
@Activate(group = Constants.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);
@@ -49,37 +52,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) {
@@ -224,4 +196,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 e2b71d05432..9a965cd80ea 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
@@ -19,17 +19,18 @@
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.utils.NetUtils;
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;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -62,7 +63,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.doRefer(IDemoService.class, url);
Assertions.assertEquals(true, invoker.isAvailable());
invoker.destroy();
Assertions.assertEquals(false, invoker.isAvailable());
@@ -73,7 +74,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.doRefer(IDemoService.class, url);
Assertions.assertEquals(true, invoker.isAvailable());
getClients(invoker)[0].setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
@@ -91,7 +92,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.doRefer(IDemoService.class, url);
long start = System.currentTimeMillis();
@@ -113,7 +114,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.doRefer(IDemoService.class, url);
ExchangeClient[] clients = getClients(invoker);
clients[0].close();
@@ -126,11 +127,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) {
@@ -140,7 +140,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 7e9818d07f1..e37bd7d0dc9 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
@@ -18,12 +18,12 @@
import org.apache.dubbo.common.Constants;
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&" + Constants.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 2baa67ccae6..30ffda71fdf 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
@@ -237,7 +237,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 b77e5e18b3c..3f2c0cf21d4 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
@@ -26,7 +26,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;
@@ -271,8 +273,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-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java
index 3b9239171a9..1eead54f164 100644
--- a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/org/apache/dubbo/rpc/protocol/hessian/HessianProtocol.java
@@ -94,7 +94,7 @@ public void run() {
@Override
@SuppressWarnings("unchecked")
- protected T doRefer(Class serviceType, URL url) throws RpcException {
+ protected T getFrameworkProxy(Class serviceType, URL url) throws RpcException {
String generic = url.getParameter(Constants.GENERIC_KEY);
boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class);
if (isGeneric) {
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 0188a0fe329..7b99e2d80d5 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
@@ -18,8 +18,8 @@
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.http.HttpBinder;
import org.apache.dubbo.remoting.http.HttpHandler;
import org.apache.dubbo.remoting.http.HttpServer;
@@ -110,7 +110,7 @@ private HttpInvokerServiceExporter createExporter(T impl, Class> type) {
@Override
@SuppressWarnings("unchecked")
- protected T doRefer(final Class serviceType, final URL url) throws RpcException {
+ protected T getFrameworkProxy(final Class serviceType, final URL url) throws RpcException {
final String generic = url.getParameter(Constants.GENERIC_KEY);
final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class);
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 1181e899d71..5a9bb845e15 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
@@ -88,7 +88,7 @@ public Exporter export(Invoker invoker) throws RpcException {
}
@Override
- public Invoker refer(Class serviceType, URL url) throws RpcException {
+ public Invoker doRefer(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 8fa088bb95f..eef3bf6aa58 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.Constants;
import org.apache.dubbo.common.URL;
+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 doRefer(final Class type, final URL url) throws RpcException {
try {
String address = url.getAddress();
String backup = url.getParameter(Constants.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-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 ba35c298ec4..38aeae826ea 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.ObjectOutput;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.common.utils.StringUtils;
+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;
@@ -68,7 +68,7 @@ private Serialization getSerialization(URL url) {
}
@Override
- public Invoker refer(final Class type, final URL url) throws RpcException {
+ protected Invoker doRefer(final Class type, final URL url) throws RpcException {
try {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setTestOnBorrow(url.getParameter("test.on.borrow", true));
@@ -119,10 +119,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);
@@ -135,13 +135,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/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
index 6265254d4c6..09ba8c30aee 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
@@ -128,7 +128,7 @@ protected Runnable doExport(T impl, Class type, URL url) throws RpcExcept
}
@Override
- protected T doRefer(Class serviceType, URL url) throws RpcException {
+ protected T getFrameworkProxy(Class serviceType, URL url) throws RpcException {
// TODO more configs to add
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
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 63e9fcdfff1..823d042142e 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
@@ -22,6 +22,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;
@@ -69,7 +70,7 @@ public void run() {
@Override
@SuppressWarnings("unchecked")
- protected T doRefer(final Class serviceType, final URL url) throws RpcException {
+ protected T getFrameworkProxy(final Class serviceType, final URL url) throws RpcException {
final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
final String generic = url.getParameter(Constants.GENERIC_KEY);
final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class);
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 93a5900d753..75dd2d248df 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
@@ -26,9 +26,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;
import org.apache.thrift.TBase;
@@ -284,7 +284,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()));
@@ -375,7 +375,7 @@ private Object decode(TProtocol protocol)
response.setId(id);
- RpcResult rpcResult = new RpcResult();
+ AppResponse rpcResult = new AppResponse();
if (realResult instanceof Throwable) {
rpcResult.setException((Throwable) realResult);
@@ -536,7 +536,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());
@@ -610,7 +610,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 fa123e232a5..e02fac3a176 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,8 @@
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.TimeoutException;
import org.apache.dubbo.remoting.exchange.ExchangeClient;
+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;
@@ -29,8 +31,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;
/**
* @since 2.7.0, use https://github.com/dubbo/dubbo-rpc-native-thrift instead
@@ -85,10 +89,9 @@ protected Result doInvoke(Invocation invocation) throws Throwable {
int timeout = getUrl().getMethodParameter(
methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
- RpcContext.getContext().setFuture(null);
-
- return (Result) currentClient.request(inv, timeout).get();
-
+ CompletableFuture appResponseFuture = currentClient.request(inv, timeout).thenApply(obj -> (AppResponse) obj);
+ RpcContext.getContext().setFuture(new FutureAdapter(appResponseFuture));
+ return new AsyncRpcResult(appResponseFuture, invocation);
} 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 055af6f8bb3..61c13ccce65 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,6 +43,8 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
/**
* @since 2.7.0, use https://github.com/dubbo/dubbo-rpc-native-thrift instead
*/
@@ -83,8 +86,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.thenApply(Function.identity());
}
throw new RemotingException(channel,
@@ -157,7 +160,7 @@ public void destroy() {
} // ~ end of method destroy
@Override
- public Invoker refer(Class type, URL url) throws RpcException {
+ protected Invoker doRefer(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 a1d5daadea8..1c781f85af2 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
@@ -24,9 +24,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;
import org.apache.thrift.TApplicationException;
@@ -186,13 +186,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());
}
@@ -256,9 +256,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());
@@ -275,8 +275,8 @@ public void testEncodeReplyResponse() throws Exception {
Request request = createRequest();
- RpcResult rpcResult = new RpcResult();
- rpcResult.setResult("Hello, World!");
+ AppResponse rpcResult = new AppResponse();
+ rpcResult.setValue("Hello, World!");
Response response = new Response();
response.setResult(rpcResult);
@@ -333,7 +333,7 @@ public void testEncodeExceptionResponse() throws Exception {
Request request = createRequest();
- RpcResult rpcResult = new RpcResult();
+ AppResponse rpcResult = new AppResponse();
String exceptionMessage = "failed";
rpcResult.setException(new RuntimeException(exceptionMessage));
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java b/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
index ddb270def40..007f62beedc 100644
--- a/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/main/java/org/apache/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
@@ -107,7 +107,7 @@ public void run() {
@Override
@SuppressWarnings("unchecked")
- protected T doRefer(final Class serviceType, final URL url) throws RpcException {
+ protected T getFrameworkProxy(final Class serviceType, final URL url) throws RpcException {
ClientProxyFactoryBean proxyFactoryBean = new ClientProxyFactoryBean();
proxyFactoryBean.setAddress(url.setProtocol("http").toIdentityString());
proxyFactoryBean.setServiceClass(serviceType);