<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to BaseMicroServicesVerticle</title><link>https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/</link><description>Recent changes to BaseMicroServicesVerticle</description><atom:link href="https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/feed" rel="self"/><language>en</language><lastBuildDate>Tue, 24 Apr 2018 20:15:10 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/feed" rel="self" type="application/rss+xml"/><item><title>BaseMicroServicesVerticle modified by Gary Cheng</title><link>https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v4
+++ v5
@@ -2,93 +2,244 @@
 package com.ezshop.common;

 import io.reactivex.Single;
-import io.vertx.core.Handler;
+import io.vertx.circuitbreaker.CircuitBreakerOptions;
 import io.vertx.core.http.HttpMethod;
-import io.vertx.reactivex.core.Future;
+import io.vertx.core.json.JsonObject;
+import io.vertx.reactivex.circuitbreaker.CircuitBreaker;
+import io.vertx.reactivex.core.AbstractVerticle;
 import io.vertx.reactivex.core.buffer.Buffer;
-import io.vertx.reactivex.ext.web.Router;
-import io.vertx.reactivex.ext.web.RoutingContext;
+import io.vertx.reactivex.core.http.HttpClient;
 import io.vertx.reactivex.ext.web.client.HttpRequest;
 import io.vertx.reactivex.ext.web.client.HttpResponse;
 import io.vertx.reactivex.ext.web.client.WebClient;
-import io.vertx.reactivex.ext.web.handler.CorsHandler;
+import io.vertx.reactivex.servicediscovery.ServiceDiscovery;
+import io.vertx.reactivex.servicediscovery.types.HttpEndpoint;
+import io.vertx.servicediscovery.Record;
+import io.vertx.servicediscovery.ServiceDiscoveryOptions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.ezshop.common.ConfigKeys.*;

 /**
- * The abstract verticle which work as HTTP server
+ * The base verticle class which provided some common functions include service discovery
  *
  * @author Gary Cheng
  */
-public abstract class BaseHttpMicroServicesVerticle extends BaseMicroServicesVerticle {
+public abstract class BaseMicroServicesVerticle extends AbstractVerticle {
+    protected static final String KEY_NAME = "name";
+
     private static final Logger logger = LoggerFactory.getLogger(BaseMicroServicesVerticle.class);

-    /**
-     * Enable CORS
-     *
-     * @param router
-     */
-    protected void enableCorsSupport(Router router) {
-        Set&amp;lt;String&amp;gt; allowedHeaders = new HashSet&amp;lt;&amp;gt;();
-        allowedHeaders.add("x-requested-with");
-        allowedHeaders.add("Access-Control-Allow-Origin");
-        allowedHeaders.add("origin");
-        allowedHeaders.add("Content-Type");
-        allowedHeaders.add("accept");
-
-        CorsHandler corsHandler = CorsHandler.create("*").allowedHeaders(allowedHeaders);
-        Arrays.asList(HttpMethod.values()).stream().forEach(method -&amp;gt; corsHandler.allowedMethod(method));
-        router.route().handler(corsHandler);
-    }
-
-    /**
-     * Dispatch a HTTP request to a HttpEndPoint service
-     *
-     * @param context Routing context
-     * @param serviceName the name of service
-     * @param uri the uri at HttpEndPoint service
-     * @param errorHandler the async error handler
-     */
-    protected void dispatchRequest(RoutingContext context, String serviceName, String uri, Handler errorHandler) {
-        logger.debug("Dispatch Http Request {} to {} service", uri, serviceName);
-        this.getCircuitBreaker(serviceName).&amp;lt;Void&amp;gt;rxExecuteCommand(
-                future -&amp;gt; this.dispatchRequestHandler(context, serviceName, uri, future))
-                .subscribe(v -&amp;gt; logger.debug("dispatch request completed"), errorHandler::handle);
-    }
-
-    protected void dispatchRequestHandler(RoutingContext context, String serviceName, String uri, Future&amp;lt;Void&amp;gt; future) {
-        this.getWebEndPoint(serviceName)
-                .subscribe(webClient -&amp;gt; invokeDispatchHttpRequest(context, webClient, uri, future),
-                        throwable -&amp;gt; future.fail("Service [" + serviceName + "] not published"));
-    }
-
-    private void invokeDispatchHttpRequest(RoutingContext context, WebClient webClient, String uri, Future&amp;lt;Void&amp;gt; future) {
-        logger.debug("invokeDispatchHttpRequest, uri:{}", uri);
-        HttpRequest&amp;lt;Buffer&amp;gt; httpRequest = webClient.request(context.request().method(), uri);
-        context.request().headers().getDelegate().forEach(header -&amp;gt; httpRequest.putHeader(header.getKey(), header.getValue()));
-        if (context.user() != null) {
-            httpRequest.putHeader("user-principal", context.user().principal().encode());
-        }
+    protected ServiceDiscovery discovery;
+    private Record publishedRecord;
+    private Map&amp;lt;String, CircuitBreaker=""&amp;gt; circuitBreakerMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
+    private Map&amp;lt;String, Object=""&amp;gt; serviceEndPointMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
+
+    @Override
+    public void start() {
+        logger.debug("Starting verticle - {}", this.getClass().getName());
+        logger.debug("Config:{}", this.config().encodePrettily());
+        this.discovery = ServiceDiscovery.create(vertx, new ServiceDiscoveryOptions().setBackendConfiguration(this.getServiceDiscoveryConfig()));
+    }
+
+    @Override
+    public void stop() {
+        logger.debug("Stopping verticle - {}", this.getClass().getName());
+        this.serviceEndPointMap.keySet().stream().forEach(serviceName -&amp;gt; this.closeCachedEndPoint(serviceName));
+        this.serviceEndPointMap.clear();
+        this.circuitBreakerMap.values().stream().forEach(circuitBreaker -&amp;gt; circuitBreaker.close());
+        this.circuitBreakerMap.clear();
+        this.unpublishRecord().subscribe(b -&amp;gt; discovery.close());
+    }
+
+    /**
+     * Return Service discovery configure, the default implementation store them in verticle's config()
+     *
+     * @return Service discovery configure
+     */
+    protected JsonObject getServiceDiscoveryConfig() {
+        return this.config();
+    }
+
+    /**
+     * Return circuit breaker of service by service name
+     *
+     * @param serviceName the name of service
+     * @return circuit breaker of service
+     */
+    protected final CircuitBreaker getCircuitBreaker(String serviceName) {
+        logger.debug("Get CircuitBreaker of service {}", serviceName);
+        CircuitBreaker circuitBreaker = circuitBreakerMap.get(serviceName);
+        if (null == circuitBreaker) {
+            circuitBreaker = this.createCircuitBreaker(serviceName);
+            this.circuitBreakerMap.put(serviceName, circuitBreaker);
+        }
+        return circuitBreaker;
+    }
+
+    /**
+     * Create circuit breaker for service
+     *
+     * @param serviceName the name of service
+     * @return circuit breaker of service
+     */
+    protected CircuitBreaker createCircuitBreaker(String serviceName) {
+        logger.debug("Create CircuitBreaker for service {}", serviceName);
+        String circuitBreakerName = serviceName + "-" + "circuit-breaker";
+        CircuitBreakerOptions options = new CircuitBreakerOptions()
+                .setMaxFailures(5)
+                .setTimeout(5000)
+                .setResetTimeout(10000)
+                .setFallbackOnFailure(true);
+        return CircuitBreaker.create(circuitBreakerName, vertx, options)
+                .openHandler(v -&amp;gt; {
+                    logger.debug("{} opened", circuitBreakerName);
+                    this.closeCachedEndPoint(serviceName);
+                })
+                .halfOpenHandler(v -&amp;gt; logger.debug("{} half opened", circuitBreakerName))
+                .closeHandler(v -&amp;gt; logger.debug("{} closed", circuitBreakerName));
+    }
+
+    /**
+     * Return an async HttpClient by service name
+     *
+     * @param serviceName the name of service
+     * @return
+     */
+    protected final Single&amp;lt;HttpClient&amp;gt; getHttpEndPoint(String serviceName) {
+        logger.debug("Get HTTP client by service name[{}]", serviceName);
+        Object endPoint = this.serviceEndPointMap.get(serviceName);
+        if (null != endPoint &amp;amp;&amp;amp; endPoint instanceof HttpClient) {
+            return Single.just((HttpClient) endPoint);
+        } else {
+            return HttpEndpoint.rxGetClient(discovery, new JsonObject().put(KEY_NAME, serviceName))
+                    .doOnSuccess(httpClient -&amp;gt; this.serviceEndPointMap.put(serviceName, httpClient));
+        }
+    }
+
+    /**
+     * Return an async HttpClient by service name
+     *
+     * @param serviceName the name of service
+     * @return
+     */
+    protected final Single&amp;lt;WebClient&amp;gt; getWebEndPoint(String serviceName) {
+        logger.debug("Get Web client by service name[{}]", serviceName);
+        Object endPoint = this.serviceEndPointMap.get(serviceName);
+        if (null != endPoint &amp;amp;&amp;amp; endPoint instanceof WebClient) {
+            return Single.just((WebClient) endPoint);
+        } else {
+            logger.debug("Getting Web client from ServiceDiscovery...");
+            return HttpEndpoint.rxGetWebClient(discovery, new JsonObject().put(KEY_NAME, serviceName))
+                    .doOnSuccess(webClient -&amp;gt; this.serviceEndPointMap.put(serviceName, webClient));
+        }
+    }
+
+    /**
+     * Publish a HttpEndPoint service to ServiceDiscovery
+     *
+     * @param serviceName the name of service to be published
+     * @param config      the configure of HttpEndPoint
+     * @return
+     */
+    protected final Single&amp;lt;Record&amp;gt; publishHttpEndPoint(String serviceName, JsonObject config) {
+        String host = config.getString(KEY_HOST, "localhost");
+        Integer port = config.getInteger(KEY_PORT, 8080);
+        String root = config.getString(KEY_ROOT, "/");
+        logger.debug("publishHttpEndPoint service:{}, host:{}, port:{}, root:{}", serviceName, host, port, root);
+        return this.publishRecord(HttpEndpoint.createRecord(serviceName, host, port, root));
+    }
+
+    /**
+     * Publish a service record to ServiceDiscovery
+     *
+     * @param record record to publish
+     * @return
+     */
+    protected Single&amp;lt;Record&amp;gt; publishRecord(Record record) {
+        return this.unpublishRecord()
+                .flatMap(b -&amp;gt; discovery.rxPublish(record))
+                .doOnSuccess(r -&amp;gt; this.publishedRecord = r);
+    }
+
+    /**
+     * Invoke a restful service by service name
+     *
+     * @param serviceName the name of service
+     * @param method      HTTP method
+     * @param uri         uri of request
+     * @param body        body of request
+     * @return result as JsonObject
+     */
+    protected Single&amp;lt;JsonObject&amp;gt; invokeRestfulService(String serviceName, HttpMethod method, String uri, JsonObject body) {
+        logger.debug("invokeRestfulService, service name:{}, uri:{}", serviceName, uri);
+        return this.getCircuitBreaker(serviceName).rxExecuteCommand(future -&amp;gt; this.getWebEndPoint(serviceName).subscribe(
+                webClient -&amp;gt; {
+                    HttpRequest request = webClient.request(method, uri);
+                    Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
+                    if (null == body) {
+                        result = request.rxSend();
+                    } else {
+                        result = request.rxSendJsonObject(body);
+                    }
+                    result.map(HttpResponse::bodyAsJsonObject).subscribe(future::complete, future::fail);
+                },
+                throwable -&amp;gt; future.fail("Service [" + serviceName + "] not found"))
+        );
+    }
+
+    /**
+     * Invoke a restful service by given host and port
+     *
+     * @param method HTTP method
+     * @param port   port of EndPoint
+     * @param host   host of EndPoint
+     * @param uri    uri of request
+     * @param body   body of request
+     * @return
+     */
+    protected Single&amp;lt;JsonObject&amp;gt; invokeRestful(HttpMethod method, int port, String host, String uri, JsonObject body) {
+        logger.debug("invokeRestfulService, host:{}, port:{}, uri:{}", host, port, uri);
+        HttpRequest&amp;lt;Buffer&amp;gt; request = WebClient.create(vertx).request(method, port, host, uri);
         Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
-        if (null != context.request().formAttributes() &amp;amp;&amp;amp; !context.request().formAttributes().isEmpty()) {
-            result = httpRequest.rxSendForm(context.request().formAttributes());
-        } else if (null != context.getBody()) {
-            result = httpRequest.rxSendBuffer(context.getBody());
+        if (null == body) {
+            result = request.rxSend();
         } else {
-            result = httpRequest.rxSend();
-        }
-        result.subscribe(response -&amp;gt; {
-            if (!context.response().ended()) {
-                context.response().setStatusCode(response.statusCode());
-                response.headers().getDelegate().forEach(header -&amp;gt; context.response().putHeader(header.getKey(), header.getValue()));
-                context.response().end(response.body());
+            result = request.rxSendJsonObject(body);
+        }
+        return result.map(HttpResponse::bodyAsJsonObject);
+    }
+
+    private Single&amp;lt;Boolean&amp;gt; unpublishRecord() {
+        return Single.create(emitter -&amp;gt; {
+            if (null != this.publishedRecord) {
+                discovery.rxUnpublish(this.publishedRecord.getRegistration())
+                        .subscribe(() -&amp;gt; {
+                            logger.debug("Service {} unpublished", this.publishedRecord.getName());
+                            this.publishedRecord = null;
+                            emitter.onSuccess(true);
+                        }, emitter::onError);
+            } else {
+                emitter.onSuccess(true);
             }
-            future.complete();
-        }, future::fail);
+        });
+    }
+
+    private void closeCachedEndPoint(String serviceName) {
+        Object endPoint = this.serviceEndPointMap.get(serviceName);
+        if (null != endPoint) {
+            logger.debug("Close cached EndPoint for service {}", serviceName);
+            if (endPoint instanceof WebClient) {
+                ((WebClient) endPoint).close();
+            } else if (endPoint instanceof HttpClient) {
+                ((HttpClient) endPoint).close();
+            }
+            this.serviceEndPointMap.remove(serviceName);
+        }
     }
 }
 ~~~
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Gary Cheng</dc:creator><pubDate>Tue, 24 Apr 2018 20:15:10 -0000</pubDate><guid>https://sourceforge.netaea841e6950512e045e658f9212534b6d22e165b</guid></item><item><title>BaseMicroServicesVerticle modified by Gary Cheng</title><link>https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v3
+++ v4
@@ -1,246 +1,94 @@
 ~~~
-package com.example.microservices.com;
+package com.ezshop.common;

 import io.reactivex.Single;
-import io.vertx.circuitbreaker.CircuitBreakerOptions;
+import io.vertx.core.Handler;
 import io.vertx.core.http.HttpMethod;
-import io.vertx.core.json.JsonObject;
-import io.vertx.reactivex.circuitbreaker.CircuitBreaker;
-import io.vertx.reactivex.core.AbstractVerticle;
+import io.vertx.reactivex.core.Future;
 import io.vertx.reactivex.core.buffer.Buffer;
-import io.vertx.reactivex.core.http.HttpClient;
+import io.vertx.reactivex.ext.web.Router;
+import io.vertx.reactivex.ext.web.RoutingContext;
 import io.vertx.reactivex.ext.web.client.HttpRequest;
 import io.vertx.reactivex.ext.web.client.HttpResponse;
 import io.vertx.reactivex.ext.web.client.WebClient;
-import io.vertx.reactivex.servicediscovery.ServiceDiscovery;
-import io.vertx.reactivex.servicediscovery.types.HttpEndpoint;
-import io.vertx.servicediscovery.Record;
-import io.vertx.servicediscovery.ServiceDiscoveryOptions;
+import io.vertx.reactivex.ext.web.handler.CorsHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;

 /**
- * The base verticle class which provided some common functions include service discovery
+ * The abstract verticle which work as HTTP server
  *
  * @author Gary Cheng
  */
-public abstract class BaseMicroServicesVerticle extends AbstractVerticle {
-    protected static final String KEY_SERVICE_NAME = "service.name";
-    protected static final String KEY_HOST = "host";
-    protected static final String KEY_PORT = "port";
-    protected static final String KEY_ROOT = "root";
-    protected static final String KEY_NAME = "name";
-
+public abstract class BaseHttpMicroServicesVerticle extends BaseMicroServicesVerticle {
     private static final Logger logger = LoggerFactory.getLogger(BaseMicroServicesVerticle.class);

-    protected ServiceDiscovery discovery;
-    private Record publishedRecord;
-    private Map&amp;lt;String, CircuitBreaker=""&amp;gt; circuitBreakerMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
-    private Map&amp;lt;String, Object=""&amp;gt; serviceEndPointMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
+    /**
+     * Enable CORS
+     *
+     * @param router
+     */
+    protected void enableCorsSupport(Router router) {
+        Set&amp;lt;String&amp;gt; allowedHeaders = new HashSet&amp;lt;&amp;gt;();
+        allowedHeaders.add("x-requested-with");
+        allowedHeaders.add("Access-Control-Allow-Origin");
+        allowedHeaders.add("origin");
+        allowedHeaders.add("Content-Type");
+        allowedHeaders.add("accept");

-    @Override
-    public void start() {
-        logger.debug("Starting verticle - {}", this.getClass().getName());
-        logger.debug("Config:{}", this.config().encodePrettily());
-        this.discovery = ServiceDiscovery.create(vertx, new ServiceDiscoveryOptions().setBackendConfiguration(this.getServiceDiscoveryConfig()));
-    }
-
-    @Override
-    public void stop() {
-        logger.debug("Stopping verticle - {}", this.getClass().getName());
-        this.serviceEndPointMap.keySet().stream().forEach(serviceName -&amp;gt; this.closeCachedEndPoint(serviceName));
-        this.serviceEndPointMap.clear();
-        this.circuitBreakerMap.values().stream().forEach(circuitBreaker -&amp;gt; circuitBreaker.close());
-        this.circuitBreakerMap.clear();
-        this.unpublishRecord().subscribe(b -&amp;gt; discovery.close());
+        CorsHandler corsHandler = CorsHandler.create("*").allowedHeaders(allowedHeaders);
+        Arrays.asList(HttpMethod.values()).stream().forEach(method -&amp;gt; corsHandler.allowedMethod(method));
+        router.route().handler(corsHandler);
     }

     /**
-     * Return Service discovery configure, the default implementation store them in verticle's config()
+     * Dispatch a HTTP request to a HttpEndPoint service
      *
-     * @return Service discovery configure
+     * @param context Routing context
+     * @param serviceName the name of service
+     * @param uri the uri at HttpEndPoint service
+     * @param errorHandler the async error handler
      */
-    protected JsonObject getServiceDiscoveryConfig() {
-        return this.config();
+    protected void dispatchRequest(RoutingContext context, String serviceName, String uri, Handler errorHandler) {
+        logger.debug("Dispatch Http Request {} to {} service", uri, serviceName);
+        this.getCircuitBreaker(serviceName).&amp;lt;Void&amp;gt;rxExecuteCommand(
+                future -&amp;gt; this.dispatchRequestHandler(context, serviceName, uri, future))
+                .subscribe(v -&amp;gt; logger.debug("dispatch request completed"), errorHandler::handle);
     }

-    /**
-     * Return circuit breaker of service by service name
-     *
-     * @param serviceName the name of service
-     * @return circuit breaker of service
-     */
-    protected final CircuitBreaker getCircuitBreaker(String serviceName) {
-        logger.debug("Get CircuitBreaker of service {}", serviceName);
-        CircuitBreaker circuitBreaker = circuitBreakerMap.get(serviceName);
-        if (null == circuitBreaker) {
-            circuitBreaker = this.createCircuitBreaker(serviceName);
-            this.circuitBreakerMap.put(serviceName, circuitBreaker);
-        }
-        return circuitBreaker;
+    protected void dispatchRequestHandler(RoutingContext context, String serviceName, String uri, Future&amp;lt;Void&amp;gt; future) {
+        this.getWebEndPoint(serviceName)
+                .subscribe(webClient -&amp;gt; invokeDispatchHttpRequest(context, webClient, uri, future),
+                        throwable -&amp;gt; future.fail("Service [" + serviceName + "] not published"));
     }

-    /**
-     * Create circuit breaker for service
-     *
-     * @param serviceName the name of service
-     * @return circuit breaker of service
-     */
-    protected CircuitBreaker createCircuitBreaker(String serviceName) {
-        logger.debug("Create CircuitBreaker for service {}", serviceName);
-        String circuitBreakerName = serviceName + "-" + "circuit-breaker";
-        CircuitBreakerOptions options = new CircuitBreakerOptions()
-                .setMaxFailures(5)
-                .setTimeout(5000)
-                .setResetTimeout(10000)
-                .setFallbackOnFailure(true);
-        return CircuitBreaker.create(circuitBreakerName, vertx, options)
-                .openHandler(v -&amp;gt; {
-                    logger.debug("{} opened", circuitBreakerName);
-                    this.closeCachedEndPoint(serviceName);
-                })
-                .halfOpenHandler(v -&amp;gt; logger.debug("{} half opened", circuitBreakerName))
-                .closeHandler(v -&amp;gt; logger.debug("{} closed", circuitBreakerName));
-    }
-
-    /**
-     * Return an async HttpClient by service name
-     *
-     * @param serviceName the name of service
-     * @return
-     */
-    protected final Single&amp;lt;HttpClient&amp;gt; getHttpEndPoint(String serviceName) {
-        logger.debug("Get HTTP client by service name[{}]", serviceName);
-        Object endPoint = this.serviceEndPointMap.get(serviceName);
-        if (null != endPoint &amp;amp;&amp;amp; endPoint instanceof HttpClient) {
-            return Single.just((HttpClient) endPoint);
+    private void invokeDispatchHttpRequest(RoutingContext context, WebClient webClient, String uri, Future&amp;lt;Void&amp;gt; future) {
+        logger.debug("invokeDispatchHttpRequest, uri:{}", uri);
+        HttpRequest&amp;lt;Buffer&amp;gt; httpRequest = webClient.request(context.request().method(), uri);
+        context.request().headers().getDelegate().forEach(header -&amp;gt; httpRequest.putHeader(header.getKey(), header.getValue()));
+        if (context.user() != null) {
+            httpRequest.putHeader("user-principal", context.user().principal().encode());
+        }
+        Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
+        if (null != context.request().formAttributes() &amp;amp;&amp;amp; !context.request().formAttributes().isEmpty()) {
+            result = httpRequest.rxSendForm(context.request().formAttributes());
+        } else if (null != context.getBody()) {
+            result = httpRequest.rxSendBuffer(context.getBody());
         } else {
-            return HttpEndpoint.rxGetClient(discovery, new JsonObject().put(KEY_NAME, serviceName))
-                    .doOnSuccess(httpClient -&amp;gt; this.serviceEndPointMap.put(serviceName, httpClient));
+            result = httpRequest.rxSend();
         }
-    }
-
-    /**
-     * Return an async HttpClient by service name
-     *
-     * @param serviceName the name of service
-     * @return
-     */
-    protected final Single&amp;lt;WebClient&amp;gt; getWebEndPoint(String serviceName) {
-        logger.debug("Get Web client by service name[{}]", serviceName);
-        Object endPoint = this.serviceEndPointMap.get(serviceName);
-        if (null != endPoint &amp;amp;&amp;amp; endPoint instanceof WebClient) {
-            return Single.just((WebClient) endPoint);
-        } else {
-            logger.debug("Getting Web client from ServiceDiscovery...");
-            return HttpEndpoint.rxGetWebClient(discovery, new JsonObject().put(KEY_NAME, serviceName))
-                    .doOnSuccess(webClient -&amp;gt; this.serviceEndPointMap.put(serviceName, webClient));
-        }
-    }
-
-    /**
-     * Publish a HttpEndPoint service to ServiceDiscovery
-     *
-     * @param config the configure of HttpEndPoint
-     * @return
-     */
-    protected final Single&amp;lt;Record&amp;gt; publishHttpEndPoint(JsonObject config) {
-        String serviceName = config.getString(KEY_SERVICE_NAME);
-        String host = config.getString(KEY_HOST, "localhost");
-        Integer port = config.getInteger(KEY_PORT, 8080);
-        String root = config.getString(KEY_ROOT, "/");
-        return this.publishRecord(HttpEndpoint.createRecord(serviceName, host, port, root));
-    }
-
-    /**
-     * Publish a service record to ServiceDiscovery
-     *
-     * @param record record to publish
-     * @return
-     */
-    protected Single&amp;lt;Record&amp;gt; publishRecord(Record record) {
-        return this.unpublishRecord()
-                .flatMap(b -&amp;gt; discovery.rxPublish(record))
-                .doOnSuccess(r -&amp;gt; this.publishedRecord = r);
-    }
-
-    /**
-     * Invoke a restful service by service name
-     *
-     * @param serviceName the name of service
-     * @param method      HTTP method
-     * @param uri         uri of request
-     * @param body        body of request
-     * @return result as JsonObject
-     */
-    protected Single&amp;lt;JsonObject&amp;gt; invokeRestfulService(String serviceName, HttpMethod method, String uri, JsonObject body) {
-        logger.debug("invokeRestfulService, service name:{}, uri:{}", serviceName, uri);
-        return this.getCircuitBreaker(serviceName).rxExecuteCommand(future -&amp;gt; this.getWebEndPoint(serviceName).subscribe(
-                webClient -&amp;gt; {
-                    HttpRequest request = webClient.request(method, uri);
-                    Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
-                    if (null == body) {
-                        result = request.rxSend();
-                    } else {
-                        result = request.rxSendJsonObject(body);
-                    }
-                    result.map(HttpResponse::bodyAsJsonObject).subscribe(future::complete, future::fail);
-                },
-                throwable -&amp;gt; future.fail("Service [" + serviceName + "] not found"))
-        );
-    }
-
-    /**
-     * Invoke a restful service by given host and port
-     *
-     * @param method HTTP method
-     * @param port   port of EndPoint
-     * @param host   host of EndPoint
-     * @param uri    uri of request
-     * @param body   body of request
-     * @return
-     */
-    protected Single&amp;lt;JsonObject&amp;gt; invokeRestful(HttpMethod method, int port, String host, String uri, JsonObject body) {
-        logger.debug("invokeRestfulService, host:{}, port:{}, uri:{}", host, port, uri);
-        HttpRequest&amp;lt;Buffer&amp;gt; request = WebClient.create(vertx).request(method, port, host, uri);
-        Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
-        if (null == body) {
-            result = request.rxSend();
-        } else {
-            result = request.rxSendJsonObject(body);
-        }
-        return result.map(HttpResponse::bodyAsJsonObject);
-    }
-
-    private Single&amp;lt;Boolean&amp;gt; unpublishRecord() {
-        return Single.create(emitter -&amp;gt; {
-            if (null != this.publishedRecord) {
-                discovery.rxUnpublish(this.publishedRecord.getRegistration())
-                        .subscribe(() -&amp;gt; {
-                            logger.debug("Service {} unpublished", this.publishedRecord.getName());
-                            this.publishedRecord = null;
-                            emitter.onSuccess(true);
-                        }, emitter::onError);
-            } else {
-                emitter.onSuccess(true);
+        result.subscribe(response -&amp;gt; {
+            if (!context.response().ended()) {
+                context.response().setStatusCode(response.statusCode());
+                response.headers().getDelegate().forEach(header -&amp;gt; context.response().putHeader(header.getKey(), header.getValue()));
+                context.response().end(response.body());
             }
-        });
-    }
-
-    private void closeCachedEndPoint(String serviceName) {
-        Object endPoint = this.serviceEndPointMap.get(serviceName);
-        if (null != endPoint) {
-            logger.debug("Close cached EndPoint for service {}", serviceName);
-            if (endPoint instanceof WebClient) {
-                ((WebClient) endPoint).close();
-            } else if (endPoint instanceof HttpClient) {
-                ((HttpClient) endPoint).close();
-            }
-            this.serviceEndPointMap.remove(serviceName);
-        }
+            future.complete();
+        }, future::fail);
     }
 }
 ~~~
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Gary Cheng</dc:creator><pubDate>Tue, 24 Apr 2018 01:59:48 -0000</pubDate><guid>https://sourceforge.net6c3427146f4444cedff97c88020498816cebf106</guid></item><item><title>BaseMicroServicesVerticle modified by Gary Cheng</title><link>https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v2
+++ v3
@@ -1,12 +1,16 @@
 ~~~
-package com.example.common;
+package com.example.microservices.com;

 import io.reactivex.Single;
 import io.vertx.circuitbreaker.CircuitBreakerOptions;
+import io.vertx.core.http.HttpMethod;
 import io.vertx.core.json.JsonObject;
 import io.vertx.reactivex.circuitbreaker.CircuitBreaker;
 import io.vertx.reactivex.core.AbstractVerticle;
+import io.vertx.reactivex.core.buffer.Buffer;
 import io.vertx.reactivex.core.http.HttpClient;
+import io.vertx.reactivex.ext.web.client.HttpRequest;
+import io.vertx.reactivex.ext.web.client.HttpResponse;
 import io.vertx.reactivex.ext.web.client.WebClient;
 import io.vertx.reactivex.servicediscovery.ServiceDiscovery;
 import io.vertx.reactivex.servicediscovery.types.HttpEndpoint;
@@ -163,6 +167,54 @@
                 .doOnSuccess(r -&amp;gt; this.publishedRecord = r);
     }

+    /**
+     * Invoke a restful service by service name
+     *
+     * @param serviceName the name of service
+     * @param method      HTTP method
+     * @param uri         uri of request
+     * @param body        body of request
+     * @return result as JsonObject
+     */
+    protected Single&amp;lt;JsonObject&amp;gt; invokeRestfulService(String serviceName, HttpMethod method, String uri, JsonObject body) {
+        logger.debug("invokeRestfulService, service name:{}, uri:{}", serviceName, uri);
+        return this.getCircuitBreaker(serviceName).rxExecuteCommand(future -&amp;gt; this.getWebEndPoint(serviceName).subscribe(
+                webClient -&amp;gt; {
+                    HttpRequest request = webClient.request(method, uri);
+                    Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
+                    if (null == body) {
+                        result = request.rxSend();
+                    } else {
+                        result = request.rxSendJsonObject(body);
+                    }
+                    result.map(HttpResponse::bodyAsJsonObject).subscribe(future::complete, future::fail);
+                },
+                throwable -&amp;gt; future.fail("Service [" + serviceName + "] not found"))
+        );
+    }
+
+    /**
+     * Invoke a restful service by given host and port
+     *
+     * @param method HTTP method
+     * @param port   port of EndPoint
+     * @param host   host of EndPoint
+     * @param uri    uri of request
+     * @param body   body of request
+     * @return
+     */
+    protected Single&amp;lt;JsonObject&amp;gt; invokeRestful(HttpMethod method, int port, String host, String uri, JsonObject body) {
+        logger.debug("invokeRestfulService, host:{}, port:{}, uri:{}", host, port, uri);
+        HttpRequest&amp;lt;Buffer&amp;gt; request = WebClient.create(vertx).request(method, port, host, uri);
+        Single&amp;lt;HttpResponse&amp;lt;Buffer&amp;gt;&amp;gt; result;
+        if (null == body) {
+            result = request.rxSend();
+        } else {
+            result = request.rxSendJsonObject(body);
+        }
+        return result.map(HttpResponse::bodyAsJsonObject);
+    }
+
     private Single&amp;lt;Boolean&amp;gt; unpublishRecord() {
         return Single.create(emitter -&amp;gt; {
             if (null != this.publishedRecord) {
@@ -191,5 +243,4 @@
         }
     }
 }
-
 ~~~
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Gary Cheng</dc:creator><pubDate>Wed, 18 Apr 2018 01:46:31 -0000</pubDate><guid>https://sourceforge.net7c6f968de113a3517ddd532b9aacf68975eaccbf</guid></item><item><title>BaseMicroServicesVerticle modified by Gary Cheng</title><link>https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v1
+++ v2
@@ -1,14 +1,13 @@
 ~~~
-package com.example.microservices.com;
+package com.example.common;

-import io.reactivex.Completable;
 import io.reactivex.Single;
 import io.vertx.circuitbreaker.CircuitBreakerOptions;
-import io.vertx.core.impl.ConcurrentHashSet;
 import io.vertx.core.json.JsonObject;
 import io.vertx.reactivex.circuitbreaker.CircuitBreaker;
 import io.vertx.reactivex.core.AbstractVerticle;
 import io.vertx.reactivex.core.http.HttpClient;
+import io.vertx.reactivex.ext.web.client.WebClient;
 import io.vertx.reactivex.servicediscovery.ServiceDiscovery;
 import io.vertx.reactivex.servicediscovery.types.HttpEndpoint;
 import io.vertx.servicediscovery.Record;
@@ -16,9 +15,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;

@@ -28,18 +24,18 @@
  * @author Gary Cheng
  */
 public abstract class BaseMicroServicesVerticle extends AbstractVerticle {
-    public static final String KEY_SERVICE_NAME = "service.name";
-    public static final String KEY_HOST = "host";
-    public static final String KEY_PORT = "port";
-    public static final String KEY_ROOT = "root";
-    private static final String KEY_NAME = "name";
+    protected static final String KEY_SERVICE_NAME = "service.name";
+    protected static final String KEY_HOST = "host";
+    protected static final String KEY_PORT = "port";
+    protected static final String KEY_ROOT = "root";
+    protected static final String KEY_NAME = "name";

     private static final Logger logger = LoggerFactory.getLogger(BaseMicroServicesVerticle.class);

     protected ServiceDiscovery discovery;
-    private Collection&amp;lt;Record&amp;gt; publishedRecords = new ConcurrentHashSet&amp;lt;&amp;gt;();
+    private Record publishedRecord;
     private Map&amp;lt;String, CircuitBreaker=""&amp;gt; circuitBreakerMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
-    private Map&amp;lt;String, Object=""&amp;gt; serviceClientMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
+    private Map&amp;lt;String, Object=""&amp;gt; serviceEndPointMap = new ConcurrentHashMap&amp;lt;&amp;gt;();

     @Override
     public void start() {
@@ -51,15 +47,11 @@
     @Override
     public void stop() {
         logger.debug("Stopping verticle - {}", this.getClass().getName());
-        if (null != discovery) {
-            List&amp;lt;Completable&amp;gt; completables = new ArrayList&amp;lt;&amp;gt;();
-            publishedRecords.forEach(record -&amp;gt; completables.add(discovery.rxUnpublish(record.getRegistration())));
-            Completable.merge(completables)
-                    .subscribe(() -&amp;gt; {
-                        logger.debug("All services have been un-published");
-                        discovery.close();
-                    });
-        }
+        this.serviceEndPointMap.keySet().stream().forEach(serviceName -&amp;gt; this.closeCachedEndPoint(serviceName));
+        this.serviceEndPointMap.clear();
+        this.circuitBreakerMap.values().stream().forEach(circuitBreaker -&amp;gt; circuitBreaker.close());
+        this.circuitBreakerMap.clear();
+        this.unpublishRecord().subscribe(b -&amp;gt; discovery.close());
     }

     /**
@@ -78,6 +70,7 @@
      * @return circuit breaker of service
      */
     protected final CircuitBreaker getCircuitBreaker(String serviceName) {
+        logger.debug("Get CircuitBreaker of service {}", serviceName);
         CircuitBreaker circuitBreaker = circuitBreakerMap.get(serviceName);
         if (null == circuitBreaker) {
             circuitBreaker = this.createCircuitBreaker(serviceName);
@@ -93,7 +86,7 @@
      * @return circuit breaker of service
      */
     protected CircuitBreaker createCircuitBreaker(String serviceName) {
-        logger.debug("create circuit breaker for service {}", serviceName);
+        logger.debug("Create CircuitBreaker for service {}", serviceName);
         String circuitBreakerName = serviceName + "-" + "circuit-breaker";
         CircuitBreakerOptions options = new CircuitBreakerOptions()
                 .setMaxFailures(5)
@@ -101,25 +94,46 @@
                 .setResetTimeout(10000)
                 .setFallbackOnFailure(true);
         return CircuitBreaker.create(circuitBreakerName, vertx, options)
-                .openHandler(v -&amp;gt; logger.debug("{} opened", circuitBreakerName))
+                .openHandler(v -&amp;gt; {
+                    logger.debug("{} opened", circuitBreakerName);
+                    this.closeCachedEndPoint(serviceName);
+                })
                 .halfOpenHandler(v -&amp;gt; logger.debug("{} half opened", circuitBreakerName))
                 .closeHandler(v -&amp;gt; logger.debug("{} closed", circuitBreakerName));
     }

     /**
-     * Lookup ServiceDiscovery by service name and return an async HttpClient
+     * Return an async HttpClient by service name
      *
      * @param serviceName the name of service
      * @return
      */
-    protected final Single&amp;lt;HttpClient&amp;gt; getServiceHttpClient(String serviceName) {
+    protected final Single&amp;lt;HttpClient&amp;gt; getHttpEndPoint(String serviceName) {
         logger.debug("Get HTTP client by service name[{}]", serviceName);
-        Object serviceClient = this.serviceClientMap.get(serviceName);
-        if (null != serviceClient) {
-            return Single.just((HttpClient) serviceClient);
+        Object endPoint = this.serviceEndPointMap.get(serviceName);
+        if (null != endPoint &amp;amp;&amp;amp; endPoint instanceof HttpClient) {
+            return Single.just((HttpClient) endPoint);
         } else {
             return HttpEndpoint.rxGetClient(discovery, new JsonObject().put(KEY_NAME, serviceName))
-                    .doOnSuccess(httpClient -&amp;gt; this.serviceClientMap.put(serviceName, httpClient));
+                    .doOnSuccess(httpClient -&amp;gt; this.serviceEndPointMap.put(serviceName, httpClient));
+        }
+    }
+
+    /**
+     * Return an async HttpClient by service name
+     *
+     * @param serviceName the name of service
+     * @return
+     */
+    protected final Single&amp;lt;WebClient&amp;gt; getWebEndPoint(String serviceName) {
+        logger.debug("Get Web client by service name[{}]", serviceName);
+        Object endPoint = this.serviceEndPointMap.get(serviceName);
+        if (null != endPoint &amp;amp;&amp;amp; endPoint instanceof WebClient) {
+            return Single.just((WebClient) endPoint);
+        } else {
+            logger.debug("Getting Web client from ServiceDiscovery...");
+            return HttpEndpoint.rxGetWebClient(discovery, new JsonObject().put(KEY_NAME, serviceName))
+                    .doOnSuccess(webClient -&amp;gt; this.serviceEndPointMap.put(serviceName, webClient));
         }
     }

@@ -143,13 +157,39 @@
      * @param record record to publish
      * @return
      */
-    private Single&amp;lt;Record&amp;gt; publishRecord(Record record) {
-        return discovery.rxPublish(record)
-                .flatMap(r -&amp;gt; {
-                    logger.debug("Service {} has been published", record.getName());
-                    this.publishedRecords.add(r);
-                    return Single.just(r);
-                });
+    protected Single&amp;lt;Record&amp;gt; publishRecord(Record record) {
+        return this.unpublishRecord()
+                .flatMap(b -&amp;gt; discovery.rxPublish(record))
+                .doOnSuccess(r -&amp;gt; this.publishedRecord = r);
+    }
+
+    private Single&amp;lt;Boolean&amp;gt; unpublishRecord() {
+        return Single.create(emitter -&amp;gt; {
+            if (null != this.publishedRecord) {
+                discovery.rxUnpublish(this.publishedRecord.getRegistration())
+                        .subscribe(() -&amp;gt; {
+                            logger.debug("Service {} unpublished", this.publishedRecord.getName());
+                            this.publishedRecord = null;
+                            emitter.onSuccess(true);
+                        }, emitter::onError);
+            } else {
+                emitter.onSuccess(true);
+            }
+        });
+    }
+
+    private void closeCachedEndPoint(String serviceName) {
+        Object endPoint = this.serviceEndPointMap.get(serviceName);
+        if (null != endPoint) {
+            logger.debug("Close cached EndPoint for service {}", serviceName);
+            if (endPoint instanceof WebClient) {
+                ((WebClient) endPoint).close();
+            } else if (endPoint instanceof HttpClient) {
+                ((HttpClient) endPoint).close();
+            }
+            this.serviceEndPointMap.remove(serviceName);
+        }
     }
 }
+
 ~~~
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Gary Cheng</dc:creator><pubDate>Mon, 16 Apr 2018 20:17:11 -0000</pubDate><guid>https://sourceforge.net65ce632c15649be6bf23d7b8e3937b228849d2dd</guid></item><item><title>BaseMicroServicesVerticle modified by Gary Cheng</title><link>https://sourceforge.net/p/garyproject00/wiki/BaseMicroServicesVerticle/</link><description>&lt;div class="markdown_content"&gt;&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;microservices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.reactivex.Completable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.reactivex.Single&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.circuitbreaker.CircuitBreakerOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.core.impl.ConcurrentHashSet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.core.json.JsonObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.reactivex.circuitbreaker.CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.reactivex.core.AbstractVerticle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.reactivex.core.http.HttpClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.reactivex.servicediscovery.ServiceDiscovery&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.reactivex.servicediscovery.types.HttpEndpoint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.servicediscovery.Record&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.vertx.servicediscovery.ServiceDiscoveryOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.slf4j.Logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.slf4j.LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.ArrayList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.ConcurrentHashMap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;/**&lt;/span&gt;
 &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="n"&gt;verticle&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;which&lt;/span&gt; &lt;span class="n"&gt;provided&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt; &lt;span class="n"&gt;common&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;discovery&lt;/span&gt;
 &lt;span class="o"&gt;*&lt;/span&gt;
 &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@author&lt;/span&gt; &lt;span class="n"&gt;Gary&lt;/span&gt; &lt;span class="n"&gt;Cheng&lt;/span&gt;
 &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseMicroServicesVerticle&lt;/span&gt; &lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;AbstractVerticle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;KEY_SERVICE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"service.name"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;KEY_HOST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;KEY_PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;KEY_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;KEY_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseMicroServicesVerticle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;ServiceDiscovery&lt;/span&gt; &lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;publishedRecords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ConcurrentHashSet&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;circuitBreakerMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ConcurrentHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;serviceClientMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ConcurrentHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Starting verticle - {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Config:{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodePrettily&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;discovery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ServiceDiscovery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ServiceDiscoveryOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setBackendConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getServiceDiscoveryConfig&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Stopping verticle - {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;completables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;publishedRecords&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;completables&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rxUnpublish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRegistration&lt;/span&gt;&lt;span class="p"&gt;())));&lt;/span&gt;
            &lt;span class="n"&gt;Completable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;completables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"All services have been un-published"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;/**&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Return&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt; &lt;span class="n"&gt;discovery&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="n"&gt;them&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;verticle&lt;/span&gt;&lt;span class="s1"&gt;'s config()&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt; &lt;span class="n"&gt;discovery&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt;
     &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="n"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;JsonObject&lt;/span&gt; &lt;span class="n"&gt;getServiceDiscoveryConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;/**&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Return&lt;/span&gt; &lt;span class="n"&gt;circuit&lt;/span&gt; &lt;span class="n"&gt;breaker&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@param&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt; &lt;span class="n"&gt;circuit&lt;/span&gt; &lt;span class="n"&gt;breaker&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
     &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="n"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="n"&gt;getCircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="n"&gt;circuitBreaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;circuitBreakerMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;circuitBreaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createCircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;circuitBreakerMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;circuitBreaker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;/**&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Create&lt;/span&gt; &lt;span class="n"&gt;circuit&lt;/span&gt; &lt;span class="n"&gt;breaker&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@param&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt; &lt;span class="n"&gt;circuit&lt;/span&gt; &lt;span class="n"&gt;breaker&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
     &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="n"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="n"&gt;createCircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"create circuit breaker for service {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;circuitBreakerName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"-"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"circuit-breaker"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;CircuitBreakerOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;CircuitBreakerOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setMaxFailures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setResetTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFallbackOnFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;circuitBreakerName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vertx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;openHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"{} opened"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;circuitBreakerName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;halfOpenHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"{} half opened"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;circuitBreakerName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;closeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"{} closed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;circuitBreakerName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;/**&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Lookup&lt;/span&gt; &lt;span class="n"&gt;ServiceDiscovery&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;async&lt;/span&gt; &lt;span class="n"&gt;HttpClient&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@param&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt;
     &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="n"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getServiceHttpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Get HTTP client by service name[{}]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;serviceClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serviceClientMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;just&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HttpEndpoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rxGetClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;JsonObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doOnSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;serviceClientMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;/**&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Publish&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;HttpEndPoint&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;ServiceDiscovery&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@param&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;configure&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;HttpEndPoint&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt;
     &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="n"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;publishHttpEndPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JsonObject&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_ROOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publishRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpEndpoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;/**&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Publish&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;ServiceDiscovery&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@param&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;publish&lt;/span&gt;
     &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt;
     &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;publishRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rxPublish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Service {} has been published"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                    &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publishedRecords&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;just&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Gary Cheng</dc:creator><pubDate>Sun, 15 Apr 2018 23:25:21 -0000</pubDate><guid>https://sourceforge.netb67db55f1feae2ec8916e15ce1c29e1df317ec92</guid></item></channel></rss>