エラーメッセージを表示する、エラーメッセージをカスタマイズする。

#SpringBoot：エラーメッセージを表示
 以下のことを実施します。
　　1.エラーメッセージを表示する。
　　2.メッセージの国際化対応
　　3.Webjarsを使用

#依存関係は以下の通り
　　・Spring Boot Dev Tools
　　・Lombok
　　・検証
　　・Thymeleaf
　　・Spring Web
#モデルの作成

　@NotBlankや@Sizeはバリデーション用のアノテーション。
　これらを使用することでエラーチェックを簡単に実装できる


```
package com.example.demo;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter


public class Inquiry {

	@NotBlank
	@Size(max=60)

	private String name;
	@NotBlank
	@Email
	@Size(max = 254)
	private String email;

	@NotBlank
	@Size(max=500)
	private String inquiry;
}
```


#コントローラを作成
　
　@Validated
　　入力値のチェックを行う
　　チェックの結果は、BindingResultに入るので
　　result.hasErrors()でエラーがあるか確認できる

```
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Controller

public class HomeController {

	@GetMapping("/")
	public String index(@ModelAttribute Inquiry inquiry) {
		return"index";
	}
	@PostMapping("/")
	public String confirm(@Validated@ModelAttribute Inquiry inquiry, BindingResult result) {
		if(result.hasErrors()) {
			return"index";
		}
		return"confirm";
	}

}
```

#Bootstrapを追加
**・Bootstrapとは**
　　BootstrapはCSSやjavaScriptから構成されるフレームワーク
　　きれいな画面がつくれることやPCやスマートフォンなどに自動対応する画面
　　が作れる。
　
**・pom.xmlを編集**
　dependenciesタグ内に以下の2つを追加

```
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>4.5.0</version>
		</dependency>
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>webjars-locator</artifactId>
			<version>0.40</version>
		</dependency>
```

#Thymeleafを作成
　index.htmlを作成し以下のソースを記載

```
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet"th:href="@{/webjars/bootstrap/css/bootstrap.min.css}">
<title>Title</title>
</head>
	<body class="bg-light">
		<div class="contatiner">
			<div class="row justify-content-md-center">
				<div class="col-md-8">
					<h4 class="border-bottom my-3" th:text="#{inquiry}"></h4>
					<form th:action="@{/}" th:object="${inquiry}"method="post" novalidate>
						<div class="form-group">
							<label for = "name" th:text="#{name}"></label>
							<input type="text" class ="form-control" th:errorclass="is-invalid" th:field="*{name}">
							<div class="invalid-feedback" th:errors="*{name}"></div>
						</div>
						<div class="form-group">
							<label for="email" th:text="#{email}"></label>
							<input type="email" class="form-control" th:errorclass="is-invalid" th:field="*{email}">
							<div class="invalid-feedback" th:errors="*{email}"></div>
						</div>
						<div class="form-group">
							<label for="inquiry" th:text="#{inquiry}"></label>
							<textarea class="form-control" rows="3" th:errorclass="is-invalid" th:field="*{inquiry}"></textarea>
							<div class="invalid-feedback" th:errors="*{inquiry}"></div>
						</div>
						<button class="btn btn-primary btn-lg btn-block my-4" type="submit" th:text="#{register}"></button>
					</form>
				</div>
			</div>
		</div>
		<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
		<script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script>
		<script th:sec="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
	</body>
</html>
```

登録完了画面を作成

```
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" th:href="@{/webjar/bootstrap/css/bootstrap.min.css}">
<title>title</title>
</head>
<body class="bg-light">
	<div class="container">
		<div class="row justify-content-md-center">
			<div class="col-md-8">
				<h4 class="border-bottom my-3" th:text="#{inquiry}"></h4>
				<p class="text-danger" th:text="#{confirmationMessage}"></p>
				<div th:object="${inquiry}">
					<div class="form-group">
						<label for="password" th:text="#{name}"></label>
						<input type="text" class="form-control"th:field="*{name}" disabled>
					</div>
					<div class="form-group">
						<label for="email" th:text="#{email}"></label>
						<input type="email" class="form-control" th:field="*{email}"disabled>
					</div>
					<div class="form-group">
						<label for="inquiry" th:text="#{inquiry}"></label>
						<textarea class="form-control" rows="3" th:field="*{inquiry}"disabled></textarea>
					</div>
				</div>
			</div>
		</div>
	</div>
	<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
	<script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script>
	<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
</body>
</html>
```

#メッセージの国際化対応
　messages_ja.prpertiesとmessages.propertiesを作成し以下のように編集する
　
　・messages.ja.properties
　　inquiry=お問い合わせ
　　name=お名前
　　email=Email
　　register=登録
　　confirmationMessage=以下の内容で登録が完了しました。
　・messages.properties
　　inquiry=Inquiry
　　name=Name
　　email=Email
　　register=Register
　　confimationMessage=Registration has been completed with the following

#確認

ブラウザでhttp://localhost:8080/を開き文字を入力後登録ボタンを押下
![課題14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/3687bd90-9e84-e6b9-099a-9a0482cf7c4f.png)

その後登録画面が表示されるか確認
![課題15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/77027b8d-99bb-904c-d394-d43d450edaaf.png)

また、空欄の状態で登録ボタンを押下しエラーメッセージが表示されるか確認
![課題13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/e4dda445-3e37-8699-228f-a55462c08ae5.png)


#エラーメッセージをカスタマイズする
　以下のことを実施します。
　・エラーメッセージをカスタマイズする
　・国際化メッセージを設定する

#依存関係
　・Spring Boot Dev Tools
　・Lombok
　・検証
　・Thymeleaf
　・Spring Web

#モデルの作成
　
　@NumberFomat(@pattern="#,###")
　　指定パターンの文字列を数値に型変換します。

　@DateTimeFormat(iso = ISO.DATE)
　　ISOパターンの文字列を日付に型変換します。

```
package com.example.demo.model;

import java.math.BigDecimal;
import java.time.LocalDate;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.annotation.NumberFormat;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Invoice {

	@NotBlank
	@Size(max=60)
	private String address;
	
	@NotBlank
	@Pattern(regexp ="[0-9-]*")
	private String phoneNumber;
	
	@NotNull
	@Min(1000)
	@NumberFormat(pattern="#,###")
	private BigDecimal price;
	
	@NotNull
	@DateTimeFormat(iso=ISO.DATE)
	private LocalDate paymentDeadline;

}
```

#コントローラ作成
　
```
package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.example.demo.model.Invoice;

@Controller
public class HomeController {

	@GetMapping("/")
	public String index(@ModelAttribute Invoice invoice) {
		return"index";
	}
	
	@PostMapping("/")
	public String confirm(@Validated @ModelAttribute Invoice invoice,BindingResult result) {
		if(result.hasErrors()) {
			return"index";
		}
		return"confirm";
	}
	
	
}
```

#Bootstrapを追加
　pom.xmlを開き以下を追加

```
<dependency>
		<groupId>org.webjars</groupId>
		<artifactId>bootstrap</artifactId>
		<version>4.5.0</version>
		</dependency>
		<dependency>
		<groupId>org.webjars</groupId>
		<artifactId>webjars-locator</artifactId>
		<version>0.40</version>
</dependency>

```

#Thymeleafを作成

```
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" th:href="@{/webjars/bootstrap/css/bootstrap.min.css}">
<title>title</title>
</head>
<body class="bg-light">
 <div class="contatiner">
 	<div class="row justify-content-md-center">
 		<div class="col-md-8">
 			<h4 class="border-bottom my-3" th:text="#{invoice}"></h4>
 			<form th:action="@{/}" th:object="${invoice}" method="post" novalidate>
 				<div class="form-group">
 					<label for="name" th:text="#{name}"></label>
 					<input type="text" class="form-control" th:errorclass="is-invalid" th:field="*{name}">
 					<div class="invalid-feedback" th:errors="*{name}"></div>
 					</div>
 				<div class="form-group">
 					<label for="address" th:text="#{address}"></label>
 					<input type="text" class="form-control"th:errorclass="is-invalid"th:field="*{address}">
 					<div class="invalid-feedback"th:errors="*{address}"></div>
 				</div>
 				<div class="form-group">
 					<label for="phone"th:text="#{phoneNumber}"></label>
 					<input type="tel"class="form-control"th:errorclass="is-invalid"th:field="*{phoneNumber}">
 					<div class="invalid-feedback"th:errors="*{phoneNumber}"></div>
 				</div>
 				<div class="form-group">
 					<label for="price" th:text="#{price}"></label>
 					<input type="text" class="form-control" th:errorclass="is-invalid"th:field="*{price}">
 					<div class="invalid-feedback"th:errors="*{price}"></div>
 				</div>
 				<div class="form-group">
 					<label for="paymentDeadline" th:text="#{paymentDeadline}"></label>
 					<input type="date"class="form-control" th:errorclass="is-invalid" th:field="*{paymentDeadline}">
 					<div class="invalid-feedback"th:errors="*{paymentDeadline}"></div>
 				</div>
 				<button class="btn btn-primary btn-lg btn-block my-4" type="submit" th:text="#{register}"></button>
 			</form>
 		</div>"
 	</div>
 </div>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script>
<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
</body>
</html>
```

登録完了画面作成

```
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet"th:href="@{/webjars/bootstrap/css/bootstrap.min.css}">
<title>title</title>
</head>
<body class="bg-light">
	<div class="container">
		<div class="row justify-content-md-center">
			<div class="col-md-8 order-md-1">
				<h4 class="border-bottom my-3"th:text="#{invoice}"></h4>
				<p class="text-danger"th:text="#{confirmationMessage}"></p>
				<div th:object="${invoice}">
					<div class="form-group">
						<label for="name"th:text="#{name}"></label>
						<input type="text"class="form-control"th:field="*{name}" disabled>
					</div>
					<div class="form-group">
						<label for="address"th:text="#{address}"></label>
						<input type="text" class="form-control"th:field="*{address}"disabled>	
					</div>
					<div class="form-group">
						<label for="phoneNumber"th:text="#{phoneNumber}"></label>
						<input type="tel" class="form-control"th:field="*{phoneNumber}"disabled>
					</div>
					<div class="form-group">
						<label for="price"th:text="#{price}"></label>
						<input type="text" class="form-control"th:field="*{price}" disabled>
					</div>
					<div class="form-group">
						<label for="paymentDeadline"th:text="#{paymentDeadline}"></label>
						<input type="date" class="form-control"th:field="*{paymentDeadline}"disabled>
					</div>
				</div>
			</div>
		</div>
	</div>
	<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
	<script th:src="@{/webjars/popper.js/umd/popper.min.js}"></script>
	<script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
</body>
</html>
```

#メッセージコンフィグ作成

　@configuration
　　設定クラスであることを示す
　@bean
　　Springに管理されるBeanの生成を示す。

```
package com.example.demo.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class MessageConfig {

	@Bean
	public MessageSource messageSource() {
		var source= new ReloadableResourceBundleMessageSource();
		source.setBasenames("classpath:i18n/messages","classpath:i18n/ValidationMessages");
		source.setDefaultEncoding("UTF-8");
		source.setFallbackToSystemLocale(false);
		return source;
	}
	@Bean
	public LocalValidatorFactoryBean getValidator() {
		var bean = new LocalValidatorFactoryBean();
		bean.setValidationMessageSource(messageSource());
		return bean;
	}
}

```

#メッセージを追加
以下のファイルを作成後編集
　・messages_jp.properties

```
invoice=請求書
name=お客様名
address =住所
phoneNumber=電話番号
price = 金額
paymentDeadline =支払期日
register =登録
confirmationMessage =登録が正常に完了しました。
```

　・messages.properties

```
invoice = Invoice
name = Name
address = Address
phoneNumber = Phone number
price = Price
paymentDeadline = Payment deadline register = Register
confirmationMessage = Registration has been successfully completed
```

　・ValidationMessages_ja.properrties

```
#個別メッセージ
Pattern.invoice.phoneNumber = {0}は、半角の数字かハイフンで入力してください(例：03-1234-5678)
min.invoice.price={0}は{1}円以上の値を入力してください

#共通メッセージ
NotBlank = {0}を入力してください
NotNull　=　{0}を入力してください
Size = {0}は{2}文字以上、{1}文字以下で入力してください。
min ={0}は{1}以上の値を入力してください。

#typeMismatch:個別メッセージ
typemismatch.invoice.price = {0}が不正な値です。
typeMismatch.invoice.paymentDealine={0}は"2020-01-01"形式で入力してください。
```


　・ValidationMessages.properties

```

#Individual messages
Pattern.invoice.phoneNumber ={0} must bea half-width numver or hyphen (e.g.03-1234-5678)
Min.invoice.price = {0} must be greater than or equal to {1} JPY
#Common messages
NotBlank = {0} is required
NotNull = {0} is required
Size = {0} must be between {2} and {1} characters
Min = {0} must be greater than or equal to {1}

#typeMismatch: Individual messages
typeMismatch.invoice.price = {0} is incorrect
typeMismatch.invoice.paymentDeadline = {0} must be in "2020-01-01" format
```


#確認

登録画面が開くか確認
![課題16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/3b27f25c-ce4f-0bb1-6635-093ac28f02e3.png)

空白で登録ボタン押下でエラーメッセージ表示
![課題19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/5cb9d6b6-70d5-5318-e46e-d340c17234a2.png)

登録ボタン押下後登録できているか確認
![課題17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/4d140615-32de-91ec-173b-412b437dc248.png)

![課題18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686519/41efb31f-99e2-f6e0-d755-21a725c54e83.png)

#以上