diff --git a/dubbo/README.md b/dubbo/README.md
new file mode 100644
index 0000000000..dec02f5cfc
--- /dev/null
+++ b/dubbo/README.md
@@ -0,0 +1,4 @@
+## Relevant articles:
+
+- [Intro to Dubbo](http://www.baeldung.com/dubbo-intro)
+
diff --git a/dubbo/pom.xml b/dubbo/pom.xml
new file mode 100644
index 0000000000..3faef99e8d
--- /dev/null
+++ b/dubbo/pom.xml
@@ -0,0 +1,72 @@
+
+ 4.0.0
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+ dubbo
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 2.5.7
+ 3.4.11
+ 0.10
+ 2.19.1
+
+
+
+
+ com.alibaba
+ dubbo
+ ${dubbo.version}
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+ org.apache.zookeeper
+ zookeeper
+ ${zookeeper.version}
+
+
+
+ com.101tec
+ zkclient
+ ${zkclient.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.8
+
+
+
+ maven-surefire-plugin
+ ${surefire.version}
+
+
+ **/*LiveTest.java
+
+
+
+
+
+
+
diff --git a/dubbo/src/main/java/com/alibaba/dubbo/registry/simple/SimpleRegistryService.java b/dubbo/src/main/java/com/alibaba/dubbo/registry/simple/SimpleRegistryService.java
new file mode 100644
index 0000000000..bf4a5e201c
--- /dev/null
+++ b/dubbo/src/main/java/com/alibaba/dubbo/registry/simple/SimpleRegistryService.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 1999-2011 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.registry.simple;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.logger.Logger;
+import com.alibaba.dubbo.common.logger.LoggerFactory;
+import com.alibaba.dubbo.common.utils.ConcurrentHashSet;
+import com.alibaba.dubbo.common.utils.NetUtils;
+import com.alibaba.dubbo.common.utils.UrlUtils;
+import com.alibaba.dubbo.registry.NotifyListener;
+import com.alibaba.dubbo.registry.RegistryService;
+import com.alibaba.dubbo.registry.support.AbstractRegistry;
+import com.alibaba.dubbo.rpc.RpcContext;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * SimpleRegistryService
+ *
+ * @author william.liangf
+ */
+public class SimpleRegistryService extends AbstractRegistry {
+
+ private final static Logger logger = LoggerFactory.getLogger(SimpleRegistryService.class);
+ private final ConcurrentMap> remoteRegistered = new ConcurrentHashMap>();
+ private final ConcurrentMap>> remoteSubscribed = new ConcurrentHashMap>>();
+
+ public SimpleRegistryService() {
+ super(new URL("dubbo", NetUtils.getLocalHost(), 0, RegistryService.class.getName(), "file", "N/A"));
+ }
+
+ public boolean isAvailable() {
+ return true;
+ }
+
+ public List lookup(URL url) {
+ List urls = new ArrayList();
+ for (URL u : getRegistered()) {
+ if (UrlUtils.isMatch(url, u)) {
+ urls.add(u);
+ }
+ }
+ return urls;
+ }
+
+ public void register(URL url) {
+ String client = RpcContext.getContext().getRemoteAddressString();
+ Set urls = remoteRegistered.get(client);
+ if (urls == null) {
+ remoteRegistered.putIfAbsent(client, new ConcurrentHashSet());
+ urls = remoteRegistered.get(client);
+ }
+ urls.add(url);
+ super.register(url);
+ registered(url);
+ }
+
+ public void unregister(URL url) {
+ String client = RpcContext.getContext().getRemoteAddressString();
+ Set urls = remoteRegistered.get(client);
+ if (urls != null && urls.size() > 0) {
+ urls.remove(url);
+ }
+ super.unregister(url);
+ unregistered(url);
+ }
+
+ public void subscribe(URL url, NotifyListener listener) {
+ if (getUrl().getPort() == 0) {
+ URL registryUrl = RpcContext.getContext().getUrl();
+ if (registryUrl != null && registryUrl.getPort() > 0
+ && RegistryService.class.getName().equals(registryUrl.getPath())) {
+ super.setUrl(registryUrl);
+ super.register(registryUrl);
+ }
+ }
+ String client = RpcContext.getContext().getRemoteAddressString();
+ ConcurrentMap> clientListeners = remoteSubscribed.get(client);
+ if (clientListeners == null) {
+ remoteSubscribed.putIfAbsent(client, new ConcurrentHashMap>());
+ clientListeners = remoteSubscribed.get(client);
+ }
+ Set listeners = clientListeners.get(url);
+ if (listeners == null) {
+ clientListeners.putIfAbsent(url, new ConcurrentHashSet());
+ listeners = clientListeners.get(url);
+ }
+ listeners.add(listener);
+ super.subscribe(url, listener);
+ subscribed(url, listener);
+ }
+
+ public void unsubscribe(URL url, NotifyListener listener) {
+ if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
+ && url.getParameter(Constants.REGISTER_KEY, true)) {
+ unregister(url);
+ }
+ String client = RpcContext.getContext().getRemoteAddressString();
+ Map> clientListeners = remoteSubscribed.get(client);
+ if (clientListeners != null && clientListeners.size() > 0) {
+ Set listeners = clientListeners.get(url);
+ if (listeners != null && listeners.size() > 0) {
+ listeners.remove(listener);
+ }
+ }
+ }
+
+ protected void registered(URL url) {
+ for (Map.Entry> entry : getSubscribed().entrySet()) {
+ URL key = entry.getKey();
+ if (UrlUtils.isMatch(key, url)) {
+ List list = lookup(key);
+ for (NotifyListener listener : entry.getValue()) {
+ listener.notify(list);
+ }
+ }
+ }
+ }
+
+ protected void unregistered(URL url) {
+ for (Map.Entry> entry : getSubscribed().entrySet()) {
+ URL key = entry.getKey();
+ if (UrlUtils.isMatch(key, url)) {
+ List list = lookup(key);
+ for (NotifyListener listener : entry.getValue()) {
+ listener.notify(list);
+ }
+ }
+ }
+ }
+
+ protected void subscribed(final URL url, final NotifyListener listener) {
+ if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
+ new Thread(new Runnable() {
+ public void run() {
+ Map> map = new HashMap>();
+ for (URL u : getRegistered()) {
+ if (UrlUtils.isMatch(url, u)) {
+ String service = u.getServiceInterface();
+ List list = map.get(service);
+ if (list == null) {
+ list = new ArrayList();
+ map.put(service, list);
+ }
+ list.add(u);
+ }
+ }
+ for (List list : map.values()) {
+ try {
+ listener.notify(list);
+ } catch (Throwable e) {
+ logger.warn("Discard to notify " + url.getServiceKey() + " to listener " + listener);
+ }
+ }
+ }
+ }, "DubboMonitorNotifier").start();
+ } else {
+ List list = lookup(url);
+ try {
+ listener.notify(list);
+ } catch (Throwable e) {
+ logger.warn("Discard to notify " + url.getServiceKey() + " to listener " + listener);
+ }
+ }
+ }
+
+ public void disconnect() {
+ String client = RpcContext.getContext().getRemoteAddressString();
+ if (logger.isInfoEnabled()) {
+ logger.info("Disconnected " + client);
+ }
+ Set urls = remoteRegistered.get(client);
+ if (urls != null && urls.size() > 0) {
+ for (URL url : urls) {
+ unregister(url);
+ }
+ }
+ Map> listeners = remoteSubscribed.get(client);
+ if (listeners != null && listeners.size() > 0) {
+ for (Map.Entry> entry : listeners.entrySet()) {
+ URL url = entry.getKey();
+ for (NotifyListener listener : entry.getValue()) {
+ unsubscribe(url, listener);
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsFailoverServiceImpl.java b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsFailoverServiceImpl.java
new file mode 100644
index 0000000000..2ad26beac3
--- /dev/null
+++ b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsFailoverServiceImpl.java
@@ -0,0 +1,14 @@
+package com.baeldung.dubbo.remote;
+
+/**
+ * @author aiet
+ */
+public class GreetingsFailoverServiceImpl implements GreetingsService {
+
+ @Override
+ public String sayHi(String name) {
+ System.out.println("failover implementation");
+ return "hi, failover " + name;
+ }
+
+}
diff --git a/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsService.java b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsService.java
new file mode 100644
index 0000000000..337c4c83e7
--- /dev/null
+++ b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsService.java
@@ -0,0 +1,10 @@
+package com.baeldung.dubbo.remote;
+
+/**
+ * @author aiet
+ */
+public interface GreetingsService {
+
+ String sayHi(String name);
+
+}
diff --git a/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsServiceImpl.java b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsServiceImpl.java
new file mode 100644
index 0000000000..a11d9588d8
--- /dev/null
+++ b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsServiceImpl.java
@@ -0,0 +1,14 @@
+package com.baeldung.dubbo.remote;
+
+/**
+ * @author aiet
+ */
+public class GreetingsServiceImpl implements GreetingsService {
+
+ @Override
+ public String sayHi(String name) {
+ System.out.println("default implementation");
+ return "hi, " + name;
+ }
+
+}
diff --git a/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsServiceSpecialImpl.java b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsServiceSpecialImpl.java
new file mode 100644
index 0000000000..37449da8d8
--- /dev/null
+++ b/dubbo/src/main/java/com/baeldung/dubbo/remote/GreetingsServiceSpecialImpl.java
@@ -0,0 +1,20 @@
+package com.baeldung.dubbo.remote;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+/**
+ * @author aiet
+ */
+public class GreetingsServiceSpecialImpl implements GreetingsService {
+
+ @Override
+ public String sayHi(String name) {
+ try {
+ System.out.println("specially called");
+ SECONDS.sleep(5);
+ } catch (Exception ignored) {
+ }
+ return "hi, " + name;
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/APIConfigurationLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/APIConfigurationLiveTest.java
new file mode 100644
index 0000000000..27c77bf9df
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/APIConfigurationLiveTest.java
@@ -0,0 +1,57 @@
+package com.baeldung.dubbo;
+
+import com.alibaba.dubbo.config.ApplicationConfig;
+import com.alibaba.dubbo.config.ReferenceConfig;
+import com.alibaba.dubbo.config.RegistryConfig;
+import com.alibaba.dubbo.config.ServiceConfig;
+import com.baeldung.dubbo.remote.GreetingsService;
+import com.baeldung.dubbo.remote.GreetingsServiceImpl;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author aiet
+ */
+public class APIConfigurationLiveTest {
+
+ @Before
+ public void initProvider() {
+ ApplicationConfig application = new ApplicationConfig();
+ application.setName("demo-provider");
+ application.setVersion("1.0");
+
+ RegistryConfig registryConfig = new RegistryConfig();
+ registryConfig.setAddress("multicast://224.1.1.1:9090");
+
+ ServiceConfig service = new ServiceConfig<>();
+ service.setApplication(application);
+ service.setRegistry(registryConfig);
+ service.setInterface(GreetingsService.class);
+ service.setRef(new GreetingsServiceImpl());
+
+ service.export();
+ }
+
+ @Test
+ public void givenProviderConsumer_whenSayHi_thenGotResponse() {
+ ApplicationConfig application = new ApplicationConfig();
+ application.setName("demo-consumer");
+ application.setVersion("1.0");
+
+ RegistryConfig registryConfig = new RegistryConfig();
+ registryConfig.setAddress("multicast://224.1.1.1:9090");
+
+ ReferenceConfig reference = new ReferenceConfig<>();
+ reference.setApplication(application);
+ reference.setRegistry(registryConfig);
+ reference.setInterface(GreetingsService.class);
+
+ GreetingsService greetingsService = reference.get();
+ String hiMessage = greetingsService.sayHi("baeldung");
+
+ assertEquals("hi, baeldung", hiMessage);
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/ClusterDynamicLoadBalanceLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/ClusterDynamicLoadBalanceLiveTest.java
new file mode 100644
index 0000000000..408d5af368
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/ClusterDynamicLoadBalanceLiveTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.OptionalDouble;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author aiet
+ */
+public class ClusterDynamicLoadBalanceLiveTest {
+
+ private ExecutorService executorService;
+
+ @Before
+ public void initRemote() {
+ executorService = Executors.newFixedThreadPool(2);
+ executorService.submit(() -> {
+ ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-default.xml");
+ remoteContext.start();
+ });
+ executorService.submit(() -> {
+ SECONDS.sleep(2);
+ ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special.xml");
+ backupRemoteContext.start();
+ return null;
+ });
+ }
+
+ @Test
+ public void givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced() throws InterruptedException {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-lb.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+ List elapseList = new ArrayList<>(6);
+ for (int i = 0; i < 6; i++) {
+ long current = System.currentTimeMillis();
+ String hiMessage = greetingsService.sayHi("baeldung");
+ assertNotNull(hiMessage);
+ elapseList.add(System.currentTimeMillis() - current);
+ SECONDS.sleep(1);
+ }
+
+ OptionalDouble avgElapse = elapseList
+ .stream()
+ .mapToLong(e -> e)
+ .average();
+ assertTrue(avgElapse.isPresent());
+ assertTrue(avgElapse.getAsDouble() > 1666.0);
+
+ }
+
+ @After
+ public void destroy() {
+ executorService.shutdown();
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/ClusterFailoverLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/ClusterFailoverLiveTest.java
new file mode 100644
index 0000000000..721363d3d1
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/ClusterFailoverLiveTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author aiet
+ */
+public class ClusterFailoverLiveTest {
+
+ private ExecutorService executorService;
+
+ @Before
+ public void initRemote() {
+ executorService = Executors.newFixedThreadPool(2);
+ executorService.submit(() -> {
+ ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special.xml");
+ backupRemoteContext.start();
+ });
+ executorService.submit(() -> {
+ ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-failover.xml");
+ remoteContext.start();
+ });
+
+ }
+
+ @Test
+ public void givenProviderCluster_whenConsumerSaysHi_thenGotFailoverResponse() {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-failtest.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+ String hiMessage = greetingsService.sayHi("baeldung");
+
+ assertNotNull(hiMessage);
+ assertEquals("hi, failover baeldung", hiMessage);
+ }
+
+ @After
+ public void destroy() {
+ executorService.shutdown();
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/ClusterFailsafeLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/ClusterFailsafeLiveTest.java
new file mode 100644
index 0000000000..29a10fa20a
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/ClusterFailsafeLiveTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+/**
+ * @author aiet
+ */
+public class ClusterFailsafeLiveTest {
+
+ private ExecutorService executorService;
+
+ @Before
+ public void initRemote() {
+ executorService = Executors.newFixedThreadPool(1);
+ executorService.submit(() -> {
+ ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special-failsafe.xml");
+ remoteContext.start();
+ });
+ }
+
+ @Test
+ public void givenProviderCluster_whenConsumerSaysHi_thenGotFailsafeResponse() {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-failtest.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+ String hiMessage = greetingsService.sayHi("baeldung");
+
+ assertNull(hiMessage);
+ }
+
+ @After
+ public void destroy() {
+ executorService.shutdown();
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/ClusterLoadBalanceLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/ClusterLoadBalanceLiveTest.java
new file mode 100644
index 0000000000..b880dfe843
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/ClusterLoadBalanceLiveTest.java
@@ -0,0 +1,66 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.OptionalDouble;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author aiet
+ */
+public class ClusterLoadBalanceLiveTest {
+
+ private ExecutorService executorService;
+
+ @Before
+ public void initRemote() {
+ executorService = Executors.newFixedThreadPool(2);
+ executorService.submit(() -> {
+ ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-default.xml");
+ remoteContext.start();
+ });
+ executorService.submit(() -> {
+ ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special.xml");
+ backupRemoteContext.start();
+ });
+ }
+
+ @Test
+ public void givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced() {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-lb.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+ List elapseList = new ArrayList<>(6);
+ for (int i = 0; i < 6; i++) {
+ long current = System.currentTimeMillis();
+ String hiMessage = greetingsService.sayHi("baeldung");
+ assertNotNull(hiMessage);
+ elapseList.add(System.currentTimeMillis() - current);
+ }
+
+ OptionalDouble avgElapse = elapseList
+ .stream()
+ .mapToLong(e -> e)
+ .average();
+ assertTrue(avgElapse.isPresent());
+ System.out.println(avgElapse.getAsDouble());
+ assertTrue(avgElapse.getAsDouble() > 2500.0);
+
+ }
+
+ @After
+ public void destroy() {
+ executorService.shutdown();
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/MulticastRegistryLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/MulticastRegistryLiveTest.java
new file mode 100644
index 0000000000..13dc5d3f1e
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/MulticastRegistryLiveTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author aiet
+ */
+public class MulticastRegistryLiveTest {
+
+ private ClassPathXmlApplicationContext remoteContext;
+
+ @Before
+ public void initRemote() {
+ remoteContext = new ClassPathXmlApplicationContext("multicast/provider-app.xml");
+ remoteContext.start();
+ }
+
+ @Test
+ public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("multicast/consumer-app.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+ String hiMessage = greetingsService.sayHi("baeldung");
+
+ assertNotNull(hiMessage);
+ assertEquals("hi, baeldung", hiMessage);
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/ResultCacheLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/ResultCacheLiveTest.java
new file mode 100644
index 0000000000..401ebc9b94
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/ResultCacheLiveTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author aiet
+ */
+public class ResultCacheLiveTest {
+
+ private ClassPathXmlApplicationContext remoteContext;
+
+ @Before
+ public void initRemote() {
+ remoteContext = new ClassPathXmlApplicationContext("multicast/provider-app-special.xml");
+ remoteContext.start();
+ }
+
+ @Test
+ public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("multicast/consumer-app.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+
+ long before = System.currentTimeMillis();
+ String hiMessage = greetingsService.sayHi("baeldung");
+
+ long timeElapsed = System.currentTimeMillis() - before;
+ assertTrue(timeElapsed > 5000);
+ assertNotNull(hiMessage);
+ assertEquals("hi, baeldung", hiMessage);
+
+
+ before = System.currentTimeMillis();
+ hiMessage = greetingsService.sayHi("baeldung");
+ timeElapsed = System.currentTimeMillis() - before;
+ assertTrue(timeElapsed < 1000);
+ assertNotNull(hiMessage);
+ assertEquals("hi, baeldung", hiMessage);
+ }
+
+}
diff --git a/dubbo/src/test/java/com/baeldung/dubbo/SimpleRegistryLiveTest.java b/dubbo/src/test/java/com/baeldung/dubbo/SimpleRegistryLiveTest.java
new file mode 100644
index 0000000000..72f15cf7ec
--- /dev/null
+++ b/dubbo/src/test/java/com/baeldung/dubbo/SimpleRegistryLiveTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.dubbo;
+
+import com.baeldung.dubbo.remote.GreetingsService;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author aiet
+ */
+public class SimpleRegistryLiveTest {
+
+ private ClassPathXmlApplicationContext remoteContext;
+ private ClassPathXmlApplicationContext registryContext;
+
+ @Before
+ public void initRemote() {
+ registryContext = new ClassPathXmlApplicationContext("simple/registry.xml");
+ registryContext.start();
+
+ remoteContext = new ClassPathXmlApplicationContext("simple/provider-app.xml");
+ remoteContext.start();
+ }
+
+ @Test
+ public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
+ ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("simple/consumer-app.xml");
+ localContext.start();
+ GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
+ String hiMessage = greetingsService.sayHi("baeldung");
+
+ assertNotNull(hiMessage);
+ assertEquals("hi, baeldung", hiMessage);
+ }
+
+}
diff --git a/dubbo/src/test/resources/cluster/consumer-app-failtest.xml b/dubbo/src/test/resources/cluster/consumer-app-failtest.xml
new file mode 100644
index 0000000000..beb982db22
--- /dev/null
+++ b/dubbo/src/test/resources/cluster/consumer-app-failtest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/cluster/consumer-app-lb.xml b/dubbo/src/test/resources/cluster/consumer-app-lb.xml
new file mode 100644
index 0000000000..268e21b902
--- /dev/null
+++ b/dubbo/src/test/resources/cluster/consumer-app-lb.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/cluster/provider-app-default.xml b/dubbo/src/test/resources/cluster/provider-app-default.xml
new file mode 100644
index 0000000000..cb51bc1771
--- /dev/null
+++ b/dubbo/src/test/resources/cluster/provider-app-default.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/cluster/provider-app-failover.xml b/dubbo/src/test/resources/cluster/provider-app-failover.xml
new file mode 100644
index 0000000000..95cbee1f90
--- /dev/null
+++ b/dubbo/src/test/resources/cluster/provider-app-failover.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/cluster/provider-app-special-failsafe.xml b/dubbo/src/test/resources/cluster/provider-app-special-failsafe.xml
new file mode 100644
index 0000000000..7a7a139bb3
--- /dev/null
+++ b/dubbo/src/test/resources/cluster/provider-app-special-failsafe.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/cluster/provider-app-special.xml b/dubbo/src/test/resources/cluster/provider-app-special.xml
new file mode 100644
index 0000000000..8e5dc07d61
--- /dev/null
+++ b/dubbo/src/test/resources/cluster/provider-app-special.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/log4j.properties b/dubbo/src/test/resources/log4j.properties
new file mode 100644
index 0000000000..4c15f1b4e0
--- /dev/null
+++ b/dubbo/src/test/resources/log4j.properties
@@ -0,0 +1,6 @@
+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{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
\ No newline at end of file
diff --git a/dubbo/src/test/resources/multicast/consumer-app.xml b/dubbo/src/test/resources/multicast/consumer-app.xml
new file mode 100644
index 0000000000..da9a41fd61
--- /dev/null
+++ b/dubbo/src/test/resources/multicast/consumer-app.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/multicast/provider-app-special.xml b/dubbo/src/test/resources/multicast/provider-app-special.xml
new file mode 100644
index 0000000000..4b22b5aace
--- /dev/null
+++ b/dubbo/src/test/resources/multicast/provider-app-special.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/multicast/provider-app.xml b/dubbo/src/test/resources/multicast/provider-app.xml
new file mode 100644
index 0000000000..065d5ddad8
--- /dev/null
+++ b/dubbo/src/test/resources/multicast/provider-app.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/simple/consumer-app.xml b/dubbo/src/test/resources/simple/consumer-app.xml
new file mode 100644
index 0000000000..91f7a666e4
--- /dev/null
+++ b/dubbo/src/test/resources/simple/consumer-app.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/simple/provider-app.xml b/dubbo/src/test/resources/simple/provider-app.xml
new file mode 100644
index 0000000000..9880172249
--- /dev/null
+++ b/dubbo/src/test/resources/simple/provider-app.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dubbo/src/test/resources/simple/registry.xml b/dubbo/src/test/resources/simple/registry.xml
new file mode 100644
index 0000000000..9d1372da10
--- /dev/null
+++ b/dubbo/src/test/resources/simple/registry.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file