1概要


Helidon

は、最近Oracleからオープンソース化された新しいJavaマイクロサービスフレームワークです。これは、J4C(Java for Cloud)という名前でOracleプロジェクトで内部的に使用されていました。

このチュートリアルでは、フレームワークの主な概念について説明した後、Helidonベースのマイクロサービスの構築と実行に移ります。


2プログラミングモデル

現在、フレームワークはマイクロサービスを書くための2つのプログラミングモデルをサポートしています:Helidon SEとHelidon MP。

Helidon SEはリアクティブプログラミングモデルをサポートするマイクロフレームワークとして設計されていますが、一方Helidon MPはEclipse MicroProfileランタイムで、Java EEコミュニティがマイクロサービスを移植可能な方法で実行できるようにします。

どちらの場合も、Helidonマイクロサービスはmainメソッドから小さなHTTPサーバーを起動するJava SEアプリケーションです。


3ヘリドンSE

このセクションでは、Helidon SEの主要コンポーネントであるWebServer、Config、およびSecurityについて詳しく説明します。


3.1. Webサーバーの設定


WebServer APIを使い始めるには、

pom.xml__ファイルに必要なhttps://search.maven.org/search?q=a:helidon-webserver[Maven依存関係]を追加する必要があります。

<dependency>
    <groupId>io.helidon.webserver</groupId>
    <artifactId>helidon-webserver</artifactId>
    <version>0.10.4</version>
</dependency>

単純なWebアプリケーションを作成するには、


WebServer.create(serverConfig、routing)

または単に

WebServer.create(routing)


のいずれかのビルダーメソッドを使用できます。最後のものはサーバーがランダムなポートで動作することを可能にするデフォルトのサーバー設定を取ります。

これは、事前定義されたポート上で動作する簡単なWebアプリケーションです。また、「/

greet」

パスと

GET

メソッドを使用して、HTTPリクエストに対してグリーティングメッセージで応答する簡単なハンドラを登録しました。

public static void main(String... args) throws Exception {
    ServerConfiguration serverConfig = ServerConfiguration.builder()
      .port(9001).build();
    Routing routing = Routing.builder()
      .get("/greet", (request, response) -> response.send("Hello World !")).build();
    WebServer.create(serverConfig, routing)
      .start()
      .thenAccept(ws ->
          System.out.println("Server started at: http://localhost:" + ws.port())
      );
}

最後の行は、サーバーを始動してHTTP要求を処理するのを待つことです。

しかし、このサンプルコードをmainメソッドで実行すると、エラーが発生します。

Exception in thread "main" java.lang.IllegalStateException:
  No implementation found for SPI: io.helidon.webserver.spi.WebServerFactory


WebServer

は実際にはSPIであり、ランタイム実装を提供する必要があります。現在、

Helidonはhttps://netty.io/index.html[Netty]Coreに基づいた

NettyWebServer

実装

を提供しています。

この実装のhttps://search.maven.org/search?q=a:helidon-webserver-netty[Maven依存関係]は次のとおりです。

<dependency>
    <groupId>io.helidon.webserver</groupId>
    <artifactId>helidon-webserver-netty</artifactId>
    <version>0.10.4</version>
    <scope>runtime</scope>
</dependency>

これで、メインアプリケーションを実行し、設定されたエンドポイントを呼び出してそれが機能することを確認できます。

http://localhost:9001/greet

この例では、ビルダーパターンを使用してポートとパスの両方を構成しました。

Helidon SEでは、設定データが

Config

APIによって提供される設定パターンを使用することもできます。これが次のセクションの主題です。

……
……


3.2.

Config

API


  • Config

    APIは、設定ソースから設定データを読み込むためのツールを提供します** 。

Helidon SEは多くの設定ソースに実装を提供します。デフォルトの実装はhttps://search.maven.org/search?q=a:helidon-config[

helidon-config

]によって提供されます。ここで、設定ソースはクラスパスの下にある

application.properties

ファイルです。

<dependency>
    <groupId>io.helidon.config</groupId>
    <artifactId>helidon-config</artifactId>
    <version>0.10.4</version>
</dependency>

設定データを読み込むには、デフォルトで

application.properties:

から設定データを取得するデフォルトビルダーを使用するだけです。

Config config = Config.builder().build();

次の内容で

src/main/resource

ディレクトリの下に

application.properties

ファイルを作成しましょう。

server.port=9080
web.debug=true
web.page-size=15
user.home=C:/Users/app

  • 値を読むためには、

    Config.get()

    メソッドを使用し、その後に対応するJava型への便利なキャストを使用できます。

int port = config.get("server.port").asInt();
int pageSize = config.get("web.page-size").asInt();
boolean debug = config.get("web.debug").asBoolean();
String userHome = config.get("user.home").asString();

実際、デフォルトのビルダーは、最初に見つかったファイルをこの優先順位でロードします。__application.yaml、application.conf、application.json、およびapplication.properties。たとえば、YAML形式を使用するには、関連するYAML

config

依存関係を追加する必要があります。

<dependency>
    <groupId>io.helidon.config</groupId>
    <artifactId>helidon-config-yaml</artifactId>
    <version>0.10.4</version>
</dependency>

それから、

application.yml

を追加します。

server:
  port: 9080
web:
  debug: true
  page-size: 15
user:
  home: C:/Users/app

同様に、JSON簡易形式であるCONF、またはJSON形式を使用するには、https://search.maven.org/search?q=a:helidon-config-hocon[helidon-config-hoconを追加する必要があります。]依存関係。

これらのファイル内の設定データは、環境変数とJavaシステムプロパティによって上書きされる可能性があることに注意してください。

  • Environment変数とSystemプロパティを無効にするか、明示的に設定ソースを指定することで** ビルダーのデフォルトの動作を制御することもできます。

ConfigSource configSource = ConfigSources.classpath("application.yaml").build();
Config config = Config.builder()
  .disableSystemPropertiesSource()
  .disableEnvironmentVariablesSource()
  .sources(configSource)
  .build();

クラスパスから設定データを読み込むことに加えて、2つの外部ソース設定、すなわちgitとetcd設定を使うこともできます。これにはhttps://search.maven.org/search?q=a:helidon-config-git[helidon-config-git]とhttps://search.maven.org/search?q=aが必要です。 :helidon-config-etcd[helidon-git-etcd]依存関係。

最後に、これらすべての設定ソースが私たちのニーズを満たさない場合、Helidonは私たちが私たちの設定ソースの実装を提供することを可能にします。たとえば、データベースから構成データを読み取ることができる実装を提供できます。


3.3.

ルーティング

API


  • Routing

    APIは、HTTP要求をJavaメソッドにバインドするメカニズムを提供します** これを実現するには、要求メソッドとパスを一致条件として使用するか、またはより多くの条件を使用するための

    RequestPredicate

    オブジェクトを使用します。

そのため、ルートを設定するために、HTTPメソッドを基準として使用することができます。

Routing routing = Routing.builder()
  .get((request, response) -> {} );

あるいは、HTTPメソッドとリクエストパスを組み合わせることもできます。

Routing routing = Routing.builder()
  .get("/path", (request, response) -> {} );

より多くの制御のために

RequestPredicate

を使うこともできます。たとえば、既存のヘッダやコンテンツタイプを確認できます。

Routing routing = Routing.builder()
  .post("/save",
    RequestPredicate.whenRequest()
      .containsHeader("header1")
      .containsCookie("cookie1")
      .accepts(MediaType.APPLICATION__JSON)
      .containsQueryParameter("param1")
      .hasContentType("application/json")
      .thenApply((request, response) -> { })
      .otherwise((request, response) -> { }))
      .build();

これまでは、ハンドラを機能的なスタイルで提供してきました。より洗練された方法でハンドラを書くことを可能にする

Service

クラスを使うこともできます。

それでは、最初に、作業しているオブジェクト、

Book

クラスのモデルを作成しましょう。

public class Book {
    private String id;
    private String name;
    private String author;
    private Integer pages;
   //...
}


  • Service.update()

    メソッドを実装することで、

    Book

    クラスのRESTサービスを作成できます。これにより、同じリソースのサブパスを設定できます。

public class BookResource implements Service {

    private BookManager bookManager = new BookManager();

    @Override
    public void update(Routing.Rules rules) {
        rules
          .get("/", this::books)
          .get("/{id}", this::bookById);
    }

    private void bookById(ServerRequest serverRequest, ServerResponse serverResponse) {
        String id = serverRequest.path().param("id");
        Book book = bookManager.get(id);
        JsonObject jsonObject = from(book);
        serverResponse.send(jsonObject);
    }

    private void books(ServerRequest serverRequest, ServerResponse serverResponse) {
        List<Book> books = bookManager.getAll();
        JsonArray jsonArray = from(books);
        serverResponse.send(jsonArray);
    }
   //...
}

メディアタイプもJSONとして設定しました。そのためにはhttps://search.maven.org/search?q=a:helidon-webserver-json[helidon-webserver-json]依存関係が必要です。

<dependency>
    <groupId>io.helidon.webserver</groupId>
    <artifactId>helidon-webserver-json</artifactId>
    <version>0.10.4</version>
</dependency>

最後に、ルート・パスをリソースにバインドするために

Routing

Builderの

register()

メソッドを使用します。

Routing routing = Routing.builder()
  .register(JsonSupport.get())
  .register("/books", new BookResource())
  .build();

これでサーバーを起動してエンドポイントを確認できます。

http://localhost:9080/books
http://localhost:9080/books/0001-201810


3.4. セキュリティ

このセクションでは、

セキュリティモジュールを使用してリソースを保護します

必要な依存関係をすべて宣言することから始めましょう。

<dependency>
    <groupId>io.helidon.security</groupId>
    <artifactId>helidon-security</artifactId>
    <version>0.10.4</version>
</dependency>
<dependency>
    <groupId>io.helidon.security</groupId>
    <artifactId>helidon-security-provider-http-auth</artifactId>
    <version>0.10.4</version>
</dependency>
<dependency>
    <groupId>io.helidon.security</groupId>
    <artifactId>helidon-security-integration-webserver</artifactId>
    <version>0.10.4</version>
</dependency>


helidon-security

、https://search.maven.org/search?q=a:helidon-security-provider-http- auth[helidon-security-provider-http-auth]、およびhttps://search.maven.org/search?q=a:helidon-security-integration-webserver[helidon-security-integration-webserver]依存関係は、から入手できます。 Maven Central

セキュリティモジュールは、認証と承認のために多くのプロバイダを提供しています。

この例では、HTTPの基本認証プロバイダ

を使用します。これは非常に簡単ですが、他のプロバイダのプロセスもほぼ同じです。

  • 最初にやるべきことは、

    Security

    インスタンスを作成することです。単純化するために、プログラム的に行うこともできます。

Map<String, MyUser> users =//...
UserStore store = user -> Optional.ofNullable(users.get(user));

HttpBasicAuthProvider httpBasicAuthProvider = HttpBasicAuthProvider.builder()
  .realm("myRealm")
  .subjectType(SubjectType.USER)
  .userStore(store)
  .build();

Security security = Security.builder()
  .addAuthenticationProvider(httpBasicAuthProvider)
  .build();

あるいは、設定方法を使用することもできます。

この場合、

Config

APIを通してロードした

application.yml

ファイルですべてのセキュリティ設定を宣言します。

#Config 4 Security ==> Mapped to Security Object
security:
  providers:
  - http-basic-auth:
      realm: "helidon"
      principal-type: USER # Can be USER or SERVICE, default is USER
      users:
      - login: "user"
        password: "user"
        roles:["ROLE__USER"]      - login: "admin"
        password: "admin"
        roles:["ROLE__USER", "ROLE__ADMIN"]
  #Config 4 Security Web Server Integration ==> Mapped to WebSecurity Object
  web-server:
    securityDefaults:
      authenticate: true
    paths:
    - path: "/user"
      methods:["get"]      roles-allowed:["ROLE__USER", "ROLE__ADMIN"]    - path: "/admin"
      methods:["get"]      roles-allowed:["ROLE__ADMIN"]----

それをロードするには、__Config__オブジェクトを作成してから__Security.fromConfig()__メソッドを呼び出すだけです。

[source,java,gutter:,true]

Config config = Config.create();
Security security = Security.fromConfig(config);

**  __Security__インスタンスを作成したら、まず__WebSecurity.from()__メソッドを使用して__WebServer__に登録する必要があります。

[source,java,gutter:,true]

Routing routing = Routing.builder()
.register(WebSecurity.from(security).securityDefaults(WebSecurity.authenticate()))
.build();

セキュリティとWebサーバー設定の両方を読み込む設定アプローチを使用して、__WebSecurity__インスタンスを直接作成することもできます。

[source,java,gutter:,true]

Routing routing = Routing.builder()
.register(WebSecurity.from(config))
.build();

__/user__および__/admin__パス用のハンドラーをいくつか追加し、サーバーを起動してそれらにアクセスしてみます。

[source,java,gutter:,true]

Routing routing = Routing.builder()
.register(WebSecurity.from(config))
.get(“/user”, (request, response) → response.send(“Hello, I’m Helidon SE”))
.get(“/admin”, (request, response) → response.send(“Hello, I’m Helidon SE”))
.build();

===  **  4ヘリドンMP **

**  Helidon MPはEclipse MicroProfile ** の実装であり、MicroProfileベースのマイクロサービスを実行するためのランタイムも提供します。

https://www.baeldung.com/eclipse-microprofile[Eclipse MicroProfileに関する記事]をすでに持っているので、そのソースコードをチェックアウトし、Helidon MPで動作するように修正します。

コードをチェックアウトしたら、すべての依存関係とプラグインを削除し、Helidon MPの依存関係をPOMファイルに追加します。

[source,xml,gutter:,true]

<dependency>
<groupId>io.helidon.microprofile.bundles</groupId>
<artifactId>helidon-microprofile-1.2</artifactId>
<version>0.10.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>2.26</version>
</dependency>

https://search.maven.org/search?q=a:helidon-microprofile-1.2[helidon-microprofile-1.2]およびhttps://search.maven.org/search?q=a:jersey-media- json-binding[jersey-media-json-binding]依存関係はMaven Centralから入手できます。

次に、**  __ src/main/resource/META-INF__ディレクトリに__beans.xml__ファイルを追加します。

[source,xml,gutter:,true]

<beans xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns=”http://xmlns.jcp.org/xml/ns/javaee”
xsi:schemaLocation=”http://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/beans


2

0.xsd”
version=”2.0″ bean-discovery-mode=”annotated”>
</beans>

__LibraryApplication__クラスで、サーバーがリソースをスキャンしないように__getClasses()__メソッドをオーバーライドします。

[source,java,gutter:,true]

@Override
public Set<Class<?>> getClasses() {
return CollectionsHelper.setOf(BookEndpoint.class);
}

最後に、mainメソッドを作成して次のコードスニペットを追加します。

[source,java,gutter:,true]

public static void main(String…​ args) {
Server server = Server.builder()
.addApplication(LibraryApplication.class)
.port(9080)
.build();
server.start();
}

以上です。これで、書籍のすべてのリソースを呼び出すことができます。

===  **  5結論**

この記事では、Helidonの主要コンポーネントについて説明し、Helidon SEとMPのどちらを設定するかについても説明しました。 Helidon MPは単なるEclipse MicroProfileランタイムなので、それを使用して既存のMicroProfileベースのマイクロサービスを実行できます。

いつものように、上記のすべての例のコードはhttps://github.com/eugenp/tutorials/tree/master/helidon[over on GitHub]にあります。