Edited at

QuarkusでDBと接続するWebAPI作ってみた


目的

巷で話題のQuarkusの使い勝手を確認した内容のまとめを残します。

Get Started だけは物足りなかったのでローカルで立てたPostgreSQLをHibernateで操作するRESTのWebAPIにしてみました。


事前準備


Mavenプロジェクト

QUARKUS - CREATING YOUR FIRST APPLICATIONを先に完了させておきます。

プロジェクトの状態はこんな感じです。

$ tree ./

./
├── pom.xml
├── quarkus_quickstart.iml
└── src
├── main
│   ├── docker
│   │   └── Dockerfile
│   ├── java
│   │   └── com
│   │   └── dsert
│   │   └── quickstart
│   │   ├── GreetingResource.java
│   │   └── GreetingService.java
│   └── resources
│   ├── META-INF
│   │   ├── microprofile-config.properties
│   │   └── resources
│   │   └── index.html
│   └── application.properties
└── test
└── java
└── com
└── dsert
└── quickstart
├── GreetingResourceTest.java
└── NativeGreetingResourceIT.java


PostgreSQL

適当にテーブルとかを作っておきます。

IntelliJで生成したDDLは以下のような感じです。

create database quarkus with owner quarkus;

create table if not exists users
(
id serial not null
constraint users_pk
primary key,
name varchar(255) not null
);


実装手順


依存関係

QUARKUS - EXTENSIONSの項目を参考にしながら、pom.xmlにHibernateとPostgreSQLの依存関係を追加します。

また、Get Startedのままの依存関係ではJSONでのリクエスト・レスポンスができないので、quarkus-resteasyquarkus-resteasy-jsonbに変更します。


pom.xml

<dependencies>

...
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jsonb</artifactId>
</dependency>

<!-- Hibernate ORM specific dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
<scope>provided</scope>
</dependency>

<!-- JDBC driver dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>



環境値

QUARKUS - APPLICATION CONFIGURATION GUIDEに記述されているように、application.propertiesで環境値の管理が可能です。

DB接続に必要な情報を以下のように記述します。


src/main/resources/application.properties

quarkus.datasource.url: jdbc:postgresql://localhost:5432/quarkus

quarkus.datasource.driver: org.postgresql.Driver
quarkus.datasource.username: quarkus
quarkus.datasource.password: quarkus-pass


ソースコード


Entity

データをマッピングする、テーブルに合うEntityオブジェクトを作成します。


src/main/java/com/dsert/quickstart/User.java

package com.dsert.quickstart;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity(name = "users")
public class User {
private int id;
private String name;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}



Service

DB操作をするサービスクラスを作ります。


src/main/java/com/dsert/quickstart/UserService.java

package com.dsert.quickstart;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import java.util.List;

@ApplicationScoped
public class UserService {
@Inject
EntityManager em;

@Transactional
public void createUser(String name) {
User user = new User();
user.setName(name);
this.em.persist(user);
}

public List<User> getUsers() {
return this.em.createNativeQuery("select * from users", User.class).getResultList();
}
}



Resource

HTTPリクエストを処理するリソースクラスを作ります。


src/main/java/com/dsert/quickstart/UserResource.java

package com.dsert.quickstart;

import javax.inject.Inject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserResource {
@Inject
UserService service;

@POST
public Map<String, String> createUser(User user) {
this.service.createUser(user.getName());
return Collections.singletonMap("message", "OK");
}

@GET
public List<User> getUsers() {
return this.service.getUsers();
}
}



動作確認


アプリケーション起動

気軽に起動したいので、DockerImageではなく、developmentモードで起動します。

mvn compile quarkus:dev                                                                                                                                                                    6.2m

[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.d-sert:quarkus_quickstart >--------------------
[INFO] Building quarkus_quickstart 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ quarkus_quickstart ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ quarkus_quickstart ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- quarkus-maven-plugin:0.11.0:dev (default-cli) @ quarkus_quickstart ---
[INFO] Using servlet resources quarkus_quickstart/src/main/resources/META-INF/resources
Listening for transport dt_socket at address: 5005
2019-03-13 08:49:58,673 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
2019-03-13 08:49:59,282 INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 609ms
2019-03-13 08:50:05,128 INFO [io.quarkus] (main) Quarkus 0.11.0 started in 6.638s. Listening on: http://127.0.0.1:8080
2019-03-13 08:50:05,130 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-postgresql, narayana-jta, resteasy, resteasy-jsonb]


HTTPリクエスト


POST

$ curl -X POST -H 'Content-Type: application/json' 'http://localhost:8080/users' -d '{"name": "sert"}'

{"message":"OK"}


GET

$ curl 'http://localhost:8080/users'

[{"id":5,"name":"sert"}]


最後に

本当はMySQLに繋ぎたかったのですが、MySQLのDriverがExtensionになく、

MariaDBのDriverでも上手く繋げなかったのでPostgreSQLで実施しました。

そのうちMySQLでリベンジしてみるつもりです。