The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

2つ目のQuarkusアプリケーション

このチュートリアルでは、データベースへの書き込みとデータベースからの読み込みを行うアプリケーションの作成方法を説明します。 Dev Services を使用するので、実際にデータベースをダウンロードしたり、設定したり、起動したりすることはありません。 また、Hibernate ORM の上のレイヤーである Panache を使用して、データの読み書きを簡単にします。

このガイドは以下についてサポートします:

  • データベースへのオブジェクトの読み書き

  • ゼロ・コンフィギュレーションでサービスを開発し、テストする

前提条件

このガイドを完成させるには、以下が必要です:

  • ざっと 30 minutes

  • IDE

  • JDK 17+がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.9.6

  • 動作するコンテナランタイム(Docker, Podman)

  • 使用したい場合は、 Quarkus CLI

このチュートリアルは、 最初のQuarkusアプリケーションの作成 で学んだことを基に構成されています。 そのアプリケーションのコードは必要ありませんが、コンセプトは理解しておいてください。

ソリューション

[Bootstrapping the project] 以降の指示に従って、ステップ・バイ・ステップでアプリケーションを作成することをお勧めします。

しかしながら、完成した例をすぐ確認することもできます。

アーカイブ をダウンロードするか、gitレポジトリをクローンします:

git clone https://github.com/quarkusio/quarkus-quickstarts.git

ソリューションは、 getting-started-dev-services ディレクトリにあります。

1. 概略手順

  • アプリケーションのブートストラップ

  • ユーザー入力を読み取るためにアプリケーションを更新

  • Panache エンティティの作成

  • エンティティの読み書き

  • プロファイルを使用して外部データベースを設定

2. インタラクティブ・アプリケーションの設定

2.1. プロジェクトのブートストラップ

新しいQuarkusプロジェクトを作成する最も簡単な方法は、ターミナルを開いて以下のコマンドを実行することです:

コマンドラインインタフェース
quarkus create app org.acme:getting-started-dev-services \
    --extension='rest'
cd getting-started-dev-services

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストールと使用方法の詳細については、 Quarkus CLI ガイドを参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.9.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started-dev-services \
    -Dextensions='rest'
cd getting-started-dev-services

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=getting-started-dev-services"

生成されたアプリケーションの中身の説明については、 最初のアプリケーションガイド を参照してください。

2.2. アプリケーションの実行

Launch the application in dev mode

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

Once the application is up, visit http://localhost:8080/hello. It should show a "Hello from Quarkus REST" message.

2.3. Accepting user input

Let’s make the application a bit more interactive. Open the project in your IDE and navigate to src/main/java/org/acme/GreetingResource.java Add a query param in the hello method. (The org.jboss.resteasy.reactive.RestQuery annotation is like the Jakarta REST @QueryParam annotation, except you don’t need to duplicate the parameter name.)

public String hello(@RestQuery String name) {
    return "Hello " + name;
}

You should see a personalised message: Hello Bloom.

2.4. Fixing the tests

In your Quarkus terminal, type 'r' to run the tests. You should see that your application changes broke the tests!

To fix the tests, open src/test/java/org/acme/GreetingResourceTest.java and replace

             .body(is("Hello from Quarkus REST"));

with

             .body(containsString("Hello"));

This still validates the HTTP endpoint, but it’s more flexible about the expected output. You should see in your terminal that the tests are now passing.

3. 永続性の追加

3.1. Panache エンティティの作成

  1. 永続化ライブラリを追加するには以下を実行ください

コマンドラインインタフェース
quarkus extension add hibernate-orm-panache jdbc-postgresql
Maven
./mvnw quarkus:add-extension -Dextensions='hibernate-orm-panache jdbc-postgresql'
Gradle
./gradlew addExtension --extensions='hibernate-orm-panache jdbc-postgresql'

The application will record the names of people it greets. Define an Entity by creating a Greeting.java class. Add the following content:

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;

@Entity
public class Greeting extends PanacheEntity {
    public String name;
}

The entity makes use of Panache, a layer on top of Hibernate ORM. Extending PanacheEntity brings in a range of methods for reading, writing, and finding data. Because all the data access methods are on the Greeting entity, rather than on a separate data access class, this is an example of the active record pattern.

The Greeting table will have one column, a field called name.

3.2. Writing data

To use the new entity, update the hello method to start writing some data.

Change the method to the following:

@GET
@Transactional
@Produces(MediaType.TEXT_PLAIN)
public String hello(@QueryParam("name") String name) {
   Greeting greeting = new Greeting();
   greeting.name = name;
   greeting.persist();
   return "Hello " + name;
}

Don’t forget the @Transactional annotation, which ensures writes are wrapped in a transaction.

GETs should not change application state.
Generally, you shouldn’t do state updates in a GET REST method, but here it makes trying things out simpler. Let’s assume what’s being written is a logging "side effect", rather than a meaningful state changes!

Try out the updated endpoint by visiting http://localhost:8080/hello?name=Bloom. You should see a "Hello Bloom" message.

3.3. Reading data

Although the new persistence code seems to be working without errors, how do you know anything is being written to the database?

Add a second REST method to GreetingResource.

@GET
@Path("names")
@Produces(MediaType.TEXT_PLAIN)
public String names() {
    List<Greeting> greetings = Greeting.listAll();
    String names = greetings.stream().map(g-> g.name)
       .collect(Collectors.joining (", "));
    return "I've said hello to " + names;
}

You should see the following message: "I’ve said hello to Bloom".

a container runtime is required.

Don’t forget that you need to have a container runtime available, or you will start seeing failures in the Quarkus logs at this point.

4. Dev services

Reading and writing to the database seems to be working well, but that’s a bit unexpected. Where did a PostgreSQL database come from? You didn’t set anything up.

The database is being managed using Dev Services. Dev Services take care of stopping and starting services needed by your application. Because you included the jdbc-postgresql dependency, the database is a containerised PostgreSQL database. If you’d added jdbc-mysql instead, you would have gotten a containerised MySQL database.

If you like, use your container tool to see what containers are running. For example, if you’re using Docker, run docker ps, and for podman, run podman ps. You should see something like the following:

ff88dcedd899  docker.io/library/postgres:14  postgres -c fsync...  20 minutes ago  Up 20 minutes  0.0.0.0:34789->5432/tcp  nostalgic_bassi

Stop Quarkus and run docker ps again. You should see nothing running (it may take a few moments for containers to shut down). Quarkus will automatically stop the container when your application stops.

4.1. Initialising services

If you play with your code some more, you may notice that sometimes, after making an application change, http://localhost:8080/hello/names doesn’t list any names. What’s going on? By default, in dev mode, with a Dev Services database, Quarkus configures Hibernate ORM database generation to be drop-and-create. See the Hibernate configuration reference for more details. If a code change triggers an application restart, the database tables will be dropped (deleted) and then re-created.

This is convenient, but what if you’d prefer the database to always have content? That would make testing easier. If you provide an import.sql file, Quarkus will use that to initialise the database on each start.

  1. Make a src/main/resources/import.sql file in your project

  2. Add the following SQL statements:

INSERT INTO Greeting(id, name)
VALUES (nextval('Greeting_SEQ'), 'Alice');
INSERT INTO Greeting(id, name)
VALUES (nextval('Greeting_SEQ'), 'Bob');

Now, hit s in your dev mode session, to force a full restart. Then visit http://localhost:8080/hello/names.

You’ll see that Alice and Bob are always included in the list of names.

5. Controlling Dev Services

5.1. Using an external database instead

What if you’d rather use an external database that you manage yourself? Add the following to src/main/resources/application.properties:

# configure your datasource
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = leopold
quarkus.datasource.password = bloom
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase

This tells Quarkus that you don’t want it to start a Dev Service, because you have your own database. You don’t need to worry about starting the database, because you’re just seeing how to change the configuration.

Visit http://localhost:8080/hello/names. Instead of a list of names, you’ll get a red error screen. In the terminal where Quarkus is running. you’ll see the following stack error message:

2023-06-28 19:18:22,880 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello?name=fred failed, error id: 4f9b5ce6-3b08-41c5-af36-24eee4d1dd2b-2: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
        at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:98)
        at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
...

This makes sense; you’ve disabled the database Dev Service, but you haven’t started your own database.

5.2. Using profiles

Unless you want to, don’t worry about setting up an external database to resolve the connection error. Instead, you will go back to using the Dev Service. It made life easy!

But what about production? You won’t want to use Dev Services in production. In fact, Quarkus only starts Dev Services in dev and test modes.

Wouldn’t it be nice to configure an external database, but have it only used in production, so you could still use dev services the rest of the time?

Add a %prod. prefix to the database configuration. This means the configuration only applies to the prod profile

The configuration should look like this:

# configure your datasource
%prod.quarkus.datasource.db-kind = postgresql
%prod.quarkus.datasource.username = leopold
%prod.quarkus.datasource.password = bloom
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase

Now the external database will be used in prod mode, and Dev Services will be used in dev and test modes.

Check http://localhost:8080/hello/names. It should be working again, because the Dev Services have been re-enabled. Notice that there was no need to restart Quarkus for any of these changes.

まとめ

You’ve taken a simple REST application and updated it to write and read data from a database, using Hibernate ORM and Panache. The data was persisted to a 'real' database, without you having to configure anything.

関連コンテンツ