Microservices News

Interview with Rick Hightower about QBit Microservices and Java Reactive programming with Reakt

This is a short interview with Rick Hightower about Reakt - Java Reactive Programming lib for Promises and Streams.


Why did you create Reakt?

Good question. Many of the ideas in Reakt were already in QBit. The problem is that QBit is a full microservices lib with health, monitoring, a typed actor system, service discovery, etc. QBit’s focus in on reactive microservices with Java.



Read the rest of the interview here: Interview about Reakt Reactive Java Lib with Promises and Streams and QBit Reactive Microservices Lib. 




Reactive Java using Reakt by example

posted May 5, 2016, 9:57 PM by Rick Hightower

Reactive Java code examples using Reakt (with links to docs for further info)

This is a presentation of different Reakt features in the context of a real application. I have renamed the classnames and such, but this is from an in-progress microservice. It demonstrates where you would use the Reakt pieces to build a reactive Java application.
This covers usage of Reakt:
  • blocking promises
  • Promises.all
  • invokable promise
  • Expected values
  • Circuit breakers
  • Working with the Reactor
  • Working with streams
  • Using AsyncSuppliers to create downstream services
  • Reakt Guava integration
  • Using promise.thenMap


Please read the full article here: Reactive Java using Reakt by example

QBit Microservices Lib 1.5.0 was Released

posted Apr 22, 2016, 10:21 PM by Rick Hightower   [ updated Apr 22, 2016, 10:25 PM ]

QBit Microservices Lib 1.5.0.RELEASE


QBit Microservices Lib now supports Reakt invokable promises for local and remote client proxies. 
This gives a nice fluent API for async programming.

Invokeable promise

        employeeService.lookupEmployee("123")
               .then((employee)-> {...}).catchError(...).invoke();

QBit callbacks are now also Reakt Callbacks without breaking the QBit contract for Callbacks.

See Reakt Invokable Promises for more details.

A full write up on QBit Invokable Promise is pending, but the curious can see ReaktInterfacesTest Service Queue, ServiceBundle for more details, and the Remote Websocket Reakt interfaces for remote access proxies.

  • 683 Use Metrik for metrics system
  • 682 Support Reakt with Websocket RPC proxies
  • 680 Support Inovkable promises on Service Queues
  • 679 Testing for Inovkable promises on proxies
  • 678 Fix health check logging
  • 676 Remote proxies support Reakt Callbacks and promises
  • 675 Local proxies support Reakt Inokable promises
  • 674 Local proxies support Reakt callbacks
  • 673 Remote proxies support callback
  • 672 Get rid of boiler plate code for Reactor, StatsCollector and Health Check

Reakt Reactive Java - Invokable Promise - Fluent Reactive Java

posted Apr 22, 2016, 10:19 PM by Rick Hightower

Reakt, Java reactive programming lib, supports invokable promises so service methods could return a Promise.

Invokable Promise

        employeeService.lookupEmployee("123")
               .then((employee)-> {...}).catchError(...).invoke();

NOTE: QBit Microservices Lib version 1.4 (coming soon) will support generation of client stubs (local and remote) that return Reakt Promises. Having the client proxy method return the promise instead of taking a callback. With QBit you will be able to use Callback's on the service side and Promises on the client proxy side. Callbacks are natural for the service, and Promises are natural for the client.

But you do not have to use QBit to use Reakt's invokable promises.

Let's walk through an example of using a Reakt invokable promises.

Let's say we are developing a service discovery service with this interface.

ServiceDiscovery interface (Example service that does lookup)

    interface ServiceDiscovery {
        Promise<URI> lookupService(URI uri);

        default void shutdown() {}
        default void start() {}
    }

Note that ServiceDiscovery.lookupService is just an example likeEmployeeService.lookupEmployee was just an example.

Notice the lookupService returns a Promise (Promise<URI> lookupService(URI uri)). To call this, we can use an invokable promise. The service side will return an invokable promise, and the client of the service will use that Promise to register its thenthenExpectthenMap, and/orcatchError handlers.

Here is the service side of the invokable promise example.

Service Side of invokable promise

    class ServiceDiscoveryImpl implements ServiceDiscovery {

        @Override
        public Promise<URI> lookupService(URI uri) {
            return invokablePromise(promise -> {
                if (uri == null) {
                    promise.reject("URI was null");
                } else {
                    ...
                    // DO SOME ASYNC OPERATION WHEN IT RETURNS CALL RESOLVE.
                    promise.resolve(successResult);
                }
            });
        }
    }

Notice to create the invokablePromise we use Promises.invokablePromise which takes aPromise Consumer (static <T> Promise<T> invokablePromise(Consumer<Promise<T>> promiseConsumer)).

The lookupService example returns a Promise and it does not execute its body until theinvoke (Promise.invoke) on the client side of the equation is called.

Let's look at the client side.

Client side of using lookupService.

        serviceDiscovery.lookupService(empURI)
                .then(this::handleSuccess)
                .catchError(this::handleError)
                .invoke();

The syntax this::handleSuccess is a method reference which can be used as Java 8 lambda expressions. We use method references to make the example shorter.

Here is a complete example with two versions of our example service.

Complete example from unit tests

package io.advantageous.reakt.promise;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.net.URI;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static io.advantageous.reakt.promise.Promises.*;
import static org.junit.Assert.*;

public class InvokablePromise {


    final URI successResult = URI.create("http://localhost:8080/employeeService/");
    ServiceDiscovery serviceDiscovery;
    ServiceDiscovery asyncServiceDiscovery;
    URI empURI;
    CountDownLatch latch;
    AtomicReference<URI> returnValue;
    AtomicReference<Throwable> errorRef;

    @Before
    public void before() {
        latch = new CountDownLatch(1);
        returnValue = new AtomicReference<>();
        errorRef = new AtomicReference<>();
        serviceDiscovery = new ServiceDiscoveryImpl();
        asyncServiceDiscovery = new ServiceDiscoveryAsyncImpl();
        asyncServiceDiscovery.start();
        empURI = URI.create("marathon://default/employeeService?env=staging");
    }

    @After
    public void after() {
        asyncServiceDiscovery.shutdown();
    }

    public void await() {
        try {
            latch.await(10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new IllegalStateException(e);
        }
    }

    @Test
    public void testServiceWithReturnPromiseSuccess() {
        serviceDiscovery.lookupService(empURI).then(this::handleSuccess)
                .catchError(this::handleError).invoke();
        await();
        assertNotNull("We have a return", returnValue.get());
        assertNull("There were no errors", errorRef.get());
        assertEquals("The result is the expected result", successResult, returnValue.get());
    }


    @Test
    public void testServiceWithReturnPromiseFail() {


        serviceDiscovery.lookupService(null).then(this::handleSuccess)
                .catchError(this::handleError).invoke();

        await();
        assertNull("We do not have a return", returnValue.get());
        assertNotNull("There were  errors", errorRef.get());
    }


    @Test
    public void testAsyncServiceWithReturnPromiseSuccess() {
        asyncServiceDiscovery.lookupService(empURI).then(this::handleSuccess)
                .catchError(this::handleError).invoke();
        await();
        assertNotNull("We have a return from async", returnValue.get());
        assertNull("There were no errors form async", errorRef.get());
        assertEquals("The result is the expected result form async", successResult, returnValue.get());
    }


    @Test
    public void testAsyncServiceWithReturnPromiseFail() {


        asyncServiceDiscovery.lookupService(null).then(this::handleSuccess)
                .catchError(this::handleError).invoke();

        await();
        assertNull("We do not have a return from async", returnValue.get());
        assertNotNull("There were  errors from async", errorRef.get());
    }

    @Test (expected = IllegalStateException.class)
    public void testServiceWithReturnPromiseSuccessInvokeTwice() {
        final Promise<URI> promise = serviceDiscovery.lookupService(empURI).then(this::handleSuccess)
                .catchError(this::handleError);
        promise.invoke();
        promise.invoke();
    }

    @Test
    public void testIsInvokable() {
        final Promise<URI> promise = serviceDiscovery.lookupService(empURI).then(this::handleSuccess)
                .catchError(this::handleError);

        assertTrue("Is this an invokable promise", promise.isInvokable());
    }


    private void handleError(Throwable error) {
        errorRef.set(error);
        latch.countDown();
    }

    private void handleSuccess(URI uri) {
        returnValue.set(uri);
        latch.countDown();
    }


    interface ServiceDiscovery {
        Promise<URI> lookupService(URI uri);

        default void shutdown() {
        }

        default void start() {
        }
    }

    class ServiceDiscoveryImpl implements ServiceDiscovery {

        @Override
        public Promise<URI> lookupService(URI uri) {
            return invokablePromise(promise -> {

                if (uri == null) {
                    promise.reject("URI was null");
                } else {
                    promise.resolve(successResult);
                }
            });
        }
    }


    class ServiceDiscoveryAsyncImpl implements ServiceDiscovery {

        final ExecutorService executorService;

        final Queue<Runnable> runnables;

        final AtomicBoolean stop;

        public ServiceDiscoveryAsyncImpl() {
            executorService = Executors.newSingleThreadExecutor();
            runnables = new LinkedTransferQueue<>();
            stop = new AtomicBoolean();
        }

        @Override
        public Promise<URI> lookupService(URI uri) {
            return invokablePromise(promise -> {
                runnables.offer(() -> {
                    if (uri == null) {
                        promise.reject("URI was null");
                    } else {
                        promise.resolve(URI.create("http://localhost:8080/employeeService/"));
                    }
                });
            });
        }

        @Override
        public void shutdown() {
            stop.set(true);
            executorService.shutdown();
        }

        @Override
        public void start() {
            executorService.submit((Runnable) () -> {

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                while (true) {
                    if (stop.get())break;
                    Runnable runnable = runnables.poll();
                    while (runnable != null) {
                        runnable.run();
                        runnable = runnables.poll();
                    }
                }

            });
        }
    }
}

Reakt website

Related Projects

Further reading

What is Microservices Architecture?

QBit Java Micorservices lib tutorials

The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.

Find more tutorial on QBit.

Reactive ProgrammingJava MicroservicesRick Hightower

High-speed microservices consulting firm and authors of QBit with lots of experience with Vertx - Mammatus Technology

Highly recommended consulting and training firm who specializes in microservices architecture and mobile development that are already very familiar with QBit and Vertx as well as iOS and Android - About Objects

Java Microservices Architecture

Microservice Service Discovery with Consul

Microservices Service Discovery Tutorial with Consul

Reactive Microservices

High Speed Microservices

Java Microservices Consulting

Microservices Training

Reactive Microservices Tutorial, using the Reactor

QBit is mentioned in the Restlet blog


Reakt 2.0.0 was released - Reakt is reactive interfaces for Java.

posted Apr 13, 2016, 12:27 AM by Rick Hightower   [ updated Apr 13, 2016, 12:28 AM ]

Reakt is reactive interfaces for Java which includes:

The emphasis is on defining interfaces that enable lambda expressions, and fluent APIs for asynchronous programming for Java.

Note: This mostly just provides the interfaces not the implementations. There are some starter implementations but the idea is that anyone can implement this. It is all about interfaces. There will be adapters for Vertx, RxJava, Reactive Streams, etc. There is support for Guava Async (used by Cassandra) and the QBit microservices lib. Czar Maker uses Reakt for its reactive leadership election.

Have a question?

Reakt Mailing List

Getting started

Using from maven

<dependency>
    <groupId>io.advantageous</groupId>
    <artifactId>reakt</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

Using from gradle

compile 'io.advantageous:reakt:2.0.0.RELEASE'

Fluent Promise API

  Promise<Employee> promise = promise()
                .then(e -> saveEmployee(e))
                .catchError(error -> 
                     logger.error("Unable to lookup employee", error));

  employeeService.lookupEmployee(33, promise);

Or you can handle it in one line.

Fluent Promise API example 2

  employeeService.lookupEmployee(33, 
        promise().then(e -> saveEmployee(e))
                 .catchError(error -> logger.error(
                                           "Unable to lookup ", error))
        );

Promises are both a callback and a Result; however, you can work with Callbacks directly.

Using Result and callback directly

        employeeService.lookupEmployee(33, result -> {
            result.then(e -> saveEmployee(e))
                  .catchError(error -> {
                    logger.error("Unable to lookup", error);
            });
        });

In both of these examples, lookupEmployee would look like:

Using Result and callback directly

   public void lookupEmployee(long employeeId, Callback<Employee> callback){...}

You can use Promises to transform into other promises.

Transforming into another type of promise using thenMap

        Promise<Employee> employeePromise = Promises.<Employee>blockingPromise();

        Promise<Sheep> sheepPromise = employeePromise
                .thenMap(employee1 -> new Sheep(employee1.getId()));

The thenMap will return a new type of Promise.

You can find more examples in the reakt wiki.

We also support working with streams.

Promise concepts

This has been adapted from this article on ES6 promises. A promise can be:

  • fulfilled The callback/action relating to the promise succeeded
  • rejected The callback/action relating to the promise failed
  • pending The callback/action has not been fulfilled or rejected yet
  • completed The callback/action has been fulfilled/resolved or rejected

Java is not single threaded, meaning that two bits of code can run at the same time, so the design of this promise and streaming library takes that into account.

There are three types of promises:

  • Callback promises
  • Blocking promises (for testing and legacy integration)
  • Replay promises (allow promises to be handled on the same thread as caller)

Replay promises are the most like their JS cousins. Replay promises are usually managed by the Reakt Reactor and supports environments like Vert.x and QBit. See the wiki for more details on Replay promises.

It is common to make async calls to store data in a NoSQL store or to call a remote REST interface or deal with a distributed cache or queue. Also Java is strongly typed so the library that mimics JS promises is going to look a bit different. We tried to use similar terminology where it makes sense.

Events and Streams are great for things that can happen multiple times on the same object — keyup, touchstart, or event a user action stream from Kafka, etc.

With those events you don't really care about what happened before when you attached the listener.

But often times when dealing with services and data repositories, you want to handle a response with a specific next action, and a different action if there was an error or timeout from the responses. You essentially want to call and handle a response asynchronously and that is what promises allow.

This is not our first time to bat with Promises. QBit has had Promises for a few years now. We just called them CallbackBuilders instead. We wanted to use more standard terminology and wanted to use the same terminology and modeling on projects that do not use QBit like Conekt, Vert.x, RxJava, and reactive streams.

At their most basic level, promises are like event listeners except:

A promise can only succeed or fail once. A promise cannot succeed or fail twice, neither can it switch from success to failure. Once it enters its completed state, then it is done.

Bridges

Reakt Guava Bridge which allows libs that use Guava async support to now have a modern Java feel.

Cassandra Reakt example

register(session.executeAsync("SELECT release_version FROM system.local"), 
  promise().thenExpect(expected -> 
     gui.setMessage("Cassandra version is " +
         expected.get().one().getString("release_version"))
  ).catchError(error -> 
     gui.setMessage("Error while reading Cassandra version: " 
     + error.getMessage())
  )
);

QBit 1 ships with a bridge and QBit 2will use Reakt as its primary reactive callback mechanism.

Conekt, a slimmed down fork of Vert.x, will also use Reakt.

See QBit microservices lib for more details.

See our wiki for more details on Reakt.

Further reading

What is Microservices Architecture?

QBit Java Micorservices lib tutorials

Czar Maker Consul

posted Apr 13, 2016, 12:24 AM by Rick Hightower

Czar Maker Consul - Reactive Java Leadership Election

Czar Maker is a nice set of interfaces for Leader Election.

There is one Czar Maker Consul implementation of this interface that uses Consul. You could use the interface to implement leader election with zookeeper or etcd. Consul and etcd use the RAFT algorithm to present a reliable kv storage (Zookeeper uses a similar technique as Consul and etcd).
Czar uses Reakt, a Java reactive, streaming API, with callbacks and promises that is Java 8 and Lambda friendly
Czar also uses QBit microservices as its HTTP/IO lib.


Czar Maker Consul is a Java lib for leadership election. Czar Maker Consul uses Consul to do leadership election.

Getting Started

Maven

<dependency>
    <groupId>io.advantageous.czarmaker</groupId>
    <artifactId>czar-maker-consul</artifactId>
    <version>0.1.0.RELEASE</version>
</dependency>

Gradle

compile 'io.advantageous.czarmaker:czar-maker-consul:0.1.0.RELEASE'

Sample usage

import io.advantageous.consul.Consul;
import io.advantageous.czarmaker.Endpoint;
import io.advantageous.czarmaker.consul.*;
import io.advantageous.qbit.util.TestTimer;
import io.advantageous.reakt.promise.Promise;
import io.advantageous.reakt.promise.Promises;
import io.advantageous.reakt.reactor.Reactor;
import io.advantageous.reakt.reactor.TimeSource;

...

    private final long sessionTTL = 10;
    private final long newLeaderCheckInterval = 5;
    private ConsulLeadershipElector leadershipElector;
    private Reactor reactor;
    private TestTimer testTimer;
    private Consul consul;

...
        consul = Consul.consul();
        testTimer = new TestTimer();
        testTimer.setTime();
        reactor = Reactor.reactor(Duration.ofSeconds(30), new TestTimeSource(testTimer));
        final String serviceName = "foo";

        ConsulLeadershipProvider provider = new ConsulLeadershipProvider(serviceName, consul, TimeUnit.SECONDS, sessionTTL);

        leadershipElector = new ConsulLeadershipElector(provider, serviceName, reactor, TimeUnit.SECONDS,
                sessionTTL, newLeaderCheckInterval);


        /** Get the current leader. */
        Promise<Endpoint> promise = Promises.<Endpoint>blockingPromise();
        leadershipElector.getLeader(promise);

        assertTrue(promise.expect().isEmpty());


        /** Elect this endpoint as the current leader. */
        Promise<Boolean> selfElectPromise = Promises.<Boolean>blockingPromise();
        leadershipElector.selfElect(new Endpoint("foo.com", 9091), selfElectPromise);

        assertTrue("We are now the leader", selfElectPromise.get());


        /** Get the current leader again.  */
        Promise<Endpoint> getLeaderPromise = Promises.<Endpoint>blockingPromise();
        leadershipElector.getLeader(getLeaderPromise);

        /** See if it present. */
        assertTrue(getLeaderPromise.expect().isPresent());

        /** See if it has the host foo.com. */
        assertEquals("foo.com", getLeaderPromise.get().getHost());

        /** See if the port is 9091. */
        assertEquals(9091, getLeaderPromise.get().getPort());

        testTimer.seconds(100);

        leadershipElector.process();

        /** Elect a new leader. */
        leadershipElector.selfElect(new Endpoint("foo2.com", 9092), selfElectPromise);


QBit 1.0.0 is now released

posted Apr 13, 2016, 12:22 AM by Rick Hightower

Support was added for Consul Session to support leader election.

All of add-on libs into QBit Extensions and now the core is a lot smaller.


There was a flurry on new releases to improve the core RPC WebSocket lib.


How to Identify you are not using Microservice Architecture

posted Nov 28, 2015, 1:24 PM by Rick Hightower   [ updated Nov 28, 2015, 1:26 PM ]

How to Identify you are not using Microservice Architecture.

Assume everyone starts with 100 points.

Everyone loses ten points for each assertion that is true. 


Not using Microservices hit list

  1. You don’t deploy to production more than once a month
  2. You always have to deploy a release chain of services
  3. You deploy multiple EAR or WAR files to the same Java EE container
  4. You make a blocking call to another service while servicing requests to your service 
  5. You make a blocking call to a database while servicing requests to your service
  6. Your service has more than 20 classes
  7. You share a database between more than one set of services or applications 
  8. You don’t deploy to a containerized or virtualized environment
  9. You don’t utilize service discovery
  10. You can have cascading failures
  11. You don’t implement circuit breakers and are not fault tolerant
  12. You don’t use async calls 
  13. You use more than 200 threads in a single service
  14. You don’t monitor health status of your services 
  15. You don't monitor statistics of your services
  16. You don’t have distributed logging
  17. You don’t use HTTP and JSON
  18. You don't use messaging
  19. Documentation for your services do not include curl commands
  20. You use WSDL
  21. You use XML as a transport
  22. You use an ESB 
  23. You use BPEL
  24. You use EAR and WAR files
  25. You use a Java EE container

If your score is below 70%, you are not using Microservices Architecture.


Microservices should be:

  1. Quickly deployable
  2. Deployed often
  3. Small
  4. Monitored: health, distributed logging, statistics
  5. Use Service Discovery to find other services
  6. Use async communication
  7. Prevent cascading failure and be fault tolerant
  8. Use web technologies like JSON, HTTP, WebSocket or messaging
Being async, using service discovery, preventing cascading failures, and being fault tolerant are all part of Reactive Microservices.


Read more about the history of microservices, how it is different from SOA, and just what are Microservices.


SOA versus Microservice Architecture

posted Nov 24, 2015, 9:12 PM by Rick Hightower   [ updated Nov 24, 2015, 9:15 PM ]

SOA vs. Microservices

Are Microservices just SOA?

It is very common for some to confuse Service-Oriented Architecture (SOA) and Microservice Architecture. In a sense, SOA and Microservice Architecture are related in some goals and purposes.

Microservices is a refocus and refinement of some of the original goals of SOA to meet the demands of a polyglot device environment that can scale and support continuous deployments in a cloud / third generation virtualization environment.


It’s not the daily increase but daily decrease. Hack away at the unessential. --Bruce Lee

Since SOA was later muddled with BPEL, ESBs, SOAP, WSDL, and their ilk, it is easier to drop the SOA moniker and just focus on the parts that worked well. Keep the parts that work. Get rid of the rest.

The focus on Microservices Architecture is web technologies to provide scalability, modular, domain-drive, small, and continuously deployable cloud-based services.

Microservices Architecture is taking what perhaps started out as SOA and applying lessons learned as well as pressure to support polyglot devices, deploy more rapidly and the architecture liquidity that cloud computing and virtualization/containerization provide. You mix all that together and you can see where Microservices Architecture started. Microservices Architecture is in general less vendor driven than SOA and more needs driven by demands of application development and current cloud infrastructure.

Microservices is not SOA. In fact, it in many ways it is directly the opposite. For example SOA often embraces WSDL which is a very strongly typed and rigid way to define a service endpoint. WSDL and XML schema takes all of the X (extensible) out of XML.



A Microservices Architecture embraces JSON and tolerant readers with the idea that the interface may change a bit and it is nicer to allow some flexibility in what properties/fields make up a message. A smart end point and a dumb pipe would be the opposite end of the spectrum than something like BPEL and ESB provides or other orchestrations mechanisms for SOA. While SOA embraces services being stateless, Microservices embrace the need for state and embrace OOP fundamentals of keeping your business logic and data together.


Read the SOA manifesto, and read the wikipedia page on SOA, try to do the exact opposite and you are a good ways down the road of adopting a Microservices architecture. Shun statelessness and embrace sharding, replication, eventual consistency and service data ownership. Shun WSDL and embrace JSON. REST and HTTP calls rule the day. Streaming calls over WebSocket is done for speed. Be the web. Microservices embraces asynchronous calls and reactive programming.

Microservices” - is a powerful term. It is one you need to embrace. It is very pragmatic. It is likely that you have been doing some or all of what Microservices Architecture is already. One day Microservices will go the way of Ajax, it will be so common it will be a forgone conclusion. Microservices is about pragmatism not vendors raising barriers to competitors by creating overly complex specifications.


We need to define Microservices a little more formerly so it does not go the way of SOA and every vendor gets to form a committee and dishonor its intentions with a set of nifty shiny baubles. SOA was a huge success and a failure. A failure because the term has actually no meaning or rather so many meanings, and yet Amazon and Google’s version of SOA are a huge success. Look at successful things that we had to call SOA and those are probably more like microservices and plain web services.

Read more about Microservices:

What is Microservices Architecture?

QBit Java Micorservices lib tutorials

The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.

Find more tutorial on QBit.

Reactive ProgrammingJava MicroservicesRick Hightower

High-speed microservices consulting firm and authors of QBit with lots of experience with Vertx - Mammatus Technology

Highly recommended consulting and training firm who specializes in microservices architecture and mobile development that are already very familiar with QBit and Vertx as well as iOS and Android - About Objects

Java Microservices Architecture

Microservice Service Discovery with Consul

Microservices Service Discovery Tutorial with Consul

Reactive Microservices

High Speed Microservices

Java Microservices Consulting

Microservices Training

Reactive Microservices Tutorial, using the Reactor

QBit is mentioned in the Restlet blog




Microservices distributed logging and MDC (Logging Mapped Diagnostic Context)

posted Nov 24, 2015, 4:20 PM by Rick Hightower   [ updated Nov 24, 2015, 4:27 PM ]

In the past we wrote about the importance of monitoring and statistics with Microservices Architecture. Certainly we have put our time and money where we speak, as QBit, the microservice library for Java, has support health checks, and statistics built-in which is both queryable/actionable/reactive and can also be stored in time series databases readily with its support for StatsD and its pluggable monitoring architecture.  

But another aspect of microservices monitoring is ability to use distributed logging in a searchable format. In order to do this and to really debug and track services one needs to use Mapped Diagnostic Context (MDC) with logging. MDC is extremely important for debugging and understanding microservices. Developing microservices without MDC and distributed log analysis is like flying blind. 

QBit, microservices lib, has implemented the Logging Mapped Diagnostic Context (MDC). Prior to MDC integration it was difficult to track request information in logs. Now we have added MDC integration it is easy to track Request URI, and more.

We added support for MDC to log the requests coming from Microservice you write like:

  • UserID
  • First name, last name
  • Request URI
  • remote address
  • browser/use-agent

For microservice to microservice calls (service to service) we can track the URI, source IP of the system, request URI. You should also be able to track (or set) any extra headers that will make sense to log in the context of the application.

This allows you to customize the Pattern used to log - and allows items to be properly pushed to SplunkGreyLog, or LogStash. This allows the MDC fields to be used for real-time operational intelligence using tools like SplunkLogStash and GreyLog. This allows you to search, analyze and log streams from your microservices log to learn about usages of these services which is critical for debugging and learning about how your microservices are used. Distributed logging and distributed log analysis is sort of a given in a microservices architecture.

Modern logging systems are designed to audit and debug distributed applications. QBit being a reactive microservice lib allows the creation of in-proc services and remote services, i.e., distributed applications. The in-proc services run in one or more threads using an actor/service queue model. QBit MDC support crosses the Thread/Queue/Actor Message boundary to facilitated debugging and provide a complete async call stack which is essential for debugging a message passing system like QBit which relies of ServiceQueue's.

Since QBit, the microservices lib, focuses on creating distributed systems you have to deal with multiple clients simultaneously when dealing with logging and auditing. The concepts of MDC (Mapped Diagnostic Contexts) was covered in the book Logging Diagnostic Messages in Pattern Languages of Program Design 3, by Neil Harrison (Addison-Wesley, 1997). QBit uses SLF4J API for Mapped Diagnostic Contexts (MDC).

Examples of using MDC

QBit provides the class ManagedServiceBuilder which is a utility class for when you are running in a PaaS like Heroku or Docker. It also allows you to share stat, health and system manager setup. You can also do things like enable stats (statsD support baked in), and install service discovery / distributed health (Consul, SkyDNS), etc.

The ManagedServiceBuilder to support MDC now provides a method enableLoggingMappedDiagnosticContext(). This installs the correct QBit interceptors to provide MDC logging and to create an async service call stack.

Let's demonstrate how this works with a simple example RestService.

RestService example to demonstrate MDC

@RequestMapping ("rest")
public class RestService {

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

...

    @RequestMapping ("mdc")
    public void mdc(final Callback<Map<String,String>> callback) {
        logger.info("CALLED MDC");
        callback.returnThis(MDC.getCopyOfContextMap());
    }
...

To make mdc work for the log, we will add the logback.xml file to the Java resources.

/resources/logback.xml

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n- 
%X{requestRemoteAddress} - %X{requestUri} - %X{requestHttpMethod}%n</pattern>
        </encoder>
    </appender>


    <logger name="io.advantageous.qbit" level="DEBUG"/>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

Notice the syntax %X{requestRemoteAddress}, this allows you to access the current HTTP request's remote address.

When constructing this service, you have to call enableLoggingMappedDiagnosticContext.

Turning on MDC support for ManagedServiceBuilder

        final ManagedServiceBuilder managedServiceBuilder = ManagedServiceBuilder.managedServiceBuilder();
        managedServiceBuilder.setRootURI("/");
        managedServiceBuilder.enableLoggingMappedDiagnosticContext();

        final RestService restService = new RestService();

        managedServiceBuilder.addEndpointService(restService);


        managedServiceBuilder.getEndpointServerBuilder().build().startServer();

At this point you can access the service with curl as follows:

Accessing the service with curl to see mdc

 curl http://localhost:8080/rest/mdc | jq .
{
  "requestRemoteAddress": "0:0:0:0:0:0:0:1:63772",
  "requestUri": "/rest/mdc",
  "requestHttpMethod": "GET"
}

Output of log

18:57:00.516 [QueueListener|Send Queue  rest] INFO  i.a.qbit.example.mdc.RestService - CALLED MDC
- 0:0:0:0:0:0:0:1:63797 - /rest/mdc - GET

Notice that the requestRemoteAddressrequestUri, and requestHttpMethod was output to the log.

Note that the enableLoggingMappedDiagnosticContext allows you to pass in N number of header names which will become part of the logging MDC and if you are using Splunk, GreyLog or LogStash will become part of the custom fields that you can parse. Once you use LogStash, Splunk or GreyLog with custom fields for headers, and requests etc. for debugging and log analysis, you will not know how you did it without it.

This is important and nice. But what if you have downstream services, i.e., ServiceQueue service or a ServiceBundle service. These services are running on other threads. Will QBit pass handle this case? Yes. Yes it will.

Downstream services example

To show QBit's ability to breach the thread chasm of other actor service queues, let's create some services.

And, in addition let's show off RequestContext which QBit uses to create this context by creating a service queue call stack to show the call stack.

Service to show capturing service call stack and MDC working N-levels deep

public interface InternalService {

    void getCallStack(Callback<List<String>> listCallback);
}

....


public class InternalServiceImpl {


    private final Logger logger = LoggerFactory.getLogger(InternalServiceImpl.class);
    private final RequestContext requestContext;

    public InternalServiceImpl(final RequestContext requestContext) {
        this.requestContext = requestContext;
    }

    public List<String> getCallStack() {

        logger.info("GET CallStack called");

        final Optional<MethodCall<Object>> currentMethodCall = requestContext.getMethodCall();

        if (!currentMethodCall.isPresent()) {
            logger.info("Method not found");
            return Arrays.asList("MethodCall Not Found");
        }

        final List<String> callStack = new ArrayList<>();
        MethodCall<Object> methodCall = currentMethodCall.get();
        callStack.add("Service Call(" + methodCall.objectName()
                + "." + methodCall.name() + ")");

        while (methodCall!=null) {

            final Request<Object> request = methodCall.originatingRequest();
            if (request ==null) {
                methodCall = null;
            } else if (request instanceof MethodCall) {
                methodCall = ((MethodCall<Object>) request);
                callStack.add("Service Call(" + methodCall.objectName()
                        + "." + methodCall.name() + ")");
            } else if (request instanceof HttpRequest) {
                final HttpRequest httpRequest = ((HttpRequest) request);

                callStack.add("REST Call(" + httpRequest.getRemoteAddress()
                        + "." + httpRequest.getUri() + ")");

                methodCall = null;
            } else {
                methodCall = null;
            }
        }

        return callStack;
    }

}

Now let's wire in this service twice. Once being used from a ServiceQueue (fastest) and once using a ServiceBundle. Notice the above calls logger.info("GET CallStack called"), and then it uses requestContext.getMethodCall() to get the current MethodCall in QBit. Note that a MethodCall is a Request in QBit, and an HttpRequest is a Request as well. You can now track the current MethodCall all the way back to the HttpRequest using the request.originatingRequest() method as shown above. We use originatingRequest to find the original HttpRequest and all of the MethodCall's in-between.

Wiring in InternalServiceImpl to show service queue call stack and logging mdc

    public static void main(String... args) throws Exception {
        final ManagedServiceBuilder managedServiceBuilder = ManagedServiceBuilder.managedServiceBuilder();


        managedServiceBuilder.setRootURI("/");

        managedServiceBuilder.enableLoggingMappedDiagnosticContext();

        /** Create Service from Service Queue. */
        final InternalService internalServiceFromServiceQueue = getInternalServiceFromServiceQueue(managedServiceBuilder);


        /** Create Service from Service Bundle. */
        final InternalService internalServiceFromServiceBundle = getInternalServiceFromServiceBundle(managedServiceBuilder);


        final StatsCollector statsCollectorForRest = managedServiceBuilder.getStatServiceBuilder().buildStatsCollector();

        final RestService restService = new RestService(internalServiceFromServiceBundle,
                internalServiceFromServiceQueue,
                ReactorBuilder.reactorBuilder().build(), Timer.timer(), statsCollectorForRest);

        managedServiceBuilder.addEndpointService(restService);


        managedServiceBuilder.getEndpointServerBuilder().build().startServer();


    }

    private static InternalService getInternalServiceFromServiceQueue(ManagedServiceBuilder managedServiceBuilder) {
        final InternalServiceImpl internalServiceImpl = new InternalServiceImpl(new RequestContext());
        final ServiceBuilder serviceBuilderForServiceObject = managedServiceBuilder.createServiceBuilderForServiceObject(internalServiceImpl);
        final ServiceQueue serviceQueue = serviceBuilderForServiceObject.buildAndStartAll();
        return serviceQueue.createProxy(InternalService.class);
    }


    private static InternalService getInternalServiceFromServiceBundle(ManagedServiceBuilder managedServiceBuilder) {
        final InternalServiceImpl internalServiceImpl = new InternalServiceImpl(new RequestContext());
        final ServiceBundle serviceBundle = managedServiceBuilder.createServiceBundleBuilder().build().startServiceBundle();
        serviceBundle.addServiceObject("myService", internalServiceImpl);
        return serviceBundle.createLocalProxy(InternalService.class, "myService");
    }

Then we use these services from the RestService example that we created to show a call stack from a ServiceQueue and a call stack from a ServiceBundle.

Using services to show call stack from ServiceQueue andServiceBundle.

@RequestMapping ("rest")
public class RestService extends BaseService {

    private final Logger logger = LoggerFactory.getLogger(RestService.class);
    private final InternalService internalServiceFromServiceQueue;
    private final InternalService internalServiceFromServiceBundle;

    public RestService(final InternalService internalServiceFromServiceBundle,
                       final InternalService internalServiceFromServiceQueue,
                       final Reactor reactor,
                       final Timer timer,
                       final StatsCollector statsCollector) {
        super(reactor, timer, statsCollector);
        this.internalServiceFromServiceBundle = internalServiceFromServiceBundle;
        this.internalServiceFromServiceQueue = internalServiceFromServiceQueue;
        reactor.addServiceToFlush(internalServiceFromServiceBundle);
        reactor.addServiceToFlush(internalServiceFromServiceQueue);
    }

    @RequestMapping ("callstack/queue")
    public void callStackFromQueue(final Callback<List<String>> callback) {
        logger.info("Logger {}", MDC.getCopyOfContextMap());
        internalServiceFromServiceQueue.getCallStack(callback);
    }

    @RequestMapping ("callstack/bundle")
    public void callStackFromBundle(final Callback<List<String>> callback) {
        logger.info("Logger {}", MDC.getCopyOfContextMap());
        internalServiceFromServiceBundle.getCallStack(callback);
    }

Now let's call this service with REST and see the results.

Calling REST service to see example service queue call stack

$ curl http://localhost:8080/rest/callstack/queue | jq .
[
  "Service Call(.getCallStack)",
  "Service Call(restservice.callStackFromQueue)",
  "REST Call(0:0:0:0:0:0:0:1:63881./rest/callstack/queue)"
]

Calling REST service to see example service bundle call stack

$ curl http://localhost:8080/rest/callstack/bundle | jq .
[
  "Service Call(myService.getCallStack)",
  "Service Call(restservice.callStackFromBundle)",
  "REST Call(0:0:0:0:0:0:0:1:63899./rest/callstack/bundle)"
]

Output

19:20:12.807 [QueueListener|Send Queue  rest] INFO  i.a.qbit.example.mdc.RestService - Logger {requestRemoteAddress=0:0:0:0:0:0:0:1:63909, requestUri=/rest/callstack/queue, requestHttpMethod=GET}
- 0:0:0:0:0:0:0:1:63909 - /rest/callstack/queue - GET

19:20:12.808 [QueueListener|Send Queue  internalserviceimpl] INFO  i.a.q.e.mdc.InternalServiceImpl - GET CallStack called
- 0:0:0:0:0:0:0:1:63909 - /rest/callstack/queue - GET

19:20:14.906 [QueueListener|Send Queue  rest] INFO  i.a.qbit.example.mdc.RestService - Logger {requestRemoteAddress=0:0:0:0:0:0:0:1:63910, requestUri=/rest/callstack/bundle, requestHttpMethod=GET}
- 0:0:0:0:0:0:0:1:63910 - /rest/callstack/bundle - GET

19:20:14.958 [QueueListener|Send Queue  /services/myService] INFO  i.a.q.e.mdc.InternalServiceImpl - GET CallStack called
- 0:0:0:0:0:0:0:1:63910 - /rest/callstack/bundle - GET

Think about this for a moment. We just passed our call context and we jumped the Thread call context chasm. Pretty cool?

Getting the current request context

You do not have to call ManagedServiceBuilder.enableLoggingMappedDiagnosticContext to get the request context. All you need to call is enableRequestChain. Calling enableRequestChain enables the request chain. There is some slight overhead for this, but this allows REST and WebSocket services to pass the originating request, methodCall, etc. to downstream services where it will be available via the RequestContext. Remember that a MethodCallHttpRequestWebSocketMessageEvent are all Requests objects in QBit. Calling ManagedServiceBuilder.enableLoggingMappedDiagnosticContext also enables ManagedServiceBuilder.enableRequestChain.

The class RequestContext allows you to access the current request or current method.

QBit's RequestContext class

package io.advantageous.qbit.service;

import io.advantageous.qbit.message.MethodCall;
import io.advantageous.qbit.message.Request;

import java.util.Optional;

/**
 * Holds the current request for the method call.
 */
public class RequestContext {
    /** Grab the current  request.
     *
     * @return Optional  request.
     */
    public Optional<Request<Object>> getRequest() {
        ...
    }

    /** Grab the current method call.
     *
     * @return Optional  method call.
     */
    public Optional<MethodCall<Object>> getMethodCall() {
       ... 
    }

...

}

In addition QBit provides a way to access the current HttpRequest associated with a service call chain. This is done via the HttpContext which extends the RequestContext.

QBit's HttpContext class

/**
 * Holds current information about the HttpRequest.
 */
public class HttpContext extends RequestContext {


    /** Grab the current http request.
     *
     * @return Optional http request.
     */
    public Optional<HttpRequest> getHttpRequest() {
        ...
    }
...

We can extend our example to capture the HttpContext. Let's add this to the RestService.

    @RequestMapping ("http-info")
    public String httpInfo() {

        final StringBuilder builder = new StringBuilder();
        final HttpContext httpContext = new HttpContext();
        final Optional<HttpRequest> httpRequest = httpContext.getHttpRequest();
        if (httpRequest.isPresent()) {
            builder.append("URI = ").append(httpRequest.get().getUri()).append("\n");
            builder.append("HTTP Method = ").append(httpRequest.get().getMethod()).append("\n");
            builder.append("USER AGENT = ").append(
                    httpRequest.get().getHeaders().getFirst(HttpHeaders.USER_AGENT)).append("\n");
        } else {
            builder.append("request not found");
        }


        final RequestContext requestContext = new RequestContext();

        if (requestContext.getMethodCall().isPresent()) {
            final MethodCall<Object> methodCall = requestContext.getMethodCall().get();
            builder.append("Object Name = ").append(methodCall.objectName()).append("\n");
            builder.append("Method Name = ").append(methodCall.name()).append("\n");
        }
        return builder.toString();
    }

The above shows how to use both HttpContext and another example of RequestContext.

$ curl http://localhost:8080/rest/http-info | jq .
"URI = /rest/http-info\nHTTP Method = GET\nUSER AGENT = curl/7.43.0\nObject Name = restservice\nMethod Name = httpInfo\n"



To read more details about QBit's MDC support read this MDC Logging Mapped Diagnostic Context for Microservices ad hoc monitoring.
We cover the design and provide more details on the above code examples. 

To learn more about microservices and QBit please read:

QBit Java Micorservices lib tutorials

The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.

Find more tutorial on QBit.

Reactive ProgrammingJava MicroservicesRick Hightower

High-speed microservices consulting firm and authors of QBit with lots of experience with Vertx - Mammatus Technology

Highly recommended consulting and training firm who specializes in microservices architecture and mobile development that are already very familiar with QBit and Vertx as well as iOS and Android - About Objects

Java Microservices Architecture

Microservice Service Discovery with Consul

Microservices Service Discovery Tutorial with Consul

Reactive Microservices

High Speed Microservices

Java Microservices Consulting

Microservices Training

Reactive Microservices Tutorial, using the Reactor

QBit is mentioned in the Restlet blog


Quick overview of QBit

The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.

Got a question? Ask here: QBit Google Group.

Everything is a queue. You have a choice. You can embrace it and control it. You can optimize for it. Or you can hide behind abstractions. QBit opens you up to peeking into what is going on, and allows you to pull some levers without selling your soul.

QBit is a library not a framework. You can mix and match QBit with Spring, Guice, etc.

QBit is FAST!

QBit the microservice framework for java

Core Features

  • Write REST based async microservices
  • Write Websocket based async microservices
  • Actor Service Queues using micro-batching for high-speed message passing
  • Strongly async typed event bus which can be distributed
  • Complex async call coordination (with the Reactor) for reactive programming
  • Built-in support for health checks (and integration with tools like Consul)
  • Built-in support for monitoring (and integration with wire protocols like StatsD)
  • Built-in support for Service Discovery (with integration with health system, DNS SRV records and Consul)
  • Integration with persistent queues



Best of both worlds for Microservices: Two Great Taste that Taste Great Together: QBit and Vertx3

posted Sep 22, 2015, 7:46 PM by Rick Hightower   [ updated Sep 22, 2015, 7:48 PM ]

QBit support Vertx 3. This allows you to create a service which can also serve up web pages and web resources for an app (an SPA). Prior to this, QBit has been more focused on just being a REST microservices, i.e., routing HTTP calls and WebSocket messages to Java methods. Rather then reinvent the world. QBit now supports Vertx 3.

The QBit support for Vertx 3 exceeds the support for Vertx 2.
QBit allows REST style support via annotations.

Example of QBit REST style support via annotations.

    @RequestMapping(value = "/todo", method = RequestMethod.DELETE)
    public void remove(final Callback<Boolean> callback, 
                       final @RequestParam("id") String id) {

        Todo remove = todoMap.remove(id);
        callback.accept(remove!=null);

    }
QBit, microservices lib, also provides integration with Consul, a typed event bus (which can be clustered), and really simplifies complex reactive async callback coordination between services, and a lot more. Please read through the QBit overview.
History: QBit at first only ran inside of Vertx2 . Then we decided to (client driven decision)  make it stand alone and we lost the ability to run it embedded inside of Vertx (we did not need it for any project on the road map). QBit was heavily inspired by Vertx and Akka.
Now you can use QBit features and Vertx 3 features via a mix and match model. You do this by setting up routers and/or a route in Vertx 3 to route to an HttpServer in QBit, and this takes about 1 line of code.
This means we can use Vertx 3's chunking, streaming, routing, etc. for complex HTTP support, HTTP auth, its Shiro Integration, etc. As well as use Vertx 3 as a normal HttpServer to serve up resources, but when we want to use REST style, async callbacks we can use QBit for routing REST calls to Java methods (as well as routing WebSocket messages to Java methods). We can access all of the features of Vertx 3. 
(Recall: QBit was originally written as a Vertx 2 add-on lib, but then we had clients that wanted to run in standalone and clients who wanted to use it with Servlets / Embedded Jetty. This is more coming back home versus a new thing. We also had pressure to add systems for microservices like monitoring, service discovery, health checks, etc. We did this at the same time Vertx 3 was adding similar features to support microservices.).
You can run QBit standalone and if you do, it uses Vertx 3 like a network lib, or you can run QBit inside of Vertx 3.
We moved this up the priority wish list for QBit for two reasons. We were going to start using Vertx support for DNS to read DNS entries for service discovery in a Heroku like environment. It made no sense to invest a lot of time using Vertx 2 API when we were switching to Vertx 3 in the short time. We also had some services that needed to deliver up an SPA (Single Page App), so we had to extend the support for Vertx anyway or add these features to QBit (which it sort of has but not really its focus so we would rather just delegate that to Vertx 3), and it made no sense to do that with Vertx 2.
Also the Vertx 3 environment and community is a very vibrant one with many shared philosophies to QBit. Let's cover where the Vertx3 integration and QBit come in.

Vertx 3 Integration and QBit, microservices lib integration, details. 
We added a new class called a VertxHttpServerBuilder (extends HttpServerBuilder), which allows one to build a QBit HTTP server from a vertx object, a vertxHttpServer and optionally from a Vertx router or a Vertx route.
Note that you can pass QBit HttpServerBuilder or a QBit HttpServer to a QBitEndpointServerBuilder to use that builder instead or HttpServer instead of the default.VertxHttpServerBuilder is a QBit HttpServerBuilder so you construct it, associate it with vertx, and then inject it into EndpointServerBuilder. This is how we integrate with the QBit REST/WebSocket support. If you are using QBit REST with Vertx, that is one integration point.
Also note that you can pass HttpServerBuilder or a HttpServer to aManagedServiceBuilder to use that builder instead or HttpServer instead of the default. If you wanted to use QBit REST and QBit Swagger support with Vertx then you would want to use ManagedServiceBuilder with this class.
Here are some docs taken from our JavaDocs for QBit VertxHttpServerBuilder.VertxHttpServerBuilder also allows one to pass a shared Vertx object if running inside of the Vertx world. It also allows one to pass a shared vertx HttpServer if you want to use more than just QBit routing. If you are using Vertx routing or you want to limit this QBit HttpServer to one route then you can pass a route.
Note: QBits Vertx 2 support is EOL. We will be phasing it out shortly.
Here are some code examples on how to mix and match QBit and Vertx3.

Usage

Creating a QBit HttpServer that is tied to a single vertx route

    HttpServer httpServer = VertxHttpServerBuilder.vertxHttpServerBuilder()
                    .setVertx(vertx).setHttpServer(httpServer).setRoute(route).build();
    httpServer.start();

Creating a QBit HttpServer server and passing a router so it can register itself as the default route

    Router router = Router.router(vertx); //Vertx router
    Route route1 = router.route("/some/path/").handler(routingContext -> {
    HttpServerResponse response = routingContext.response();
         // enable chunked responses because we will be adding data as
         // we execute over other handlers. This is only required once and
         // only if several handlers do output.
         response.setChunked(true);
         response.write("route1\n");

         // Call the next matching route after a 5 second delay
        routingContext.vertx().setTimer(5000, tid -> routingContext.next());
    });

    //Now install our QBit Server to handle REST calls.
    vertxHttpServerBuilder = VertxHttpServerBuilder.vertxHttpServerBuilder()
                    .setVertx(vertx).setHttpServer(httpServer).setRouter(router);

    HttpServer httpServer = vertxHttpServerBuilder.build();
    httpServer.start();
Note that you can pass HttpServerBuilder or a HttpServer toEndpointServerBuilder to use that builder instead or HttpServer instead of the default. If you are using QBit REST with Vertx, that is one integration point.

EndpointServerBuilder integration

    //Like before
    vertxHttpServerBuilder = VertxHttpServerBuilder.vertxHttpServerBuilder()
                    .setVertx(vertx).setHttpServer(httpServer).setRouter(router);

    //Now just inject it into the vertxHttpServerBuilder before you call build
    HttpServer httpServer = vertxHttpServerBuilder.build();
    endpointServerBuilder.setHttpServer(httpServer);
Also note that you can pass HttpServerBuilder or a HttpServer to aManagedServiceBuilder to use that builder instead or HttpServer instead of the default.
If you wanted to use QBit REST and QBit Swagger support with Vertx then you would want to use ManagedServiceBuilder with this class.

ManagedServiceBuilder integration

    //Like before
    vertxHttpServerBuilder = VertxHttpServerBuilder.vertxHttpServerBuilder()
                    .setVertx(vertx).setHttpServer(httpServer).setRouter(router);

    //Now just inject it into the vertxHttpServerBuilder before you call build
    HttpServer httpServer = vertxHttpServerBuilder.build();
    managedServiceBuilder.setHttpServer(httpServer);
Read Vertx guide on routing for more details Vertx Http Ext Manual.

Where do we go from here

QBit has a health system, and a microservices stats collections system. Vertx 3 provided similar support. QBit has an event bus. Vertx has an event bus. There is no reason why QBit can't provide Vertx implementations of its event bus (this is how the QBit event bus started), or for that matter integrate with Vertx's health system or its stats collection system. QBit has its own service discovery system with implementations that talk to DNS, Consul, or just monitor JSON files to be updated (for Chef Push, or Consul, etcd pull model). There is no reason QBit could not provide an implementation of its Service Discovery that worked with Vertx's clustering support. All of the major internal services that QBit provides are extensible with plugins via interfaces. There is plenty of opportunity for more integration of QBit and Vertx.
QBit and Vertx have both evolved to provide more and more support for microservices and there is a lot of synergy between the two libs.
QBit can also play well with Servlets, Spring MVC, Spring Boot, and other lightweight HTTP libs. QBit comes batteries included.

Find out more information on QBit here.
The Java microservice lib. QBit is a reactive programming lib for building microservices - JSON, HTTP, WebSocket, and REST. QBit uses reactive programming to build elastic REST, and WebSockets based cloud friendly, web services. SOA evolved for mobile and cloud. ServiceDiscovery, Health, reactive StatService, events, Java idiomatic reactive programming for Microservices.

1-10 of 29