Quarkus Spring Extension で簡単な API を作成してみる
今回は https://quarkus.io/guides/spring-di これらのチュートリアルを参考に簡単な API を作成しました。
今 Quakus の公式ではこんな感じで Spring boot の互換性という事で Extension for Spring といったものが公開されています。
Quakus は起動も早くメモリ使用量も少ない、割と最近出てきた人気のフレームワークだけど学習コストなどを懸念して手を出し辛かった。。。そんな人も慣れた Spring boot と同じ様に開発していけるなら敷居も低くなるのでは?
API 概要
今回作るのはこんなドメインモデルを持った書籍管理 API。練習用のなんてことのない CRUD をやります。3層構造で作ります。
public class Book {
private Integer id;
private String title;
private String author;
private Integer cost;
}
Dependency
maven 使ってます。
今回使ってみるのはこの3つ。pom にこいつらを追加します。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-di</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-web</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-data-jpa</artifactId>
</dependency>
Controller
CRUD と言ってもどれもそんな変わらないので今回は GET と POST だけ作りました。 Spring を使っている人なら見慣れたアノテーションが使われています。
@RestController
@RequestMapping("book")
public class BookController {
@Autowired
private BookService bookService;
/**
* 指定した id の本を取得するためのエンドポイントです。
*
* @param bookId 取得したい本の id
* @return 取得した本
*/
@GetMapping(path = "/{id}")
@Produces(MediaType.APPLICATION_JSON)
public BookResponse getBook(@PathVariable("id") String bookId) {
Book book = bookService.getBook(Integer.parseInt(bookId));
return BookResponse.of(book);
}
/**
* 指定した本を登録するためのエンドポイントです
*
* @param request 登録したい本のリクエスト
* @return 登録した本
*/
@PostMapping
@Produces(MediaType.APPLICATION_JSON)
public CreateBookResponse createBook(CreateBookRequest request) {
Book book = bookService.createBook(request.toModel());
return CreateBookResponse.of(book);
}
}
Service
@Service
@Configuration
public class BookServiceImpl implements BookService {
@Autowired
BookRepository bookRepository;
private static final String LOCAL_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LOCAL_DATE_TIME_FORMAT);
/**
* {@inheritDoc}
*/
@Override
public Book getBook(Integer bookId) {
Optional<BookEntity> optionalBookEntity = bookRepository.findById(bookId);
if (optionalBookEntity.isPresent()) {
BookEntity bookEntity = optionalBookEntity.get();
return Book.builder()
.id(bookEntity.getId())
.title(bookEntity.getTitle())
.author(bookEntity.getAuthor())
.cost(bookEntity.getCost())
.build();
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public Book createBook(Book book) {
BookEntity bookEntity = BookEntity.builder()
.cost(book.getCost())
.title(book.getTitle())
.author(book.getAuthor())
.createdAt(Timestamp.valueOf(LocalDateTime.now().format(dateTimeFormatter)))
.updatedAt(Timestamp.valueOf(LocalDateTime.now().format(dateTimeFormatter)))
.build();
BookEntity createdEntity = bookRepository.save(bookEntity);
return Book.builder()
.id(createdEntity.getId())
.title(createdEntity.getTitle())
.author(createdEntity.getAuthor())
.cost(createdEntity.getCost())
.build();
}
}
Repository
Spring data jpa を使っています。現在実際のプロジェクトでも Quakus を使っていますが開発を始めた当初はこんな Extension はなかったので普通に Java EE の jpa を使っています。簡単な CRUD ならデータアクセスの部分、Repository を書かなくても良いので楽です。
public interface BookRepository extends CrudRepository<BookEntity, Integer> {
}
はい、こんな感じで Spring で書くのと全く同じ様に Quarkus でも作っていくことが可能です。細かいところは端折っていますがこれでもう Quarkus として起動できました。
test は QuarkusTest で作りました。 以前は QuarkusTest で Mockito も使えなかったので自分達で Mock を作成していましたが今は使える様になってます。
@QuarkusTest
class BookControllerTest {
@InjectMock
BookService bookService;
@Test
void test_指定したidで本を取得できる() {
when(bookService.getBook(1)).thenReturn(Book.builder()
.id(1)
.title("java 入門")
.author("hoge")
.cost(5000)
.build());
given()
.when()
.pathParam("id", "1")
.get("/book/{id}")
.then()
.statusCode(200)
.body("id", equalTo(1))
.body("title", equalTo("java 入門"))
.body("cost", equalTo(5000));
verify(bookService).getBook(1);
}
@Test
void test_POSTでリクエストして本が登録できる事() {
when(bookService.createBook(Book.builder()
.title("swift 入門")
.author("huga")
.cost(3000)
.build()))
.thenReturn(Book.builder()
.id(1)
.title("swift 入門")
.author("huga")
.cost(3000)
.build());
given()
.when()
.contentType("application/json")
.body(marshalToJson(CreateBookRequest.builder()
.title("swift 入門")
.author("huga")
.cost(3000)
.build()))
.post("/book")
.then()
.statusCode(200)
.body("message", equalTo("Book successfully created!"))
.body("title", equalTo("swift 入門"))
.body("cost", equalTo(3000));
}
}
コードは git にもアップしていますのでそちらも参考にして下さい。
https://github.com/tsukasaM/book-quarkus-spring-extension
まとめ
以上です。今回は Quarkus の Spring Extension を使って簡単な API を作成しました。主な実装箇所は 通常の Spring boot と同じシンタックスで書ける事がわかりました。 次回は 元々 Spring で作っていた API をコードをいじらずに Quakus で起動できるかやってみたいと思います。(たぶん)
学習書籍
Quarkus Cookbook【電子書籍】[ Alex Soto Bueno ]
Spring Boot2徹底活用 現場至上主義 [ 廣末丈士 ]
【中古】 Apache Maven2.0入門 Java・オープンソース・ビルドツール /野瀬直樹,横田健彦【著】 【中古】afb
ディスカッション
コメント一覧
まだ、コメントがありません