diff --git a/README.md b/README.md index 6f41ccfda56..b5906c7f46b 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ public interface GreetingService { } ``` -*See [api/GreetingService.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/com/alibaba/dubbo/samples/api/GreetingsService.java) on GitHub.* +*See [api/GreetingService.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.* ### Implement service interface for the provider @@ -73,7 +73,7 @@ public class GreetingServiceImpl implements GreetingService { } ``` -*See [provider/GreetingServiceImpl.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/com/alibaba/dubbo/samples/server/GreetingsServiceImpl.java) on GitHub.* +*See [provider/GreetingServiceImpl.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.* ### Start service provider @@ -101,7 +101,7 @@ public class Application { } ``` -*See [provider/Application.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/com/alibaba/dubbo/samples/provider/Application.java) on GitHub.* +*See [provider/Application.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.* ### Build and run the provider @@ -141,7 +141,7 @@ public class Application { The consumer will print out `Hello world` on the screen. -*See [consumer/Application.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/com/alibaba/dubbo/samples/consumer/Application.java) on GitHub.* +*See [consumer/Application.java](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/consumer/Application.java) on GitHub.* ### Next steps diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java index 47aa2515a3c..99a46a97e19 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java @@ -51,4 +51,31 @@ public interface Router extends Comparable { */ List> route(List> invokers, URL url, Invocation invocation) throws RpcException; + /** + * priority + * + * @return + */ + int getPriority(); + + /** + * compare Router + * + * @param o + * @return + */ + @Override + default int compareTo(Router o) { + if (o == null) { + throw new IllegalArgumentException(); + } + if (this.getPriority() == o.getPriority()) { + if (o.getUrl() == null) { + return -1; + } + return getUrl().toFullString().compareTo(o.getUrl().toFullString()); + } else { + return getPriority() > o.getPriority() ? 1 : -1; + } + } } \ No newline at end of file diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java index f0bd58ef344..242a2ffc23f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java @@ -108,7 +108,6 @@ protected Invoker doSelect(List> invokers, URL url, Invocation weightedRoundRobin = new WeightedRoundRobin(); weightedRoundRobin.setWeight(weight); map.putIfAbsent(identifyString, weightedRoundRobin); - weightedRoundRobin = map.get(identifyString); } if (weight != weightedRoundRobin.getWeight()) { //weight changed diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/MockInvokersSelector.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/MockInvokersSelector.java index 35ce7e5331c..18133a4d47f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/MockInvokersSelector.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/MockInvokersSelector.java @@ -49,6 +49,11 @@ public List> route(final List> invokers, return invokers; } + @Override + public int getPriority() { + return Integer.MAX_VALUE; + } + private List> getMockedInvokers(final List> invokers) { if (!hasMockProviders(invokers)) { return null; diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java index f45741ea97b..9b3e5271b52 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java @@ -40,7 +40,6 @@ /** * ConditionRouter - * */ public class ConditionRouter implements Router { @@ -178,17 +177,13 @@ public List> route(List> invokers, URL url, Invocation } @Override - public URL getUrl() { - return url; + public int getPriority() { + return priority; } @Override - public int compareTo(Router o) { - if (o == null || o.getClass() != ConditionRouter.class) { - return 1; - } - ConditionRouter c = (ConditionRouter) o; - return this.priority == c.priority ? url.toFullString().compareTo(c.url.toFullString()) : (this.priority > c.priority ? 1 : -1); + public URL getUrl() { + return url; } boolean matchWhen(URL url, Invocation invocation) { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java index 616432254aa..7c3070abf54 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java @@ -40,7 +40,6 @@ /** * ScriptRouter - * */ public class ScriptRouter implements Router { @@ -114,13 +113,24 @@ public List> route(List> invokers, URL url, Invocation } } + @Override + public int getPriority() { + return priority; + } + @Override public int compareTo(Router o) { - if (o == null || o.getClass() != ScriptRouter.class) { - return 1; + if (o == null) { + throw new IllegalArgumentException(); + } + if (this.priority == o.getPriority()) { + if (o instanceof ScriptRouter) { + ScriptRouter c = (ScriptRouter) o; + return rule.compareTo(c.rule); + } + return 0; + } else { + return this.priority > o.getPriority() ? 1 : -1; } - ScriptRouter c = (ScriptRouter) o; - return this.priority == c.priority ? rule.compareTo(c.rule) : (this.priority > c.priority ? 1 : -1); } - } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java index 4bcb43b7c08..c7526ce9c5c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java @@ -72,18 +72,10 @@ public List> route(List> invokers, URL url, Invocation result.add(invoker); } } - // If no invoker be selected, downgrade to normal invokers - if (result.isEmpty()) { - for (Invoker invoker : invokers) { - if (StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) { - result.add(invoker); - } - } - } - // Normal request - } else { + } + // If Constants.REQUEST_TAG_KEY unspecified or no invoker be selected, downgrade to normal invokers + if (result.isEmpty()) { for (Invoker invoker : invokers) { - // Can't access tag invoker,only normal invoker should be selected if (StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) { result.add(invoker); } @@ -98,11 +90,7 @@ public List> route(List> invokers, URL url, Invocation } @Override - public int compareTo(Router o) { - if (o == null || o.getClass() != TagRouter.class) { - return 1; - } - TagRouter c = (TagRouter) o; - return this.priority == c.priority ? url.toFullString().compareTo(c.url.toFullString()) : (this.priority > c.priority ? 1 : -1); + public int getPriority() { + return priority; } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java index e8b80595e7d..2d3602aead4 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java @@ -24,6 +24,7 @@ import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; @@ -44,8 +45,8 @@ */ public abstract class AbstractClusterInvoker implements Invoker { - private static final Logger logger = LoggerFactory - .getLogger(AbstractClusterInvoker.class); + private static final Logger logger = LoggerFactory.getLogger(AbstractClusterInvoker.class); + protected final Directory directory; protected final boolean availablecheck; @@ -110,25 +111,28 @@ public void destroy() { * @return the invoker which will final to do invoke. * @throws RpcException */ - protected Invoker select(LoadBalance loadbalance, Invocation invocation, List> invokers, List> selected) throws RpcException { - if (invokers == null || invokers.isEmpty()) { + protected Invoker select(LoadBalance loadbalance, Invocation invocation, + List> invokers, List> selected) throws RpcException { + + if (CollectionUtils.isEmpty(invokers)) { return null; } - String methodName = invocation == null ? "" : invocation.getMethodName(); + String methodName = invocation == null ? StringUtils.EMPTY : invocation.getMethodName(); - boolean sticky = invokers.get(0).getUrl().getMethodParameter(methodName, Constants.CLUSTER_STICKY_KEY, Constants.DEFAULT_CLUSTER_STICKY); - { - //ignore overloaded method - if (stickyInvoker != null && !invokers.contains(stickyInvoker)) { - stickyInvoker = null; - } - //ignore concurrency problem - if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) { - if (availablecheck && stickyInvoker.isAvailable()) { - return stickyInvoker; - } + boolean sticky = invokers.get(0).getUrl() + .getMethodParameter(methodName, Constants.CLUSTER_STICKY_KEY, Constants.DEFAULT_CLUSTER_STICKY); + + //ignore overloaded method + if (stickyInvoker != null && !invokers.contains(stickyInvoker)) { + stickyInvoker = null; + } + //ignore concurrency problem + if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) { + if (availablecheck && stickyInvoker.isAvailable()) { + return stickyInvoker; } } + Invoker invoker = doSelect(loadbalance, invocation, invokers, selected); if (sticky) { @@ -137,8 +141,10 @@ protected Invoker select(LoadBalance loadbalance, Invocation invocation, List return invoker; } - private Invoker doSelect(LoadBalance loadbalance, Invocation invocation, List> invokers, List> selected) throws RpcException { - if (invokers == null || invokers.isEmpty()) { + private Invoker doSelect(LoadBalance loadbalance, Invocation invocation, + List> invokers, List> selected) throws RpcException { + + if (CollectionUtils.isEmpty(invokers)) { return null; } if (invokers.size() == 1) { @@ -158,7 +164,7 @@ private Invoker doSelect(LoadBalance loadbalance, Invocation invocation, List int index = invokers.indexOf(invoker); try { //Avoid collision - invoker = index < invokers.size() - 1 ? invokers.get(index + 1) : invokers.get(0); + invoker = invokers.get((index + 1) % invokers.size()); } catch (Exception e) { logger.warn(e.getMessage() + " may because invokers list dynamic change, ignore.", e); } @@ -171,7 +177,8 @@ private Invoker doSelect(LoadBalance loadbalance, Invocation invocation, List } /** - * Reselect, use invokers not in `selected` first, if all invokers are in `selected`, just pick an available one using loadbalance policy. + * Reselect, use invokers not in `selected` first, if all invokers are in `selected`, + * just pick an available one using loadbalance policy. * * @param loadbalance * @param invocation @@ -181,48 +188,40 @@ private Invoker doSelect(LoadBalance loadbalance, Invocation invocation, List * @throws RpcException */ private Invoker reselect(LoadBalance loadbalance, Invocation invocation, - List> invokers, List> selected, boolean availablecheck) - throws RpcException { + List> invokers, List> selected, boolean availablecheck) throws RpcException { //Allocating one in advance, this list is certain to be used. - List> reselectInvokers = new ArrayList>(invokers.size() > 1 ? (invokers.size() - 1) : invokers.size()); - - //First, try picking a invoker not in `selected`. - if (availablecheck) { // invoker.isAvailable() should be checked - for (Invoker invoker : invokers) { - if (invoker.isAvailable()) { - if (selected == null || !selected.contains(invoker)) { - reselectInvokers.add(invoker); - } - } - } - if (!reselectInvokers.isEmpty()) { - return loadbalance.select(reselectInvokers, getUrl(), invocation); - } - } else { // do not check invoker.isAvailable() - for (Invoker invoker : invokers) { - if (selected == null || !selected.contains(invoker)) { - reselectInvokers.add(invoker); - } + List> reselectInvokers = new ArrayList<>( + invokers.size() > 1 ? (invokers.size() - 1) : invokers.size()); + + // First, try picking a invoker not in `selected`. + for (Invoker invoker : invokers) { + if (availablecheck && !invoker.isAvailable()) { + continue; } - if (!reselectInvokers.isEmpty()) { - return loadbalance.select(reselectInvokers, getUrl(), invocation); + + if (selected == null || !selected.contains(invoker)) { + reselectInvokers.add(invoker); } } + + if (!reselectInvokers.isEmpty()) { + return loadbalance.select(reselectInvokers, getUrl(), invocation); + } + // Just pick an available invoker using loadbalance policy - { - if (selected != null) { - for (Invoker invoker : selected) { - if ((invoker.isAvailable()) // available first - && !reselectInvokers.contains(invoker)) { - reselectInvokers.add(invoker); - } + if (selected != null) { + for (Invoker invoker : selected) { + if ((invoker.isAvailable()) // available first + && !reselectInvokers.contains(invoker)) { + reselectInvokers.add(invoker); } } - if (!reselectInvokers.isEmpty()) { - return loadbalance.select(reselectInvokers, getUrl(), invocation); - } } + if (!reselectInvokers.isEmpty()) { + return loadbalance.select(reselectInvokers, getUrl(), invocation); + } + return null; } @@ -257,7 +256,7 @@ public String toString() { } protected void checkInvokers(List> invokers, Invocation invocation) { - if (invokers == null || invokers.isEmpty()) { + if (CollectionUtils.isEmpty(invokers)) { throw new RpcException("Failed to invoke the method " + invocation.getMethodName() + " in the service " + getInterface().getName() + ". No provider available for the service " + directory.getUrl().getServiceKey() 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 64d4b24f9b0..b8ae095af6b 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 @@ -65,7 +65,7 @@ public FailbackClusterInvoker(Directory directory) { super(directory); } - private void addFailed(Invocation invocation, AbstractClusterInvoker router) { + private void addFailed(Invocation invocation, AbstractClusterInvoker invoker) { if (retryFuture == null) { synchronized (this) { if (retryFuture == null) { @@ -84,11 +84,11 @@ public void run() { } } } - failed.put(invocation, router); + failed.put(invocation, invoker); } void retryFailed() { - if (failed.size() == 0) { + if (failed.isEmpty()) { return; } for (Map.Entry> entry : new HashMap<>(failed).entrySet()) { 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 a8a984e04eb..2fd1af923c8 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 @@ -86,12 +86,12 @@ public Result invoke(Invocation invocation) throws RpcException { } catch (RpcException e) { if (e.isBiz()) { throw e; - } else { - if (logger.isWarnEnabled()) { - logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e); - } - result = doMockInvoke(invocation, e); } + + if (logger.isWarnEnabled()) { + logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e); + } + result = doMockInvoke(invocation, e); } } return result; 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 869ac524464..f8fdb3178b1 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java @@ -19,6 +19,7 @@ import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; @@ -68,6 +69,8 @@ public void setUp() throws Exception { invokers.add(invoker2); clusterinvoker = new StickyClusterInvoker(dic); + + ExtensionLoader.resetExtensionLoader(LoadBalance.class); } @Test diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java index 0bf0562fd73..ac538b7c9dc 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/StaticDirectoryTest.java @@ -54,12 +54,12 @@ public void testStaticDirectory() { invokers.add(invoker2); invokers.add(invoker3); List> filteredInvokers = router.route(invokers, URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation()); - StaticDirectory staticDirectory = new StaticDirectory(filteredInvokers); - Boolean isAvailable = staticDirectory.isAvailable(); + StaticDirectory staticDirectory = new StaticDirectory<>(filteredInvokers); + boolean isAvailable = staticDirectory.isAvailable(); Assert.assertTrue(!isAvailable); - List newInvokers = staticDirectory.list(new MockDirInvocation()); + List> newInvokers = staticDirectory.list(new MockDirInvocation()); Assert.assertTrue(newInvokers.size() > 0); staticDirectory.destroy(); - Assert.assertTrue(newInvokers.size() == 0); + Assert.assertEquals(0, newInvokers.size()); } } diff --git a/dubbo-cluster/src/test/resources/log4j.xml b/dubbo-cluster/src/test/resources/log4j.xml index 9b7df211e96..df9d68a0fab 100644 --- a/dubbo-cluster/src/test/resources/log4j.xml +++ b/dubbo-cluster/src/test/resources/log4j.xml @@ -19,7 +19,7 @@ - + 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 18ad19f5246..9265287a114 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 @@ -665,6 +665,7 @@ public class Constants { public static final String REQUEST_TAG_KEY = "request.tag"; + public static final String TELNET = "telnet"; /* * private Constants(){ } */ diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java index 31f72e669e7..54de28041b3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java @@ -124,6 +124,20 @@ public static ExtensionLoader getExtensionLoader(Class type) { return loader; } + // For testing purposes only + public static void resetExtensionLoader(Class type) { + ExtensionLoader loader = EXTENSION_LOADERS.get(type); + if (loader != null) { + // Remove all instances associated with this loader as well + Map> classes = loader.getExtensionClasses(); + for (Map.Entry> entry : classes.entrySet()) { + EXTENSION_INSTANCES.remove(entry.getValue()); + } + classes.clear(); + EXTENSION_LOADERS.remove(type); + } + } + private static ClassLoader findClassLoader() { return ClassHelper.getClassLoader(ExtensionLoader.class); } @@ -346,12 +360,8 @@ public boolean hasExtension(String name) { if (name == null || name.length() == 0) { throw new IllegalArgumentException("Extension name == null"); } - try { - this.getExtensionClass(name); - return true; - } catch (Throwable t) { - return false; - } + Class c = this.getExtensionClass(name); + return c != null; } public Set getSupportedExtensions() { @@ -565,11 +575,7 @@ private Class getExtensionClass(String name) { if (name == null) { throw new IllegalArgumentException("Extension name == null"); } - Class clazz = getExtensionClasses().get(name); - if (clazz == null) { - throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!"); - } - return clazz; + return getExtensionClasses().get(name); } private Map> getExtensionClasses() { diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java index 42563d4935f..27d7da6e8b8 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/concurrent/CompletableFutureTaskTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -31,7 +33,6 @@ import java.util.concurrent.TimeUnit; import org.apache.dubbo.common.utils.NamedThreadFactory; -import org.junit.Ignore; import org.junit.Test; @@ -46,7 +47,7 @@ public void testCreate() throws InterruptedException { CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { countDownLatch.countDown(); return true; - },executor); + }, executor); countDownLatch.await(); } @@ -75,7 +76,7 @@ public void testListener() throws InterruptedException { } return "hello"; - },executor); + }, executor); final CountDownLatch countDownLatch = new CountDownLatch(1); completableFuture.thenRunAsync(new Runnable() { @Override @@ -87,13 +88,13 @@ public void run() { } - @Test - @Ignore +@Test public void testCustomExecutor() { Executor mockedExecutor = mock(Executor.class); CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { return 0; }); - completableFuture.thenRunAsync(mock(Runnable.class), verify(mockedExecutor)); + completableFuture.thenRunAsync(mock(Runnable.class), mockedExecutor).whenComplete((s, e) -> + verify(mockedExecutor, times(1)).execute(any(Runnable.class))); } } \ No newline at end of file diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java index fada00eb90f..7cddb97f237 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -74,7 +74,7 @@ public abstract class AbstractConfig implements Serializable { legacyProperties.put("dubbo.service.url", "dubbo.service.address"); // this is only for compatibility - Runtime.getRuntime().addShutdownHook(DubboShutdownHook.getDubboShutdownHook()); + DubboShutdownHook.getDubboShutdownHook().register(); } protected String id; diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java index 90ed2376cd5..05c3643fb93 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java @@ -40,14 +40,17 @@ public static DubboShutdownHook getDubboShutdownHook() { return dubboShutdownHook; } + /** + * Has it already been registered or not? + */ + private final AtomicBoolean registered = new AtomicBoolean(false); /** * Has it already been destroyed or not? */ - private final AtomicBoolean destroyed; + private final AtomicBoolean destroyed= new AtomicBoolean(false); private DubboShutdownHook(String name) { super(name); - this.destroyed = new AtomicBoolean(false); } @Override @@ -55,16 +58,36 @@ public void run() { if (logger.isInfoEnabled()) { logger.info("Run shutdown hook now."); } - destroyAll(); + doDestroy(); + } + + /** + * Register the ShutdownHook + */ + public void register() { + if (!registered.get() && registered.compareAndSet(false, true)) { + Runtime.getRuntime().addShutdownHook(getDubboShutdownHook()); + } + } + + /** + * Unregister the ShutdownHook + */ + public void unregister() { + if (registered.get() && registered.compareAndSet(true, false)) { + Runtime.getRuntime().removeShutdownHook(getDubboShutdownHook()); + } } /** * Destroy all the resources, including registries and protocols. */ - public void destroyAll() { + public void doDestroy() { if (!destroyed.compareAndSet(false, true)) { return; } + // unregister the shutdownHook + unregister(); // destroy all the registries AbstractRegistryFactory.destroyAll(); // destroy all the protocols @@ -88,4 +111,5 @@ private void destroyProtocols() { } } + } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index 66e8d7fc426..579acd0d437 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -170,6 +170,7 @@ private static void putRandomPort(String protocol, Integer port) { protocol = protocol.toLowerCase(); if (!RANDOM_PORT_MAP.containsKey(protocol)) { RANDOM_PORT_MAP.put(protocol, port); + logger.warn("Use random available port(" + port + ") for protocol " + protocol); } } @@ -654,7 +655,6 @@ private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Ma portToBind = getAvailablePort(defaultPort); putRandomPort(name, portToBind); } - logger.warn("Use random available port(" + portToBind + ") for protocol " + name); } } diff --git a/dubbo-config/dubbo-config-api/src/test/resources/log4j.xml b/dubbo-config/dubbo-config-api/src/test/resources/log4j.xml index 4a9fe2e9c4a..5007dd1d1bc 100644 --- a/dubbo-config/dubbo-config-api/src/test/resources/log4j.xml +++ b/dubbo-config/dubbo-config-api/src/test/resources/log4j.xml @@ -18,7 +18,7 @@ - + diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java index 99b538c25e0..6d663655be7 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java @@ -44,6 +44,7 @@ public class SpringExtensionFactory implements ExtensionFactory { public static void addApplicationContext(ApplicationContext context) { contexts.add(context); + DubboShutdownHook.getDubboShutdownHook().unregister(); BeanFactoryUtils.addApplicationListener(context, shutdownHookListener); } @@ -105,11 +106,8 @@ private static class ShutdownHookListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextClosedEvent) { - // we call it anyway since dubbo shutdown hook make sure its destroyAll() is re-entrant. - // pls. note we should not remove dubbo shutdown hook when spring framework is present, this is because - // its shutdown hook may not be installed. DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook(); - shutdownHook.destroyAll(); + shutdownHook.doDestroy(); } } } diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/log4j.xml b/dubbo-config/dubbo-config-spring/src/test/resources/log4j.xml index 63be60179cb..bbb7f03f981 100644 --- a/dubbo-config/dubbo-config-spring/src/test/resources/log4j.xml +++ b/dubbo-config/dubbo-config-spring/src/test/resources/log4j.xml @@ -19,7 +19,7 @@ - + diff --git a/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml b/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml index 18f2b5f1391..f0370700874 100644 --- a/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml +++ b/dubbo-container/dubbo-container-spring/src/test/resources/log4j.xml @@ -19,7 +19,7 @@ - + diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-consumer/src/main/resources/log4j.properties index 63f4e27e3c6..24243814906 100644 --- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.properties index d95684642d3..15a0900f0d2 100644 --- a/dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.properties +++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/log4j.properties @@ -4,4 +4,4 @@ log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n \ No newline at end of file +log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n \ No newline at end of file diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/Cache.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/Cache.java index 4ba84eb31e6..fb2a329fc15 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/Cache.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/Cache.java @@ -17,12 +17,27 @@ package org.apache.dubbo.cache; /** - * Cache + * Cache interface to support storing and retrieval of value against a lookup key. It has two operation get and put. + *
  • put-Storing value against a key.
  • + *
  • get-Retrival of object.
  • + * @see org.apache.dubbo.cache.support.lru.LruCache + * @see org.apache.dubbo.cache.support.jcache.JCache + * @see org.apache.dubbo.cache.support.expiring.ExpiringCache + * @see org.apache.dubbo.cache.support.threadlocal.ThreadLocalCache */ public interface Cache { - + /** + * API to store value against a key + * @param key Unique identifier for the object being store. + * @param value Value getting store + */ void put(Object key, Object value); + /** + * API to return stored value using a key. + * @param key Unique identifier for cache lookup + * @return Return stored object against key + */ Object get(Object key); } diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java index 2fabd94a5f3..77256bb5ee5 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/CacheFactory.java @@ -22,11 +22,21 @@ import org.apache.dubbo.rpc.Invocation; /** - * CacheFactory + * Interface needs to be implemented by all the cache store provider.Along with implementing CacheFactory interface + * entry needs to be added in org.apache.dubbo.cache.CacheFactory file in a classpath META-INF sub directories. + * + * @see Cache */ @SPI("lru") public interface CacheFactory { + /** + * CacheFactory implementation class needs to implement this return underlying cache instance for method against + * url and invocation. + * @param url + * @param invocation + * @return Instance of Cache containing cached value against method url and invocation. + */ @Adaptive("cache") Cache getCache(URL url, Invocation invocation); 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 ee6282659aa..4de9f5a170c 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 @@ -32,17 +32,60 @@ import java.io.Serializable; /** - * CacheFilter + * CacheFilter is a core component of dubbo.Enabling cache key of service,method,consumer or provider dubbo will cache method return value. + * Along with cache key we need to configure cache type. Dubbo default implemented cache types are + *
  • lur
  • + *
  • threadlocal
  • + *
  • jcache
  • + *
  • expiring
  • + * + *
    + *   e.g. 1)<dubbo:service cache="lru" />
    + *        2)<dubbo:service /> <dubbo:method name="method2" cache="threadlocal" /> <dubbo:service/>
    + *        3)<dubbo:provider cache="expiring" />
    + *        4)<dubbo:consumer cache="jcache" />
    + *
    + *If cache type is defined in method level then method level type will get precedence. According to above provided
    + *example, if service has two method, method1 and method2, method2 will have cache type as threadlocal where others will
    + *be backed by lru
    + *
    + * + * @see org.apache.dubbo.rpc.Filter + * @see org.apache.dubbo.cache.support.lru.LruCacheFactory + * @see org.apache.dubbo.cache.support.lru.LruCache + * @see org.apache.dubbo.cache.support.jcache.JCacheFactory + * @see org.apache.dubbo.cache.support.jcache.JCache + * @see org.apache.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory + * @see org.apache.dubbo.cache.support.threadlocal.ThreadLocalCache + * @see org.apache.dubbo.cache.support.expiring.ExpiringCacheFactory + * @see org.apache.dubbo.cache.support.expiring.ExpiringCache + * */ @Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.CACHE_KEY) public class CacheFilter implements Filter { private CacheFactory cacheFactory; + /** + * Dubbo will populate and set the cache factory instance based on service/method/consumer/provider configured + * cache attribute value. Dubbo will search for the class name implementing configured cache in file org.apache.dubbo.cache.CacheFactory + * under META-INF sub folders. + * + * @param cacheFactory instance of CacheFactory based on cache type + */ public void setCacheFactory(CacheFactory cacheFactory) { this.cacheFactory = cacheFactory; } + /** + * If cache is configured, dubbo will invoke method on each method call. If cache value is returned by cache store + * then it will return otherwise call the remote method and return value. If remote method's return valeu has error + * then it will not cache the value. + * @param invoker service + * @param invocation invocation. + * @return Cache returned value if found by the underlying cache store. If cache miss it will call target method. + * @throws RpcException + */ @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { if (cacheFactory != null && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.CACHE_KEY))) { @@ -66,7 +109,10 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept } return invoker.invoke(invocation); } - + + /** + * Cache value wrapper. + */ static class ValueWrapper implements Serializable{ private static final long serialVersionUID = -1777337318019193256L; diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java index ad95e770e0d..2522ce775a8 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java @@ -26,12 +26,29 @@ import java.util.concurrent.ConcurrentMap; /** - * AbstractCacheFactory + * AbstractCacheFactory is a default implementation of {@link CacheFactory}. It abstract out the key formation from URL along with + * invocation method. It initially check if the value for key already present in own local in-memory store then it won't check underlying storage cache {@link Cache}. + * Internally it used {@link ConcurrentHashMap} to store do level-1 caching. + * + * @see CacheFactory + * @see org.apache.dubbo.cache.support.jcache.JCacheFactory + * @see org.apache.dubbo.cache.support.lru.LruCacheFactory + * @see org.apache.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory + * @see org.apache.dubbo.cache.support.expiring.ExpiringCacheFactory */ public abstract class AbstractCacheFactory implements CacheFactory { + /** + * This is used to store factory level-1 cached data. + */ private final ConcurrentMap caches = new ConcurrentHashMap(); + /** + * Takes URL and invocation instance and return cache instance for a given url. + * @param url url of the method + * @param invocation invocation context. + * @return Instance of cache store used as storage for caching return values. + */ @Override public Cache getCache(URL url, Invocation invocation) { url = url.addParameter(Constants.METHOD_KEY, invocation.getMethodName()); @@ -44,6 +61,11 @@ public Cache getCache(URL url, Invocation invocation) { return cache; } + /** + * Takes url as an method argument and return new instance of cache store implemented by AbstractCacheFactory subclass. + * @param url url of the method + * @return Create and return new instance of cache store used as storage for caching return values. + */ protected abstract Cache createCache(URL url); } diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCache.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCache.java index 9fd61f59504..9295718dfc7 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCache.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCache.java @@ -24,6 +24,22 @@ /** * ExpiringCache - With the characteristic of expiration time. */ + +/** + * This class store the cache value with the characteristic of expiration time. If a service,method,consumer or provided is configured with key cache + * with value expiring, dubbo initialize the instance of this class using {@link ExpiringCacheFactory} to store method's returns value + * to server from store without making method call. + *
    + *     e.g. 1) <dubbo:service cache="expiring" cache.seconds="60" cache.interval="10"/>
    + *          2) <dubbo:consumer cache="expiring" />
    + * 
    + *
  • It used constructor argument url instance cache.seconds value to decide time to live of cached object.Default value of it is 180 second.
  • + *
  • It used constructor argument url instance cache.interval value for cache value expiration interval.Default value of this is 4 second
  • + * @see Cache + * @see ExpiringCacheFactory + * @see org.apache.dubbo.cache.support.AbstractCacheFactory + * @see org.apache.dubbo.cache.filter.CacheFilter + */ public class ExpiringCache implements Cache { private final Map store; @@ -37,11 +53,22 @@ public ExpiringCache(URL url) { this.store = expiringMap; } + /** + * API to store value against a key in the calling thread scope. + * @param key Unique identifier for the object being store. + * @param value Value getting store + */ @Override public void put(Object key, Object value) { store.put(key, value); } + /** + * API to return stored value using a key against the calling thread specific store. + * @param key Unique identifier for cache lookup + * @return Return stored object against key + */ + @Override public Object get(Object key) { return store.get(key); diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java index 381a04ee243..5259d74b6eb 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactory.java @@ -20,11 +20,23 @@ import org.apache.dubbo.cache.support.AbstractCacheFactory; import org.apache.dubbo.common.URL; + /** - * ExpiringCacheFactory + * Implement {@link org.apache.dubbo.cache.CacheFactory} by extending {@link AbstractCacheFactory} and provide + * instance of new {@link ExpiringCache}. + * + * @see AbstractCacheFactory + * @see ExpiringCache + * @see Cache */ + public class ExpiringCacheFactory extends AbstractCacheFactory { - + + /** + * Takes url as an method argument and return new instance of cache store implemented by JCache. + * @param url url of the method + * @return ExpiringCache instance of cache + */ @Override protected Cache createCache(URL url) { return new ExpiringCache(url); diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCache.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCache.java index 2a28204573f..92e16423e3d 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCache.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCache.java @@ -30,7 +30,14 @@ import java.util.concurrent.TimeUnit; /** - * JCache + * This class store the cache value per thread. If a service,method,consumer or provided is configured with key cache + * with value jcache, dubbo initialize the instance of this class using {@link JCacheFactory} to store method's returns value + * to server from store without making method call. + * + * @see Cache + * @see JCacheFactory + * @see org.apache.dubbo.cache.support.AbstractCacheFactory + * @see org.apache.dubbo.cache.filter.CacheFilter */ public class JCache implements org.apache.dubbo.cache.Cache { diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java index bd1e9d5c612..c4d713f0b17 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/jcache/JCacheFactory.java @@ -20,11 +20,26 @@ import org.apache.dubbo.cache.support.AbstractCacheFactory; import org.apache.dubbo.common.URL; +import javax.cache.spi.CachingProvider; + /** - * JCacheFactory + * JCacheFactory is factory class to provide instance of javax spi cache.Implement {@link org.apache.dubbo.cache.CacheFactory} by + * extending {@link AbstractCacheFactory} and provide + * @see AbstractCacheFactory + * @see JCache + * @see org.apache.dubbo.cache.filter.CacheFilter + * @see Cache + * @see CachingProvider + * @see javax.cache.Cache + * @see javax.cache.CacheManager */ public class JCacheFactory extends AbstractCacheFactory { + /** + * Takes url as an method argument and return new instance of cache store implemented by JCache. + * @param url url of the method + * @return JCache instance of cache + */ @Override protected Cache createCache(URL url) { return new JCache(url); diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCache.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCache.java index 11a00ac60c9..1d745804d83 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCache.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCache.java @@ -23,22 +23,55 @@ import java.util.Map; /** - * LruCache + * This class store the cache value per thread. If a service,method,consumer or provided is configured with key cache + * with value lru, dubbo initialize the instance of this class using {@link LruCacheFactory} to store method's returns value + * to server from store without making method call. + *
    + *     e.g. 1) <dubbo:service cache="lru" cache.size="5000"/>
    + *          2) <dubbo:consumer cache="lru" />
    + * 
    + *
    + * LruCache uses url's cache.size value for its max store size, if nothing is provided then
    + * default value will be 1000
    + * 
    + * + * @see Cache + * @see LruCacheFactory + * @see org.apache.dubbo.cache.support.AbstractCacheFactory + * @see org.apache.dubbo.cache.filter.CacheFilter */ public class LruCache implements Cache { + /** + * This is used to store cache records + */ private final Map store; + /** + * Initialize LruCache, it uses constructor argument cache.size value as its storage max size. + * If nothing is provided then it will use 1000 as default value. + * @param url A valid URL instance + */ public LruCache(URL url) { final int max = url.getParameter("cache.size", 1000); this.store = new LRUCache(max); } + /** + * API to store value against a key in the calling thread scope. + * @param key Unique identifier for the object being store. + * @param value Value getting store + */ @Override public void put(Object key, Object value) { store.put(key, value); } + /** + * API to return stored value using a key against the calling thread specific store. + * @param key Unique identifier for cache lookup + * @return Return stored object against key + */ @Override public Object get(Object key) { return store.get(key); diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java index 775cdd0237f..cda21292e8f 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/lru/LruCacheFactory.java @@ -21,10 +21,20 @@ import org.apache.dubbo.common.URL; /** - * LruCacheFactory + * Implement {@link org.apache.dubbo.cache.CacheFactory} by extending {@link AbstractCacheFactory} and provide + * instance of new {@link LruCache}. + * + * @see AbstractCacheFactory + * @see LruCache + * @see Cache */ public class LruCacheFactory extends AbstractCacheFactory { + /** + * Takes url as an method argument and return new instance of cache store implemented by LruCache. + * @param url url of the method + * @return ThreadLocalCache instance of cache + */ @Override protected Cache createCache(URL url) { return new LruCache(url); diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCache.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCache.java index 4b557bebbbd..0f35ed3315e 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCache.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCache.java @@ -23,12 +23,33 @@ import java.util.Map; /** - * ThreadLocalCache + * This class store the cache value per thread. If a service,method,consumer or provided is configured with key cache + * with value threadlocal, dubbo initialize the instance of this class using {@link ThreadLocalCacheFactory} to store method's returns value + * to server from store without making method call. + *
    + *      e.g. <dubbo:service cache="threadlocal" />
    + *  
    + *
    + * As this ThreadLocalCache stores key-value in memory without any expiry or delete support per thread wise, if number threads and number of key-value are high then jvm should be
    + * configured with appropriate memory.
    + * 
    + * + * @see org.apache.dubbo.cache.support.AbstractCacheFactory + * @see org.apache.dubbo.cache.filter.CacheFilter + * @see Cache */ public class ThreadLocalCache implements Cache { + /** + * Thread local variable to store cached data. + */ private final ThreadLocal> store; + /** + * Taken URL as an argument to create an instance of ThreadLocalCache. In this version of implementation constructor + * argument is not getting used in the scope of this class. + * @param url + */ public ThreadLocalCache(URL url) { this.store = new ThreadLocal>() { @Override @@ -38,11 +59,21 @@ protected Map initialValue() { }; } + /** + * API to store value against a key in the calling thread scope. + * @param key Unique identifier for the object being store. + * @param value Value getting store + */ @Override public void put(Object key, Object value) { store.get().put(key, value); } + /** + * API to return stored value using a key against the calling thread specific store. + * @param key Unique identifier for cache lookup + * @return Return stored object against key + */ @Override public Object get(Object key) { return store.get().get(key); diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactory.java index e456f2696b7..bde16f63bd6 100644 --- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactory.java +++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/threadlocal/ThreadLocalCacheFactory.java @@ -21,10 +21,20 @@ import org.apache.dubbo.common.URL; /** - * ThreadLocalCacheFactory + * Implement {@link org.apache.dubbo.cache.CacheFactory} by extending {@link AbstractCacheFactory} and provide + * instance of new {@link ThreadLocalCache}. Note about this class is, each thread does not have a local copy of factory. + * + * @see AbstractCacheFactory + * @see ThreadLocalCache + * @see Cache */ public class ThreadLocalCacheFactory extends AbstractCacheFactory { + /** + * Takes url as an method argument and return new instance of cache store implemented by ThreadLocalCache. + * @param url url of the method + * @return ThreadLocalCache instance of cache + */ @Override protected Cache createCache(URL url) { return new ThreadLocalCache(url); diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validation.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validation.java index 1cf10225fb0..d6775f0e270 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validation.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validation.java @@ -22,11 +22,16 @@ import org.apache.dubbo.common.extension.SPI; /** - * Validation + * Instance of Validation interface provide instance of {@link Validator} based on the value of validation attribute. */ @SPI("jvalidation") public interface Validation { + /** + * Return the instance of {@link Validator} for a given url. + * @param url Invocation url + * @return Instance of {@link Validator} + */ @Adaptive(Constants.VALIDATION_KEY) Validator getValidator(URL url); diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validator.java index cea93d85fec..b1565ba4b68 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validator.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/Validator.java @@ -17,7 +17,8 @@ package org.apache.dubbo.validation; /** - * Validator + * Instance of validator class is an extension to perform validation on method input parameter before the actual method invocation. + * */ public interface Validator { 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 e22908067ed..2af761a0958 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 @@ -29,17 +29,52 @@ import org.apache.dubbo.validation.Validator; /** - * ValidationFilter + * ValidationFilter invoke the validation by finding the right {@link Validator} instance based on the + * configured validation attribute value of invoker url before the actual method invocation. + * + *
    + *     e.g. <dubbo:method name="save" validation="jvalidation" />
    + *     In the above configuration a validation has been configured of type jvalidation. On invocation of method save
    + *     dubbo will invoke {@link org.apache.dubbo.validation.support.jvalidation.JValidator}
    + * 
    + * + * To add a new type of validation + *
    + *     e.g. <dubbo:method name="save" validation="special" />
    + *     where "special" is representing a validator for special character.
    + * 
    + * + * developer needs to do + *
    + * 1)Implement a SpecialValidation.java class (package name xxx.yyy.zzz) either by implementing {@link Validation} or extending {@link org.apache.dubbo.validation.support.AbstractValidation}
    + * 2)Implement a SpecialValidator.java class (package name xxx.yyy.zzz)
    + * 3)Add an entry special=xxx.yyy.zzz.SpecialValidation under META-INF folders org.apache.dubbo.validation.Validation file. + * + * @see Validation + * @see Validator + * @see Filter + * @see org.apache.dubbo.validation.support.AbstractValidation */ @Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.VALIDATION_KEY, order = 10000) public class ValidationFilter implements Filter { private Validation validation; + /** + * Sets the validation instance for ValidationFilter + * @param validation Validation instance injected by dubbo framework based on "validation" attribute value. + */ public void setValidation(Validation validation) { this.validation = validation; } + /** + * Perform the validation of before invoking the actual method based on validation attribute value. + * @param invoker service + * @param invocation invocation. + * @return Method invocation result + * @throws RpcException Throws RpcException if validation failed or any other runtime exception occurred. + */ @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { if (validation != null && !invocation.getMethodName().startsWith("$") diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/AbstractValidation.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/AbstractValidation.java index 0f1f629512b..17f6646f526 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/AbstractValidation.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/AbstractValidation.java @@ -24,7 +24,12 @@ import java.util.concurrent.ConcurrentMap; /** - * AbstractValidation + * AbstractValidation is abstract class for Validation interface. It helps low level Validation implementation classes + * by performing common task e.g. key formation, storing instance of validation class to avoid creation of unnecessary + * copy of validation instance and faster execution. + * + * @see Validation + * @see Validator */ public abstract class AbstractValidation implements Validation { diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java index 8e04ba5f225..e0859897f1e 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidation.java @@ -21,10 +21,17 @@ import org.apache.dubbo.validation.support.AbstractValidation; /** - * JValidation + * Creates a new instance of {@link Validator} using input argument url. + * @see AbstractValidation + * @see Validator */ public class JValidation extends AbstractValidation { + /** + * Return new instance of {@link JValidator} + * @param url Valid URL instance + * @return Instance of JValidator + */ @Override protected Validator createValidator(URL url) { return new JValidator(url); diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java index a7c8afe3f29..9feccb22e72 100644 --- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java +++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java @@ -68,7 +68,10 @@ import java.util.concurrent.ConcurrentHashMap; /** - * JValidator + * Implementation of JValidation. JValidation is invoked if configuration validation attribute value is 'jvalidation'. + *
    + *     e.g. <dubbo:method name="save" validation="jvalidation" />
    + * 
    */ public class JValidator implements Validator { diff --git a/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml b/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml index ff12d5b0915..f5c44f1f4ef 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml +++ b/dubbo-registry/dubbo-registry-api/src/test/resources/log4j.xml @@ -19,7 +19,7 @@ - + diff --git a/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java b/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java index 95459b282b6..8c8b8ea6660 100644 --- a/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java +++ b/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java @@ -34,7 +34,7 @@ import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance; import org.apache.dubbo.rpc.cluster.router.script.ScriptRouter; import org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory; - +import org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -1014,6 +1014,37 @@ public void test_Notified_acceptProtocol2() { List> invokers = registryDirectory.list(invocation); Assert.assertEquals(2, invokers.size()); } + + @Test + public void test_Notified_withGroupFilter() { + URL directoryUrl = noMeaningUrl.addParameterAndEncoded(Constants.REFER_KEY, "interface" + service + "&group=group1,group2"); + RegistryDirectory directory = this.getRegistryDirectory(directoryUrl); + URL provider1 = URL.valueOf("dubbo://10.134.108.1:20880?methods=getXXX&group=group1&mock=false"); + URL provider2 = URL.valueOf("dubbo://10.134.108.1:20880?methods=getXXX&group=group2&mock=false"); + + List providers = new ArrayList<>(); + providers.add(provider1); + providers.add(provider2); + directory.notify(providers); + + invocation = new RpcInvocation(); + invocation.setMethodName("getXXX"); + List> invokers = directory.list(invocation); + + Assert.assertEquals(2, invokers.size()); + Assert.assertTrue(invokers.get(0) instanceof MockClusterInvoker); + Assert.assertTrue(invokers.get(1) instanceof MockClusterInvoker); + + directoryUrl = noMeaningUrl.addParameterAndEncoded(Constants.REFER_KEY, "interface" + service + "&group=group1"); + directory = this.getRegistryDirectory(directoryUrl); + directory.notify(providers); + + invokers = directory.list(invocation); + + Assert.assertEquals(2, invokers.size()); + Assert.assertFalse(invokers.get(0) instanceof MockClusterInvoker); + Assert.assertFalse(invokers.get(1) instanceof MockClusterInvoker); + } enum Param { MORGAN, diff --git a/dubbo-registry/dubbo-registry-default/src/test/resources/log4j.xml b/dubbo-registry/dubbo-registry-default/src/test/resources/log4j.xml index 9e129907d34..c8d6d8c5b58 100644 --- a/dubbo-registry/dubbo-registry-default/src/test/resources/log4j.xml +++ b/dubbo-registry/dubbo-registry-default/src/test/resources/log4j.xml @@ -32,7 +32,7 @@ - + diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java index 580238b0338..a5ceda82f88 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java @@ -17,7 +17,9 @@ package org.apache.dubbo.remoting.telnet.support; 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.StringUtils; import org.apache.dubbo.remoting.Channel; import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.telnet.TelnetHandler; @@ -49,14 +51,20 @@ public String telnet(Channel channel, String message) throws RemotingException { } if (command.length() > 0) { if (extensionLoader.hasExtension(command)) { - try { - String result = extensionLoader.getExtension(command).telnet(channel, message); - if (result == null) { - return null; + if (commandEnabled(channel.getUrl(), command)) { + try { + String result = extensionLoader.getExtension(command).telnet(channel, message); + if (result == null) { + return null; + } + buf.append(result); + } catch (Throwable t) { + buf.append(t.getMessage()); } - buf.append(result); - } catch (Throwable t) { - buf.append(t.getMessage()); + } else { + buf.append("Command: "); + buf.append(command); + buf.append(" disabled"); } } else { buf.append("Unsupported command: "); @@ -72,4 +80,21 @@ public String telnet(Channel channel, String message) throws RemotingException { return buf.toString(); } + private boolean commandEnabled(URL url, String command) { + boolean commandEnable = false; + String supportCommands = url.getParameter(Constants.TELNET); + if (StringUtils.isEmpty(supportCommands)) { + commandEnable = true; + } else { + String[] commands = Constants.COMMA_SPLIT_PATTERN.split(supportCommands); + for (String c : commands) { + if (command.equals(c)) { + commandEnable = true; + break; + } + } + } + return commandEnable; + } + } diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml b/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml index b91d2d6ad7a..927212a49b1 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml +++ b/dubbo-remoting/dubbo-remoting-api/src/test/resources/log4j.xml @@ -19,7 +19,7 @@ - + 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 82591ab90c1..b250c1e1f1c 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 @@ -17,6 +17,7 @@ package org.apache.dubbo.rpc.protocol.dubbo.telnet; import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.CompatibleTypeUtils; import org.apache.dubbo.common.utils.PojoUtils; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; @@ -75,6 +76,14 @@ private static boolean isMatch(Class[] types, List args) { } if (ReflectUtils.isPrimitive(arg.getClass())) { + if (arg instanceof String && type.isEnum()) { + try { + CompatibleTypeUtils.compatibleTypeConvert(arg, type); + } catch (RuntimeException e) { + return false; + } + continue; + } if (!ReflectUtils.isPrimitive(type)) { return false; } 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 ced3d067751..14ab1242f6b 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 @@ -26,6 +26,7 @@ import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.ProxyFactory; import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -51,6 +52,11 @@ public static void setUpBeforeClass() throws Exception { public void setUp() throws Exception { } + @AfterClass + public static void tearDownAfterClass() { + ProtocolUtils.closeAll(); + } + @Test public void test_Normal_available() { URL url = URL.valueOf("dubbo://127.0.0.1:20883/org.apache.dubbo.rpc.protocol.dubbo.IDemoService"); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboLazyConnectTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboLazyConnectTest.java index 4efad6f9af2..31a4421e76f 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboLazyConnectTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboLazyConnectTest.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -40,6 +41,11 @@ public static void setUpBeforeClass() throws Exception { public void setUp() throws Exception { } + @AfterClass + public static void tearDownAfterClass() { + ProtocolUtils.closeAll(); + } + @Test(expected = RpcException.class) public void testSticky1() { URL url = URL.valueOf("dubbo://127.0.0.1:9090/org.apache.dubbo.rpc.protocol.dubbo.IDemoService"); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ExplicitCallbackTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ExplicitCallbackTest.java index 3c8aecdd39f..e7a2b2a8837 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ExplicitCallbackTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ExplicitCallbackTest.java @@ -49,6 +49,7 @@ public class ExplicitCallbackTest { @After public void tearDown() { destroyService(); + ProtocolUtils.closeAll(); } public void exportService() { diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java index ce43473025b..04c3645824a 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java @@ -23,6 +23,8 @@ import org.apache.dubbo.rpc.ProxyFactory; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl; +import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; +import org.junit.After; import org.junit.Assert; import org.junit.Test; @@ -36,6 +38,11 @@ public class MultiThreadTest { private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + @After + public void after() { + ProtocolUtils.closeAll(); + } + @Test public void testDubboMultiThreadInvoke() throws Exception { Exporter rpcExporter = protocol.export(proxy.getInvoker(new DemoServiceImpl(), DemoService.class, URL.valueOf("dubbo://127.0.0.1:20259/TestService"))); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java index f9cca922c11..43297a9d6ba 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java @@ -22,8 +22,10 @@ import org.apache.dubbo.rpc.ProxyFactory; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl; +import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; import org.apache.dubbo.rpc.service.EchoService; +import org.junit.After; import org.junit.Assert; import org.junit.Test; @@ -31,6 +33,11 @@ public class RpcFilterTest { private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + @After + public void after() { + ProtocolUtils.closeAll(); + } + @Test public void testRpcFilter() throws Exception { DemoService service = new DemoServiceImpl(); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java index 357b0321d36..db85cc51b3d 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java @@ -47,7 +47,7 @@ public interface DemoService { Type enumlength(Type... types); -// Type enumlength(Type type); + Type getType(Type type); String get(CustomArgument arg1); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java index e404af0e46c..ed38344a324 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java @@ -71,8 +71,8 @@ public Type enumlength(Type... types) { return Type.Lower; return types[0]; } - - public Type enumlength(Type type) { + + public Type getType(Type type) { return type; } diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java index a785330aa86..dc63c8b8b53 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java @@ -108,6 +108,23 @@ public void testInvokeByPassingNullValue() throws RemotingException { } } + @Test + public void testInvokeByPassingEnumValue() throws RemotingException { + mockInvoker = mock(Invoker.class); + given(mockInvoker.getInterface()).willReturn(DemoService.class); + given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo")); + given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok")); + mockChannel = mock(Channel.class); + given(mockChannel.getAttribute("telnet.service")).willReturn(null); + given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555")); + given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886")); + + DubboProtocol.getDubboProtocol().export(mockInvoker); + String result = invoke.telnet(mockChannel, "getType(\"High\")"); + assertTrue(result.contains("ok")); + } + + @SuppressWarnings("unchecked") @Test public void testInvokeAutoFindMethod() throws RemotingException { diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/resources/log4j.xml b/dubbo-rpc/dubbo-rpc-dubbo/src/test/resources/log4j.xml index 0af90b6084a..3c5d2ba218e 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/resources/log4j.xml +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/resources/log4j.xml @@ -33,9 +33,9 @@ - - + diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/fst/FstObjectOutputTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/fst/FstObjectOutputTest.java index ecf2335d88f..8126b6f3fe6 100644 --- a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/fst/FstObjectOutputTest.java +++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/fst/FstObjectOutputTest.java @@ -18,6 +18,7 @@ import org.apache.dubbo.common.serialize.model.AnimalEnum; import org.apache.dubbo.common.serialize.model.person.FullAddress; +import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -41,6 +42,11 @@ public void setUp() { this.fstObjectOutput = new FstObjectOutput(byteArrayOutputStream); } + @After + public void tearDown() throws IOException { + new FstObjectInput(new ByteArrayInputStream(new byte[]{0})); + } + @Test public void testWriteBool() throws IOException { diff --git a/pom.xml b/pom.xml index 8f3c0e5a762..6c2c92494d5 100644 --- a/pom.xml +++ b/pom.xml @@ -276,6 +276,9 @@ release + + 2.11.1 + @@ -289,6 +292,18 @@ none + + + org.apache.logging.log4j + log4j-api + ${log4j2_version} + + + org.apache.logging.log4j + log4j-core + ${log4j2_version} + +