この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
前回は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で用意されたソースを元に、少ない変更で実装できることが分かりました。