[JAVA] Try launching a webAP server on the micro using Helidon

Overview

In this entry, a toolkit for developing Java microservices types "Helidon", Which was released last week 1.0 released. Let's launch a web service on the micro using io / # /). In a nutshell, it focuses on the compact launch of the Web API IF, which is required for microservices, and aims at the minimum configuration rather than the full stack.

Helidonのサイト

Assumed reader

--Java engineer --If possible, have knowledge of frameworks such as Spring Boot and Micronaut.

What is Helidon

Overview

Helidon is made by Oracle and is published on GitHub as open source software under the Apache2 license. The following is a quick translation of the explanation at the top of the site.

--Simple and fast ~ Compact and fast because it is just adding a library based on Netty --Supports MicroProfile ~ With MicroProfile's small class library at its core, JSON support (JAX-RS, JSON-P / B) and dependency injection (CDI) are suppressed. ――Has a Reactive Web server ~ Since Netty is built in as a Web server, you can start up immediately and use the features of Netty in the direction of Reactive. ――Has various observable points ~ It has points for observation such as metrics and tracing that are required for microservices, and it is easy to combine with Prometheus, Zipkin, Kubernetes, etc.

For those who understand, you can think of it as the following position. --In Java, Micronaut rather than Spring ――In Ruby, Sinatra rather than Rails --In Scala, Scalatra rather than Play --In terms of Node, Koa rather than Express

Overall structure

The table below summarizes what is written on page 1 of the site's Introduction. That's all we have.

layer component Description
Helidon SE RxServer Acts as a web server
Security Supports security
Config Supports loading settings
Helidon MP JAX-RS(Jersey) I / O support for web requests
JSON Processing JSON processing
CDI Dependency injection

Try to move

Premise

As long as Java8 can be run, this entry uses Corretto.

$ java -version
openjdk version "1.8.0_202"
OpenJDK Runtime Environment Corretto-8.202.08.2 (build 1.8.0_202-b08)
OpenJDK 64-Bit Server VM Corretto-8.202.08.2 (build 25.202-b08, mixed mode)

Write the source

Let's move the source in Introduction.

The main class is OK only with the following. (For simplicity, it throws without handling main exceptions)


package io.hrkt.helidontest;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import io.helidon.webserver.Routing;
import io.helidon.webserver.WebServer;

public class HelidontestApplication {

    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        WebServer webServer = WebServer
                .create(Routing.builder()
                        .any((req, res) -> res.send("It works!")).build())
                .start().toCompletableFuture().get(10, TimeUnit.SECONDS);

        System.out.println(
                "Server started at: http://localhost:" + webServer.port());
    }

}

The build.gradle file for running with Gradle has the following format.

plugins {
	id 'application'
	id 'java'
	id 'idea'
	id 'eclipse'
}

group = 'io.hrkt'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
mainClassName = "io.hrkt.helidontest.HelidontestApplication"

repositories {
	mavenCentral()
}

dependencies {
	implementation group: 'io.helidon.webserver', name: 'helidon-webserver', version: '1.0.0'
}

Start-up

Let's run it with the "run" task using gradle's "application" plugin.

$ ./gradlew run

> Task :run
2 21, 2019 6:21:17 am io.helidon.webserver.NettyWebServer lambda$start$7
information: Channel '@default' started: [id: 0x229c8f03, L:/0:0:0:0:0:0:0:0:53721]
Server started at: http://localhost:53721
<=========----> 75% EXECUTING [6s]
> :run

I will try to access it.

$ curl localhost:53721
It works!

It worked. The source at this point is on GitHub as 0.0.1.

Add settings

If you only use the above, you cannot actually use it, so let's try adding settings such as specifying the port number.

Modify the above source a little and use the ServerConfiguration class to do the following:

        int port = 8080;
        
        ServerConfiguration configuration = ServerConfiguration.builder().port(port).build();
        Routing routing = Routing.builder()
                .any((req, res) -> res.send("It works!")).build();
        WebServer webServer = WebServer
                .create(configuration, routing)
                .start().toCompletableFuture().get(10, TimeUnit.SECONDS);

        System.out.println(
                "Server started at: http://localhost:" + webServer.port());

$ ./gradlew run
> Task :run
2 21, 2019 7:30:45 am io.helidon.webserver.NettyWebServer lambda$start$7
information: Channel '@default' started: [id: 0x4a177e3e, L:/0:0:0:0:0:0:0:0:8080]
Server started at: http://localhost:8080

In this way, when starting the Web Server, the service is built by passing various operation settings and Routing.

The source at this point is on GitHub as 0.0.2.

Try adding Jersey (JAX-RS) resources

Add a resource class like the one below.

package io.hrkt.helidontest.resource;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/")
public class HelloWorld {

    @GET
    @Path("hello")
    public Response hello() {
        return Response.ok("Hello World!").build();
    }
}

Add the settings to the Routing of the main class. For the above source, it looks like this:

        Routing routing = Routing.builder().register("/jersey", 
                JerseySupport.builder()
                .register(HelloWorld.class) 
                .build())
                .any((req, res) -> res.send("It works!")).build();

Try to access / hello under the path added as / jersey.

$ curl localhost:8080/jersey/hello
Hello World!

I got the message I expected. For other paths, "It Works" is output as described above.

Try to read the configuration file

Try out the features around Config. Prepare the configuration file as src / main / resources / application.properties.

web.port=9801

In the above source code, the read part is like this.

        Config config = Config.create();
        int port = config.get("web.port").asInt().orElse(8080);

I will start it.

$ ./gradlew run

> Task :run
[DEBUG](main) Using Console logging
2 21, 2019 8:08:21 am io.helidon.webserver.NettyWebServer lambda$start$7
information: Channel '@default' started: [id: 0x4ea36bbe, L:/0:0:0:0:0:0:0:0:9801]
Server started at: http://localhost:9801

Above, you can see that the value specified in the config file (9801) is read and the value for fallback (8080) is not used.

As the configuration file, according to the document, YAML, HOCON, JSON can be used in addition to the "properties" used above. Use the corresponding jar files in addition to the dependencies.

Config records the load time. It also has a function to detect the update of the configuration file and start the corresponding handler. This is useful when you want to dynamically change the configuration after deploying the app.

        Instant loadTime = config.timestamp();
        System.out.println("Configfile was loaded at : " + loadTime);

Summary

I explained Helidon and tried to run a web server.

At the time of writing the entry, there were some parts where the tutorial code did not work as it was (such as the setting file reading system as in the release notes), probably because 1.0 was released and it was a short time, but the test code and It's a compact framework that you can roughly see by looking around the example.

You can find the source for this entry on GitHub (https://github.com/hrkt/helidontest).

I would like to write another entry about adding security.

Recommended Posts

Try launching a webAP server on the micro using Helidon
Try using the service on Android Oreo
Try communication using gRPC on Android + Java server
I tried using Log4j2 on a Java EE server
Using the database (SQL Server 2014) from a Java program 2018/01/04
Try using the query attribute of Ruby on Rails
I tried using the GitHub repository as a library server
Try Hello World using plain Java on a Docker container
Easily set up a Jenkins server on AWS using Bitnami's AMI
Try using Redmine on Mac docker
Build a Minecraft server on AWS
Put a badge on the icon
Try using the messaging system Pulsar
Using a local network on iOS 14
Building a DLNA server on Ubuntu (just move for the time being)
Try using || instead of the ternary operator
Try using the Stream API in Java
A note on the libGDX Utils class
Try using the Rails API (zip code)
Kick ShellScript on the server from Java
Try deploying a Rails app on EC2-Part 1-
Try building a GPU container on GCP.
Try using the Emotion API from Android
Try the Docker environment on AWS ECS
A rudimentary note on the Fibonacci sequence
Try using the Wii remote with Java
Try implementing GraphQL server using grahpql-java-tools (+ kotlin)
A quick note on using jshell with the official Docker image of the JDK