Eclipse MicroProfileを使用したマイクロサービスの構築
1. 概要
この記事では、EclipseMicroProfileに基づくマイクロサービスの構築に焦点を当てます。
JAX-RS、CDI、JSON-PAPIを使用してRESTfulWebアプリケーションを作成する方法を見ていきます。
2. マイクロサービスアーキテクチャ
簡単に言えば、マイクロサービスは、いくつかの独立したサービスの集合として完全なシステムを形成するソフトウェアアーキテクチャスタイルです。
それぞれが1つの機能的な境界に焦点を合わせ、RESTなどの言語に依存しないプロトコルを使用して他と通信します。
3. Eclipse MicroProfile
Eclipse MicroProfileは、Microservicesアーキテクチャー向けにEnterprise Javaを最適化することを目的としたイニシアチブです。 これはJavaEE WebProfile APIのサブセットに基づいているため、JavaEEアプリケーションと同じようにMicroProfileアプリケーションを構築できます。
MicroProfileの目標は、マイクロサービスを構築するための標準APIを定義し、複数のMicroProfileランタイムにわたってポータブルアプリケーションを提供することです。
4. Mavenの依存関係
Eclipse MicroProfileアプリケーションの構築に必要なすべての依存関係は、次のBOM(Bill Of Materials)依存関係によって提供されます。
org.eclipse.microprofile
microprofile
1.2
pom
provided
MicroProfileランタイムにはすでにAPIと実装が含まれているため、スコープはprovidedとして設定されます。
5. 表現モデル
簡単なリソースクラスを作成することから始めましょう。
public class Book {
private String id;
private String name;
private String author;
private Integer pages;
// ...
}
ご覧のとおり、このBookクラスにはアノテーションがありません。
6. CDIの使用
簡単に言えば、CDIは依存性注入とライフサイクル管理を提供するAPIです。 WebアプリケーションでのエンタープライズBeanの使用を簡素化します。
次に、本の表現のストアとしてCDIマネージドBeanを作成しましょう。
@ApplicationScoped
public class BookManager {
private ConcurrentMap inMemoryStore
= new ConcurrentHashMap<>();
public String add(Book book) {
// ...
}
public Book get(String id) {
// ...
}
public List getAll() {
// ...
}
}
すべてのクライアントで状態が共有されるインスタンスが1つだけ必要なため、このクラスに@ApplicationScopedで注釈を付けます。 そのために、タイプセーフなメモリ内データストアとしてConcurrentMapを使用しました。 次に、CRUD操作のメソッドを追加しました。
これで、BeanはCDIに対応し、BeanBookEndpoint usingの@Injectアノテーションに注入できます。
7. JAX-RS API
JAX-RSでRESTアプリケーションを作成するには、@ApplicationPathで注釈が付けられたApplicationクラスと、@Path.で注釈が付けられたリソースを作成する必要があります。
7.1. JAX RSアプリケーション
JAX-RSアプリケーションは、Webアプリケーションでリソースを公開するベースURIを識別します。
次のJAX-RSアプリケーションを作成しましょう。
@ApplicationPath("/library")
public class LibraryApplication extends Application {
}
この例では、Webアプリケーション内のすべてのJAX-RSリソースクラスがLibraryApplicationに関連付けられており、同じlibraryパス(ApplicationPath annotation.の値)の下にあります。
この注釈付きクラスは、JAX RSランタイムに、リソースを自動的に見つけて公開するように伝えます。
7.2. JAXRSエンドポイント
Resourceクラスとも呼ばれるEndpointクラスは、1つのリソースを定義する必要がありますが、同じタイプの多くは技術的に可能です。
@Pathでアノテーションが付けられた、または@Path or @HttpMethodでアノテーションが付けられた少なくとも1つのメソッドを持つ各Javaクラスはエンドポイントです。
次に、その表現を公開するJAX-RSエンドポイントを作成します。
@Path("books")
@RequestScoped
public class BookEndpoint {
@Inject
private BookManager bookManager;
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getBook(@PathParam("id") String id) {
return Response.ok(bookManager.get(id)).build();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllBooks() {
return Response.ok(bookManager.getAll()).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response add(Book book) {
String bookId = bookManager.add(book);
return Response.created(
UriBuilder.fromResource(this.getClass())
.path(bookId).build())
.build();
}
}
この時点で、Webアプリケーションの/library/booksパスの下にあるBookEndpointリソースにアクセスできます。
7.3. JAX RSJSONメディアタイプ
JAX RSは、RESTクライアントと通信するための多くのメディアタイプをサポートしていますが、JSOP-P APIの使用を指定しているためEclipse MicroProfile restricts the use of JSONです。 そのため、メソッドに@Consumes(MediaType.APPLICATION_JSON)と@Produces(MediaType.APPLICATION_JSON).のアノテーションを付ける必要があります。
@Consumesアノテーションは、受け入れられる形式を制限します。この例では、JSONデータ形式のみが受け入れられます。 HTTPリクエストヘッダーContent-Typeはapplication/jsonである必要があります。
同じ考えが@Producesアノテーションの背後にあります。 JAX RSランタイムは、JSON形式への応答をマーシャリングする必要があります。 リクエストHTTPヘッダーAcceptはapplication/json.である必要があります
8. JSON-P
JAX RSランタイムはJSON-Pをすぐにサポートするため、メソッドの入力パラメーターまたは戻り値の型としてJsonObjectを使用できます。
しかし、現実の世界では、多くの場合、POJOクラスを使用します。 したがって、JsonObjectとPOJOの間のマッピングを行う方法が必要です。 ここで、JAXRSエンティティプロバイダーが活躍します。
JSON入力ストリームをBook POJOにマーシャリングするには、タイプBook,のパラメーターを使用してリソースメソッドを呼び出し、クラスBookMessageBodyReader:を作成する必要があります。
@Provider
@Consumes(MediaType.APPLICATION_JSON)
public class BookMessageBodyReader implements MessageBodyReader {
@Override
public boolean isReadable(
Class> type, Type genericType,
Annotation[] annotations,
MediaType mediaType) {
return type.equals(Book.class);
}
@Override
public Book readFrom(
Class type, Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
return BookMapper.map(entityStream);
}
}
同じプロセスを実行して、BookをJSON出力ストリームにアンマーシャリングします。つまり、BookMessageBodyWriter:を作成して、戻り値の型がBook,であるリソースメソッドを呼び出します。
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class BookMessageBodyWriter
implements MessageBodyWriter {
@Override
public boolean isWriteable(
Class> type, Type genericType,
Annotation[] annotations,
MediaType mediaType) {
return type.equals(Book.class);
}
// ...
@Override
public void writeTo(
Book book, Class> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException {
JsonWriter jsonWriter = Json.createWriter(entityStream);
JsonObject jsonObject = BookMapper.map(book);
jsonWriter.writeObject(jsonObject);
jsonWriter.close();
}
}
BookMessageBodyReaderとBookMessageBodyWriterには@Providerの注釈が付けられているため、JAXRSランタイムによって自動的に登録されます。
9. アプリケーションの構築と実行
MicroProfileアプリケーションは移植可能であり、準拠するMicroProfileランタイムで実行する必要があります。 アプリケーションをOpen Libertyでビルドして実行する方法を説明しますが、準拠しているEclipseMicroProfileを使用できます。
構成ファイルserver.xmlを使用してOpenLibertyランタイムを構成します。
jaxrs-2.0
cdi-1.2
jsonp-1.0
プラグインliberty-maven-pluginをpom.xmlに追加しましょう:
net.wasdev.wlp.maven.plugins
liberty-maven-plugin
2.1.2
io.openliberty
openliberty-runtime
17.0.0.4
zip
${basedir}/src/main/liberty/config/server.xml
${package.file}
${packaging.type}
false
project
/
${project.artifactId}-${project.version}.war
9080
9443
install-server
prepare-package
install-server
create-server
install-feature
package-server-with-apps
package
install-apps
package-server
このプラグインは、プロパティセットをスローするように構成可能です。
library
${project.build.directory}/${app.name}-service.jar
runnable
上記のexecの目標により、実行可能なjarファイルが生成されるため、アプリケーションは独立してデプロイおよび実行できる独立したマイクロサービスになります。 Dockerイメージとして展開することもできます。
実行可能jarを作成するには、次のコマンドを実行します。
mvn package
マイクロサービスを実行するには、次のコマンドを使用します。
java -jar target/library-service.jar
これにより、Open Libertyランタイムが開始され、サービスがデプロイされます。 エンドポイントにアクセスして、次のURLですべての書籍を取得できます。
curl http://localhost:9080/library/books
結果はJSONです:
[
{
"id": "0001-201802",
"isbn": "1",
"name": "Building Microservice With Eclipse MicroProfile",
"author": "example",
"pages": 420
}
]
1冊の本を入手するには、次のURLをリクエストします。
curl http://localhost:9080/library/books/0001-201802
そして結果はJSONです:
{
"id": "0001-201802",
"isbn": "1",
"name": "Building Microservice With Eclipse MicroProfile",
"author": "example",
"pages": 420
}
次に、APIを操作して新しい本を追加します。
curl
-H "Content-Type: application/json"
-X POST
-d '{"isbn": "22", "name": "Gradle in Action","author": "example","pages": 420}'
http://localhost:9080/library/books
ご覧のとおり、応答のステータスは201であり、ブックが正常に作成されたことを示しています。Locationは、ブックにアクセスできるURIです。
< HTTP/1.1 201 Created
< Location: http://localhost:9080/library/books/0009-201802
10. 結論
この記事では、Eclipse MicroProfileに基づいてシンプルなマイクロサービスを構築する方法を示し、JAX RS、JSON-P、およびCDIについて説明しました。
コードは利用可能ですover on Github;これはMavenベースのプロジェクトであるため、インポートしてそのまま実行するのは簡単です。