Skip to content

[Detailed Tutorial] Building Microservices using QBit

Richard Hightower edited this page Jun 14, 2015 · 6 revisions

##Overview Microservices is now a very popular term. Microservices as of now has no solid definition but has certain aspects that are thematic to its applications. Many confuse microservices with SOA while in fact in many ways it is the opposite, For example SOA often embraces WSDL which is a very strongly typed and rigid way to define a service endpoint. On the other hand Microservices embrace 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. Microservices style is to recognize that the world is polyglot programming, and the easiest integration is around JSON, HTTP and other web standards like WebSocket.

#####Some of the Microservices characteristics: -microservice approach is to create smaller services that are focused on a small business domain or crosscutting concern. They are small so they can be released more often and are written to be malleable. They are easier to write. They are easier to change.

-The real drivers for Microservices Architecture are cloud/virtualization/OS containerization, EC2, proliferation of mobile devices, cheaper memory, more virtualization, more cores, SSD, trend towards fatter clients, 10 GBE, 100 GBE, etc.

-Dumb fast pipes and batching calls (turning them into streams) are a good indication that what you wrote is a microservice. Some call this style reactive programming.

-Microservices are not stateless. Microservices should own their data.

-With Microservices you should be able to exercise your service API via curl and have it return JSON.

-Microservices uses an async model and shouldn't be making blocking calls.

-microservices use service discovery and service monitoring to recover from failure and to spread load across more nodes.

#####Key ways to indentify Microservices:

-Keys ways to identify Java Microservices

-You don’t use an EAR or WAR files

-Your services have main methods

-You don’t auto-deploy java components, you auto-deploy AMI images or docker containers

-You use a fatjar that is runnable as a process (or sharded services) Or you use gradle distZip or distTar

-Your code is non-blocking. If you have to use a blocking API for integration, you do it from a non-blocking worker pool.

Building Microservices using QBit.

This wiki will walk trough the process of building simple microservices using QBit in baby steps.

What you will build

In this wiki we will build four simple examples starting with the simplest to a slightly more complex so we can demonstrate to you how to build Microservices using QBit. As we mentioned before in order to be a microservice, a service needs to run in a standalone process or a related group of standalone processes. To do so, Gradle can be very useful.

Therefore on the first example we will cover how to use gradle's application plugin to build and run a simple hello world example, and how to use distZip to Create ZIP archive including libs and start scripts so you can run this example from the install directory.

$ /opt/example/restful-qbit-1.0/bin/restful-qbit
Hello World!

On the second example we will build a simple Restfull microservice that responds with pong when we send it a ping request as follows:

$ curl http://localhost:9090/services/pongservice/ping
"pong"

On the third example we will add a service that take request params, pull the requests params as arguments to the method, in this case the method will be adding two numbers that are pulled from the URL. When we load the following URL:

http://localhost:9090/main/my/service/add?a=2&b=3

we get:

5

and when we load:

http://localhost:9090/main/my/service/add2/3/4

we get:

7

On the fourth example we will build a Restful example that is slightly more complex then the previous; you can add departments and employees to the departments, then you can access the employees/departments with a Restful request:

add a department:

curl -X POST http://localhost:9090/main/dir/department/?departmentId=1&name=Engineering

add an employee:

curl -H "Content-Type: application/json" -X POST /
-d '{"firstName":"Rick","lastName":"Hightower", "id": 1}'  /
http://localhost:9090/main/dir/department/employee/?departmentId=1

To list the employee:

$ curl http://localhost:9090/main/dir/employee/1

{"firstName":"Rick","lastName":"Hightower","id":1}

To list the department:

$ curl http://localhost:9090/main/dir/department/1

{"id":1,"employees":[{"firstName":"Rick","lastName":"Hightower","id":1}]}

We can delete an employee as follows:

curl -H "Content-Type: application/json" -X DELETE  http://localhost:9090/main/dir/employee?id=1

and finally we can delete an employee from a specific department as follows:

curl -H "Content-Type: application/json" -X DELETE  http://localhost:9090/main/dir/department/3/employee?id=4

How to complete this guide

In order to complete this example successfully you will need the following installed on your machine:

Now that your machine is all ready let's get started:

git clone https://github.com/fadihub/microservices-using-qbit.git

Once this is done you can test the service, let's first explain the process:

##First example How to use gradle One of the characteristics of a Microservice is that a service needs to run in a standalone process or a related group of standalone processes. Building a standalone application with gradle is quite easy. Here will demonstrate how to use gradle's plugin to build and run a simple Hello World example.

Here is the simple Hello World main to demonstrate gradle's application plugin:

package io.advantageous.examples;

public class Main {

    public static void main(String... args) {
        System.out.println("Hello World!");
    }
}

The gradle build file using java and application plugin:

apply plugin: 'java'
apply plugin:'application'

sourceCompatibility = 1.8
version = '1.0'
mainClassName = "io.advantageous.examples.Main"

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

To build this example simply do the following:

gradle clean build

To run it simply:

gradle run

There are tree more useful gradle commands: installDist Installs the application into a specified directory distZip Creates ZIP archive including libs and start scripts distTar Creates TAR archive including libs and start scripts

The application plug-in allows you to create scripts to start a process. These scripts work on all operating systems. Microservices run as standalone processes. The gradle application plug-in is a good fit for microservice development.

To Create ZIP archive including libs and start scripts:

gradle distZip

This will store zip file under ~/build/distribution/yourzipfile.zip

you can find it by:

$ find . -name "*.zip"
./build/distributions/restful-qbit-1.0.zip

Unzip the file and store it wherever you like:

unzip ./build/distributions/restful-qbit-1.0.zip -d /opt/example/

here it is stored under ~/opt/example. Now we can run this simple Hello World example from the installed directory:

$ /opt/example/restful-qbit-1.0/bin/restful-qbit
Hello World!

##Second example simple RestFul Microservice using QBit - The ping pong example.

First using gradle, import QBit's library. The gradle build file:

apply plugin: 'java'
apply plugin:'application'

sourceCompatibility = 1.8
version = '1.0'
mainClassName = "io.advantageous.examples.Main"

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile group: 'io.advantageous.qbit', name: 'qbit-vertx', version: '0.7.3-SNAPSHOT'
}

Then define The PongService; simply returns pong when it is called:

package io.advantageous.qbit.example;


import io.advantageous.qbit.annotation.RequestMapping;

@RequestMapping("/pongservice")
public class PongService {


    @RequestMapping("/ping")
    public String ping() {
        return "pong";
    }

}

The @RequestMapping defines the service as one that responsds to an HTTP call. If you do not specify the path, then the lower case name of the class and the lower case name of the method becomes the path. Thus PongService.ping() becomes /pongservice/ping. To bind this service to a port we use a service server. A service server is a server that hosts services like our pong service.

To bind in the service to a port:

package io.advantageous.examples;

import io.advantageous.qbit.server.ServiceEndpointServer;
import io.advantageous.qbit.server.EndpointServerBuilder;

public class Main {

    public static void main(String... args) {
        final ServiceEndpointServer serviceServer = EndpointServerBuilder
                .endpointServerBuilder()
                .setPort(9090).build();
        serviceServer.initServices(new PongService());
        serviceServer.startServer();
    }
}

Notice we pass an instance of the PongService to the initServices of the service server. If we want to change the root address from "services" to something else we could do this here it is changed from services to main:

 final ServiceEndpointServer serviceServer = EndpointServerBuilder
                .endpointServerBuilder()
                .setUri("/main")
                .setPort(9090).build();
        serviceServer.initServices(new PongService());
        serviceServer.startServer();

##The third example a service that takes request param - adding two numbers pulled from the URL

@RequestParam bellow allows you to pull the requests params as arguments to the method. If we pass a URL like: http://localhost:9090/main/my/service/add?a=1&b=2. QBit will use 1 for argument a and 2 for argument b.

@RequestMapping("/my/service")
public class SimpleService {

    @RequestMapping("/add")
    public int add(@RequestParam("a") int a,
                   @RequestParam("b") int b) {

        return a + b;
    }

To pass arguments which are part of the URL path. We do this by using the @PathVariable annotation. as follows:

  @RequestMapping("/add2/{0}/{1}")
    public int add2(@PathVariable int a, @PathVariable int b) {

        return a + b;

    }

Now we can pass the a and b arguments in the URL http://localhost:9090/main/my/service/add2/1/4

The 1 is correlates to the "a" argument to the method and the 4 correlates to the "b" arguments.

To add this new service to main do the following:

package io.advantageous.examples;

import io.advantageous.qbit.server.ServiceEndpointServer;
import io.advantageous.qbit.server.EndpointServerBuilder;

public class Main {

    public static void main(String... args) {
        final ServiceEndpointServer serviceServer = EndpointServerBuilder
                .endpointServerBuilder()
                .setUri("/main")
                .setPort(9090).build();
        serviceServer.initServices(
                new PongService(),
                new SimpleService());
        serviceServer.startServer();
    }
}

##The fourth example is another RestFul - The employee and department example.

Annotation such as @RequestMapping, @PathVariable, and lambda 8 expressions are heavily used here. To add an employee:

@RequestMapping(value = "/department/", method = RequestMethod.POST)
    public boolean addDepartment(  @RequestParam("departmentId")   final long departmentId,
                                @RequestParam("name")           final String name) {
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.getId() == departmentId).findAny();
        if (departmentOptional.isPresent()) {
            throw new IllegalArgumentException("Department " + departmentId + " already exists");
        }
        departmentList.add(new Department(departmentId, name));
        return true;
    }

To add an employee:

@RequestMapping(value = "/department/employee/", method = RequestMethod.POST)
    public boolean addEmployee(    @RequestParam("departmentId") final long departmentId,
                                    final Employee employee) {

        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.getId() == departmentId).findAny();
        if (!departmentOptional.isPresent()) {
            throw new IllegalArgumentException("Department not found");
        }


        final boolean alreadyExists = departmentOptional.get().employeeList().stream()
                .anyMatch(employeeItem -> employeeItem.getId() == employee.getId());

        if (alreadyExists) {
            throw new IllegalArgumentException("Employee with id already exists " + employee.getId());
        }
        departmentOptional.get().addEmployee(employee);
        return true;
    }

To list an employee:

@RequestMapping("/employee/{0}/")
    public Employee listEmployee(@PathVariable("employeeId") final long employeeId) {

        /* Find the department that has the employee. */
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.employeeList().stream()
                        .anyMatch(employee -> employee.getId() == employeeId)).findFirst();

        /* Find employee in department. */
        if (departmentOptional.isPresent()) {
            return departmentOptional.get().employeeList()
                    .stream().filter(employee -> employee.getId() == employeeId)
                    .findFirst().get();
        } else {
            return null;
        }
    }

To list a department:

@RequestMapping("/department/{0}/")
    public Department listDepartment(@PathVariable("departmentId") final long departmentId) {

        return departmentList.stream()
                .filter(department -> department.getId() == departmentId).findFirst().get();
    }

To remove an employee; here it find the employee in which department resides and removes it:

@RequestMapping(value = "/employee", method = RequestMethod.DELETE)
    public boolean removeEmployee(@RequestParam("id") final long employeeId) {

        /* Find the department that has the employee. */
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.employeeList().stream()
                        .anyMatch(employee -> employee.getId() == employeeId)).findFirst();

        /* Remove employee from department. */
        if (departmentOptional.isPresent()) {
            departmentOptional.get().removeEmployee(employeeId);
            return true;
        } else {
            return false;
        }
    }

To remove an employee from a specific department:

@RequestMapping(value = "/department/{departmentId}/employee", method = RequestMethod.DELETE)
    public boolean removeEmployeeFromDepartment(
            @PathVariable("departmentId")   final long departmentId,
            @RequestParam("id")             final long employeeId) {

        /* Find the department by id. */
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.getId() == departmentId).findFirst();

        /* Remove employee from department. */
        if (departmentOptional.isPresent()) {
            departmentOptional.get().removeEmployee(employeeId);
            return true;
        } else {
            return false;
        }
    }

To remove a department:

 @RequestMapping(value = "/department", method = RequestMethod.DELETE)
    public boolean removeDepartment(@RequestParam("id") final long departmentId) {

        return departmentList.removeIf(department -> departmentId == department.getId());
    }

Add this new service EmployeeDirectoryService to main:

package io.advantageous.qbit.example;

import io.advantageous.qbit.server.ServiceEndpointServer;
import io.advantageous.qbit.server.EndpointServerBuilder;

public class Main {

    public static void main(String... args) {
        final ServiceEndpointServer serviceServer = EndpointServerBuilder
                .endpointServerBuilder()
                .setUri("/main")
                .setPort(9090).build();
        serviceServer.initServices(
                new PongService(),
                new SimpleService(),
                new EmployeeDirectoryService());
        serviceServer.startServer();
    }
}

Before we test these examples let's list the entire code for these examples:

##The Full Code Listings

####Employee.java Listing

~/src/main/java/io.advantageous.qbit.example/Employee.java

package io.advantageous.qbit.example;

public class Employee {

    private String firstName;
    private String lastName;
    private final long id;

    public Employee(String firstName, String lastName, long id) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public long getId() {
        return id;
    }
}

####Department.java Listing

`~/src/main/java/io.advantageous.qbit.example/Department.java`

```java
package io.advantageous.qbit.example;

import java.util.ArrayList;
import java.util.List;

public class Department {

    private String name;
    private final long id;
    private final List<Employee> employees = new ArrayList();

    public Department(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public void addEmployee(final Employee employee) {
        employees.add(employee);
    }


    public boolean removeEmployee(final long id) {
        return employees.removeIf(employee -> employee.getId() == id);
    }

    public List<Employee> employeeList() {
        return employees;
    }


    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

####TestHelloMain.java Listing

~/src/main/java/io.advantageous.qbit.example/TestHelloMain.java

package io.advantageous.qbit.example;

public class TestHelloMain {

    public static void main(String... args) {
        System.out.println("Hello World!");
    }
}

####PongService.java Listing

~/src/main/java/io.advantageous.qbit.example/PongService.java

package io.advantageous.qbit.example;


import io.advantageous.qbit.annotation.RequestMapping;

@RequestMapping("/pongservice")
public class PongService {


    @RequestMapping("/ping")
    public String ping() {
        return "pong";
    }

}

####SimpleService.java Listing

~/src/main/java/io.advantageous.qbit.example/SimpleService.java

package io.advantageous.qbit.example;


import io.advantageous.qbit.annotation.PathVariable;
import io.advantageous.qbit.annotation.RequestMapping;
import io.advantageous.qbit.annotation.RequestParam;

@RequestMapping("/my/service")
public class SimpleService {

    @RequestMapping("/add")
    public int add(@RequestParam("a") int a,
                   @RequestParam("b") int b) {

        return a + b;
    }

    @RequestMapping("/add2/{0}/{1}")
    public int add2(@PathVariable int a, @PathVariable int b) {

        return a + b;

    }

//    @RequestMapping("/add3/{0}")
//    public int add3(@PathVariable int a, @RequestParam("b") int b) {
//
//
//        return a + b;
//
//    }

}

####EmployeeDirectoryService.java Listing

~/src/main/java/io.advantageous.qbit.example/EmployeeDirectoryService.java

package io.advantageous.qbit.example;


import io.advantageous.qbit.annotation.PathVariable;
import io.advantageous.qbit.annotation.RequestMapping;
import io.advantageous.qbit.annotation.RequestMethod;
import io.advantageous.qbit.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@RequestMapping("/dir")
public class EmployeeDirectoryService {


    private final List<Department> departmentList = new ArrayList<>();


    @RequestMapping("/employee/{0}/")
    public Employee listEmployee(@PathVariable("employeeId") final long employeeId) {

        /* Find the department that has the employee. */
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.employeeList().stream()
                        .anyMatch(employee -> employee.getId() == employeeId)).findFirst();

        /* Find employee in department. */
        if (departmentOptional.isPresent()) {
            return departmentOptional.get().employeeList()
                    .stream().filter(employee -> employee.getId() == employeeId)
                    .findFirst().get();
        } else {
            return null;
        }
    }



    @RequestMapping("/department/{0}/")
    public Department listDepartment(@PathVariable("departmentId") final long departmentId) {

        return departmentList.stream()
                .filter(department -> department.getId() == departmentId).findFirst().get();
    }



    @RequestMapping(value = "/department/", method = RequestMethod.POST)
    public boolean addDepartment(  @RequestParam("departmentId")   final long departmentId,
                                   @RequestParam("name")           final String name) {
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.getId() == departmentId).findAny();
        if (departmentOptional.isPresent()) {
            throw new IllegalArgumentException("Department " + departmentId + " already exists");
        }
        departmentList.add(new Department(departmentId, name));
        return true;
    }


    @RequestMapping(value = "/department/employee/", method = RequestMethod.POST)
    public boolean addEmployee(    @RequestParam("departmentId") final long departmentId,
                                   final Employee employee) {

        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.getId() == departmentId).findAny();
        if (!departmentOptional.isPresent()) {
            throw new IllegalArgumentException("Department not found");
        }


        final boolean alreadyExists = departmentOptional.get().employeeList().stream()
                .anyMatch(employeeItem -> employeeItem.getId() == employee.getId());

        if (alreadyExists) {
            throw new IllegalArgumentException("Employee with id already exists " + employee.getId());
        }
        departmentOptional.get().addEmployee(employee);
        return true;
    }




    @RequestMapping(value = "/employee", method = RequestMethod.DELETE)
    public boolean removeEmployee(@RequestParam("id") final long employeeId) {

        /* Find the department that has the employee. */
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.employeeList().stream()
                        .anyMatch(employee -> employee.getId() == employeeId)).findFirst();

        /* Remove employee from department. */
        if (departmentOptional.isPresent()) {
            departmentOptional.get().removeEmployee(employeeId);
            return true;
        } else {
            return false;
        }
    }


    @RequestMapping(value = "/department", method = RequestMethod.DELETE)
    public boolean removeDepartment(@RequestParam("id") final long departmentId) {

        return departmentList.removeIf(department -> departmentId == department.getId());
    }



    @RequestMapping(value = "/department/{departmentId}/employee", method = RequestMethod.DELETE)
    public boolean removeEmployeeFromDepartment(
            @PathVariable("departmentId")   final long departmentId,
            @RequestParam("id")             final long employeeId) {

        /* Find the department by id. */
        final Optional<Department> departmentOptional = departmentList.stream()
                .filter(department -> department.getId() == departmentId).findFirst();

        /* Remove employee from department. */
        if (departmentOptional.isPresent()) {
            departmentOptional.get().removeEmployee(employeeId);
            return true;
        } else {
            return false;
        }
    }

}

####Main.java Listing

~/src/main/java/io.advantageous.qbit.example/Main.java

package io.advantageous.qbit.example;

import io.advantageous.qbit.server.ServiceEndpointServer;
import io.advantageous.qbit.server.EndpointServerBuilder;

public class Main {

    public static void main(String... args) {
        final ServiceEndpointServer serviceServer = EndpointServerBuilder
                .endpointServerBuilder()
                .setUri("/main")
                .setPort(9090).build();
        serviceServer.initServices(
                new PongService(),
                new SimpleService(),
                new EmployeeDirectoryService());
        serviceServer.startServer();
    }
}

####build.gradle Listing

group = 'io.advantageous.qbit'
apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'application'

sourceCompatibility = 1.8
version = '1.0'


repositories {
    mavenLocal()
    mavenCentral()
}

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

task runTestHelloMain(type: JavaExec, dependsOn: 'classes') {

    main = 'io.advantageous.qbit.example.TestHelloMain'
    classpath = sourceSets.main.runtimeClasspath
}

task runMain(type: JavaExec, dependsOn: 'classes') {

    main = 'io.advantageous.qbit.example.ServiceMain'
    classpath = sourceSets.main.runtimeClasspath
}

task runPingMain(type: JavaExec, dependsOn: 'classes') {

    main = 'io.advantageous.qbit.example.PingMain'
    classpath = sourceSets.main.runtimeClasspath
}




dependencies {
    compile group: 'io.advantageous.qbit', name: 'qbit-vertx', version: '0.7.3-SNAPSHOT'


    compile "org.slf4j:slf4j-api:[1.7,1.8)"
    compile 'ch.qos.logback:logback-classic:1.1.2'

    testCompile group: 'junit', name: 'junit', version: '4.11'
}




idea {
    project {
        jdkName = '1.8'
        languageLevel = '1.8'
    }

}

##Testing The examples

With your terminal cd microservices-using-qbit

####Test the First example

gradle clean build output:

:clean
:compileJava
Note: /Users/fadi/examples/qbit/microservices-using-qbit/src/main/java/io/advantageous/qbit/example/Department.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:processResources
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Then gradle runTestHelloMain you should get the following:

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:runTestHelloMain
Hello World!

BUILD SUCCESSFUL

####Testing the second example

gradle runMain keep this terminal window running for the remaining examples, then open up another terminal window.

Then curl http://localhost:9090/main/pongservice/ping you should get the following:

"pong"

####Testing the third example

With your favorite browser visit http://localhost:9090/main/my/service/add?a=2&b=3 you should get:

5

then visit http://localhost:9090/main/my/service/add2/3/4 ou should get:

7

####Testing the fourth example

To add an engineering, HR, and Sales departments with your terminal:

curl -X POST http://localhost:9090/main/dir/department/?departmentId=1&name=Engineering
curl -X POST http://localhost:9090/main/dir/department/?departmentId=2&name=HR
curl -X POST http://localhost:9090/main/dir/department/?departmentId=3&name=Sales

If terminal asks you if it is true press enter and your department will be added

To add employees to the departments:

curl -H "Content-Type: application/json" -X POST /
-d '{"firstName":"Rick","lastName":"Hightower", "id": 1}'  /
http://localhost:9090/main/dir/departme\
nt/employee/?departmentId=1

curl -H "Content-Type: application/json" -X POST  /
-d '{"firstName":"Diana","lastName":"Hightower", "id": 2}'  /
http://localhost:9090/main/dir/departm\
ent/employee/?departmentId=2

To list employees do the following:

curl http://localhost:9090/main/dir/employee/1

you should get:

{"firstName":"Rick","lastName":"Hightower","id":1}

and

curl http://localhost:9090/main/dir/employee/2

you should get:

{"firstName":"Diana","lastName":"Hightower","id":2}

To list departments:

curl http://localhost:9090/main/dir/department/1

you should get:

{"id":1,"employees":[{"firstName":"Rick","lastName":"Hightower","id":1}]}

To delete an employee:

curl -H "Content-Type: application/json" -X DELETE  /
http://localhost:9090/main/dir/employee?id=2

to check go back and do:

curl http://localhost:9090/main/dir/employee/2

this time it won't return {"firstName":"Diana","lastName":"Hightower","id":2} like it did before.

You can also delete an employee from a specific department:

curl -H "Content-Type: application/json" -X DELETE  \
http://localhost:9090/main/dir/department/1/employee?id=2

That is it we are done...

##Summary In this wiki we went over four simple examples to demonstrate how to build Microservices using QBit and we also tested them, see you in the next tutorial!

Tutorials

__

Docs

Getting Started

Basics

Concepts

REST

Callbacks and Reactor

Event Bus

Advanced

Integration

QBit case studies

QBit 2 Roadmap

-- Related Projects

Kafka training, Kafka consulting, Cassandra training, Cassandra consulting, Spark training, Spark consulting

Clone this wiki locally