Oracle Helidonを使用したマイクロサービス
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]にあります。