Write a Reactive server with Micronaut

Micronaut Reactive HTTP Request Processing

Since Micronaut is built on Netty, it is possible to perform non-blocking I / O.

Reactive HTTP Request Processing

If your controller method returns a non-blocking type such as an RxJava Observable or a CompletableFuture then Micronaut will use the Event loop thread to subscribe to the result.

When the Controller method returns the RxJava ʻObservable or CompletableFuture, it uses the Event loop thread to subscribe to the Controller` result.

If however you return any other type then Micronaut will execute your @Controller method in a preconfigured I/O thread pool.

If it returns any other type, it will use the I / O thread pool.

The return type of Controller is important, isn't it?

Well, it's easy, but let's use it.

environment

Click here for this environment.

$ mn -V
| Micronaut Version: 1.0.4
| JVM Version: 1.8.0_191

Sample application

For the time being, create a template project.

$ mn create-app hello-reactive --build maven
$ cd hello-reactive

Leave the class with the main method as it is for the time being

src/main/java/hello/reactive/Application.java

package hello.reactive;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class);
    }
}

Let's make Controller.

src/main/java/hello/reactive/HelloReactiveController.java

package hello.reactive;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.reactivex.Flowable;
import org.reactivestreams.Publisher;

@Controller("/reactive")
public class HelloReactiveController {

}

Let's write the contents of the method.

First, let's check the documentation to see what type to return.

Reactive Responses

It seems like that.

In addition, it seems that you can use CompletableFuture or Reactive type for method arguments.

Let's create a text / event-stream method that returns a message every second.

    @Get(value = "/hello", produces = MediaType.TEXT_EVENT_STREAM)
    public Publisher<String> hello() {
        return Flowable
                .fromArray("Hello Reactive")
                .repeat(10)
                .delay(1, TimeUnit.SECONDS)
                .map(m -> String.format("[%s] %s", LocalDateTime.now(), m));
    }

When I checked the dependency of the created project, I found RxJava, so I used this.

$ ./mvnw dependency:tree

[INFO] +- io.micronaut:micronaut-runtime:jar:1.0.4:compile
[INFO] |  +- io.micronaut:micronaut-aop:jar:1.0.4:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.8:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
[INFO] |  +- io.reactivex.rxjava2:rxjava:jar:2.2.2:compile

Start and check.

$ curl -i localhost:8080/reactive/hello
HTTP/1.1 200 OK
transfer-encoding: chunked
Date: Wed, 20 Feb 2019 13:00:07 GMT
transfer-encoding: chunked
content-type: text/event-stream

data: [2019-02-20T13:00:08.861] Hello Reactive

data: [2019-02-20T13:00:09.940] Hello Reactive

data: [2019-02-20T13:00:10.943] Hello Reactive

data: [2019-02-20T13:00:11.946] Hello Reactive

data: [2019-02-20T13:00:12.948] Hello Reactive

data: [2019-02-20T13:00:13.950] Hello Reactive

data: [2019-02-20T13:00:14.953] Hello Reactive

data: [2019-02-20T13:00:15.954] Hello Reactive

data: [2019-02-20T13:00:16.956] Hello Reactive

data: [2019-02-20T13:00:17.959] Hello Reactive

Somehow, it works like that.

Let's write something that takes an argument.

    @Post(value = "echo", consumes = MediaType.TEXT_PLAIN, produces = MediaType.TEXT_EVENT_STREAM)
    public Publisher<String> echo(@Body Flowable<String> text) {
        return text.map(t -> "★" + t + "★");
    }

The input isn't streamed either ...

$ curl -i -XPOST -H 'Content-Type: text/plain' localhost:8080/reactive/echo -d 'hello'
HTTP/1.1 200 OK
transfer-encoding: chunked
Date: Wed, 20 Feb 2019 13:01:29 GMT
transfer-encoding: chunked
content-type: text/event-stream

data: ★hello★

Is it okay to put Reactor in the dependency?

For the time being, I was able to make a simple confirmation.

Recommended Posts

Write a Reactive server with Micronaut
Launch a stub server with WireMock
Prepare a LEMP Ubuntu 18 server with Ansible Galaxy
Create a web api server with spring boot
Set up a CentOS virtual server with Vagrant
Try DI with Micronaut
Play down with Raspberry PI4 as a server. Part 2
Write solidly with PhpStorm
[JUnit 5 compatible] Write a test using JUnit 5 with Spring boot 2.2, 2.3
Write tests with Minitest
[JUnit 5] Write a validation test with Spring Boot! [Parameterization test]
Hello World with Micronaut
Serverless Function with Micronaut
Implementing a large-scale GraphQL server in Java with Netflix DGS
Access Apache Kafka with Micronaut
Create a playground with Xcode 12
Draw a gradient with CAGradientLayer
To write a user-oriented program (1)
A story stuck with NotSerializableException
Implement a simple Web REST API server with Spring Boot + MySQL
Create a simple web server with the Java standard library com.sun.net.httpserver
A story of connecting to a CentOS 8 server with an old Ansible