[Java][JHipster]バリデーションチェックを行う
はじめに
前回はJHipsterを使いScaffoldでデータをCRUDする機能を実装しました。今回はこれに、サーバ側でバリデーションを行う機能を追加する方法について書きたいと思います。
実装する機能について
前回作成したArticleのEntityを登録する際に、同じタイトルが既に登録されていたらエラーとするバリデーションを実装します。画面上では以下の様な感じとなります。
バリデーションの実装
上記のバリデーションを実現するには以下を実装する必要があります。
- (入力した)タイトルに一致するArticleを検索する機能
- バリデーションの判定を行い、エラー時にはエラーを返却する機能
- 画面にエラーメッセージを表示する機能
以下、それぞれの実装について見ていきたいと思います。
タイトルに一致するArticleを検索する機能
この機能はデータの検索機能となるため、Repository層に実装します。「src/main/java/org/jhipster/repository/ArticleRepository.java」に「findByCurrentUserAndTitle」という名前で作成します。
src/main/java/org/jhipster/repository/ArticleRepository.java
package org.jhipster.repository; (中略) /** * Spring Data JPA repository for the Article entity. */ @SuppressWarnings("unused") public interface ArticleRepository extends JpaRepository<Article,Long> { (中略) @Query("select article from Article article where article.user.login = ?#{principal.username} and article.title = :title") List<Article> findByCurrentUserAndTitle(@Param("title")String title); }
Articleはユーザ毎に作成されるため、検索条件にユーザ名とタイトルを指定してArticleを検索しています(同一ユーザ名のユーザが複数いる場合については・・・、今回は無視します)。「@Query」でSQL文を記述しているため直感的に分かるかと思います。
バリデーション判定
バリデーションの判定については、画面で入力したデータのPostリクエストを受け取るコントローラに実装しました。
/src/main/java/org/jhipster/web/rest/ArticleResource.java
@PostMapping("/articles") @Timed public ResponseEntity<Article> createArticle(@Valid @RequestBody Article article) throws URISyntaxException { log.debug("REST request to save Article : {}", article); if (article.getId() != null) { return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new article cannot already have an ID")).body(null); } List<Article> articles = articleRepository.findByCurrentUserAndTitle(article.getTitle()); if(!articles.isEmpty()){ return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "article.titleexists", "Title already exist!")).body(null); } Article result = articleRepository.save(article); return ResponseEntity.created(new URI("/api/articles/" + result.getId())) .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString())) .body(result); }
8〜11行目が今回追加したソースです。8行目で先に実装した「findByCurrentUserAndTitle」を呼び出して、タイトルが一致するデータを取得しています。9〜11行目ではデータが存在するかを判定し、存在する場合にはエラーメッセージのキー(「article.titleexists」)を指定して返却しています。6行目のreturn文とほぼ同じなのに注目してください。これはエラーメッセージ以外はScaffoldで作成された仕組みを踏襲しているためです。
画面に表示するエラーメッセージ
JHipsterではメッセージの定義にi18nを使用しています。今回は使用言語がデフォルト(英語)の場合のみメッセージを定義しました。「/src/main/webapp/i18n/en/global.json」の「error」項目にメッセージを追加しました。
/src/main/webapp/i18n/en/global.json
(中略) "error": { (中略) "emailexists": "E-mail is already in use!", "idexists": "A new {{ entityName }} cannot already have an ID", "article": { "titleexists": "Title already exist!" } (中略)
「error」の中に「article」を作成し、その中に「titleexists」というキー名でメッセージを定義しています。このキーは先のコントローラ内で「article.titleexists」として指定したキーとなります。
まとめ
バリデーションチェックでよくある、サーバ側でのデータ検索 → バリデーション判定 → エラーメッセージの表示、というパターンを実装してみました。Scaffoldで用意されたソースを元に、少ない変更で実装できることが分かりました。