-
Notifications
You must be signed in to change notification settings - Fork 140
[Detailed Tutorial] Building Microservices using QBit
##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.
This wiki will walk trough the process of building simple microservices using QBit in baby steps.
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
In order to complete this example successfully you will need the following installed on your machine:
- Gradle; if you need help installing it, visit Installing Gradle.
- Your favorite IDE or text editor (we recommend [Intellig IDEA ] (https://www.jetbrains.com/idea/) latest version).
- [JDK ] (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 1.8 or later.
- Build and install QBit on your machine click [Building QBit ] (https://github.com/advantageous/qbit/wiki/%5BQuick-Start%5D-Building-QBit-the-microservice-lib-for-Java) for instrutions.
Now that your machine is all ready let's get started:
- [Download ] (https://github.com/fadihub/microservices-using-qbit/archive/master.zip) and unzip the source repository for this guide, or clone it using Git:
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!
QBit Website 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.
Reactive Programming, Java Microservices, Rick Hightower
Java Microservices Architecture
[Microservice Service Discovery with Consul] (http://www.mammatustech.com/Microservice-Service-Discovery-with-Consul)
Microservices Service Discovery Tutorial with Consul
[Reactive Microservices] (http://www.mammatustech.com/reactive-microservices)
[High Speed Microservices] (http://www.mammatustech.com/high-speed-microservices)
Reactive Microservices Tutorial, using the Reactor
QBit is mentioned in the Restlet blog
All code is written using JetBrains Idea - the best IDE ever!
Kafka training, Kafka consulting, Cassandra training, Cassandra consulting, Spark training, Spark consulting
Tutorials
- QBit tutorials
- Microservices Intro
- Microservice KPI Monitoring
- Microservice Batteries Included
- RESTful APIs
- QBit and Reakt Promises
- Resourceful REST
- Microservices Reactor
- Working with JSON maps and lists
__
Docs
Getting Started
- First REST Microservice
- REST Microservice Part 2
- ServiceQueue
- ServiceBundle
- ServiceEndpointServer
- REST with URI Params
- Simple Single Page App
Basics
- What is QBit?
- Detailed Overview of QBit
- High level overview
- Low-level HTTP and WebSocket
- Low level WebSocket
- HttpClient
- HTTP Request filter
- HTTP Proxy
- Queues and flushing
- Local Proxies
- ServiceQueue remote and local
- ManagedServiceBuilder, consul, StatsD, Swagger support
- Working with Service Pools
- Callback Builders
- Error Handling
- Health System
- Stats System
- Reactor callback coordination
- Early Service Examples
Concepts
REST
Callbacks and Reactor
Event Bus
Advanced
Integration
- Using QBit in Vert.x
- Reactor-Integrating with Cassandra
- Using QBit with Spring Boot
- SolrJ and service pools
- Swagger support
- MDC Support
- Reactive Streams
- Mesos, Docker, Heroku
- DNS SRV
QBit case studies
QBit 2 Roadmap
-- Related Projects
- QBit Reactive Microservices
- Reakt Reactive Java
- Reakt Guava Bridge
- QBit Extensions
- Reactive Microservices
Kafka training, Kafka consulting, Cassandra training, Cassandra consulting, Spark training, Spark consulting