質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アノテーション

アノテーションとは、特定のコードに対して、メタデータを注釈として付与することを指します。また、付与したメタデータ自体をアノテーションと呼ぶ場合もあります。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

3回答

10804閲覧

No message found under code 'male' for locale 'ja' を解決したいです。

Mason

総合スコア14

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アノテーション

アノテーションとは、特定のコードに対して、メタデータを注釈として付与することを指します。また、付与したメタデータ自体をアノテーションと呼ぶ場合もあります。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2023/01/07 10:20

編集2023/01/08 03:35

前提

「Spring 解体新書」という書籍で学習しています。
メッセージを解決できない例外でエラーが出ています。
ソースコードに問題はなさそうです。
getMessageでmessages.propertiesの値を取れるはずですがどこに問題があるかが不明です。

実現したいこと

ユーザー登録画面を表示できるようにしたいです。

発生している問題・エラーメッセージ

There was an unexpected error (type=Internal Server Error, status=500). No message found under code 'male' for locale 'ja'. org.springframework.context.NoSuchMessageException: No message found under code 'male' for locale 'ja'. at org.springframework.context.support.DelegatingMessageSource.getMessage(DelegatingMessageSource.java:76) at com.example.application.service.UserApplicationService.getGenderMap(UserApplicationService.java:20) at com.example.controller.SignupController.getSignup(SignupController.java:44) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)

該当のソースコード

java

1package com.example.application.service; 2 3import java.util.LinkedHashMap; 4import java.util.Locale; 5import java.util.Map; 6 7import org.springframework.beans.factory.annotation.Autowired; 8import org.springframework.context.MessageSource; 9import org.springframework.stereotype.Service; 10 11@Service 12public class UserApplicationService { 13 14 @Autowired 15 private MessageSource messageSource; 16 17// 性別のMAPを生成する 18 public Map<String,Integer>getGenderMap(Locale locale){ 19 Map<String,Integer>genderMap = new LinkedHashMap<>(); 20 String male = messageSource.getMessage("male",null,locale); 21 String female = messageSource.getMessage("female", null,locale); 22 genderMap.put(male, 1); 23 genderMap.put(female, 2); 24 return genderMap; 25 } 26} 27

java

1package com.example.controller; 2 3import java.util.Locale; 4import java.util.Map; 5 6import org.modelmapper.ModelMapper; 7import org.springframework.beans.factory.annotation.Autowired; 8import org.springframework.stereotype.Controller; 9import org.springframework.ui.Model; 10import org.springframework.validation.BindingResult; 11import org.springframework.validation.annotation.Validated; 12import org.springframework.web.bind.annotation.GetMapping; 13import org.springframework.web.bind.annotation.ModelAttribute; 14import org.springframework.web.bind.annotation.PostMapping; 15import org.springframework.web.bind.annotation.RequestMapping; 16 17import com.example.application.service.UserApplicationService; 18import com.example.domain.user.model.MUser; 19import com.example.domain.user.service.UserService; 20import com.example.form.GroupOrder; 21import com.example.form.SignupForm; 22 23import lombok.extern.slf4j.Slf4j; 24 25@Controller 26@RequestMapping("/user") 27@Slf4j 28public class SignupController { 29 30 @Autowired 31 private UserApplicationService userApplicationService; 32 33 @Autowired 34 private UserService userService; 35 36 @Autowired 37 private ModelMapper modelMapper; 38 39// ユーザー登録画面を表示 40 @GetMapping("/signup") 41 public String getSignup(Model model, Locale locale, @ModelAttribute SignupForm form) { 42 43 //性別を取得 44 Map<String,Integer> genderMap = userApplicationService.getGenderMap(locale); 45 model.addAttribute("genderMap", genderMap); 46 47 //ユーザー登録画面に遷移 48 return "user/signup"; 49 } 50 51 //ユーザー登録処理 52 @PostMapping("/signup") 53 public String postSignup(Model model, Locale locale, @ModelAttribute @Validated(GroupOrder.class) SignupForm form, BindingResult bindingResult) { 54 55 //入力チェック結果 56 if(bindingResult.hasErrors()) { 57 //NG:ユーザー登録画面に戻ります。 58 return getSignup(model, locale, form); 59 } 60 61 log.info(form.toString()); 62 63 //formをMUserクラスに変更 64 MUser user = modelMapper.map(form, MUser.class); 65 66 //ユーザー登録 67 userService.signup(user); 68 69 //ログイン画面にリダイレクト 70 return "redirect:/login"; 71 } 72}

java

1package com.example.form; 2 3import java.util.Date; 4 5import javax.validation.constraints.Email; 6import javax.validation.constraints.Max; 7import javax.validation.constraints.Min; 8import javax.validation.constraints.NotBlank; 9import javax.validation.constraints.NotNull; 10import javax.validation.constraints.Pattern; 11 12import org.hibernate.validator.constraints.Length; 13import org.springframework.format.annotation.DateTimeFormat; 14 15import lombok.Data; 16 17@Data 18public class SignupForm{ 19 20 @NotBlank(groups = ValidGroup1.class) 21 @Email(groups = ValidGroup2.class) 22 private String userId; 23 24 @NotBlank(groups = ValidGroup1.class) 25 @Length(min = 4, max = 100, groups = ValidGroup2.class) 26 @Pattern(regexp = "^[a-zA-Z0-9]+$", groups = ValidGroup2.class) 27 private String password; 28 29 @NotBlank(groups = ValidGroup1.class) 30 private String userName; 31 32 @DateTimeFormat(pattern = "yyyy/MM/dd") 33 @NotNull(groups = ValidGroup1.class) 34 private Date birthday; 35 36 @Min(value = 20, groups = ValidGroup2.class) 37 @Max(value = 100, groups = ValidGroup2.class) 38 private Integer age; 39 40 @NotNull(groups = ValidGroup1.class) 41 private Integer gender; 42}

messages.properties

1user.signup.title=ユーザー登録 2user.signup.btn=ユーザー登録 3userId=ユーザーID 4password=パスワード 5userName=ユーザー名 6birthday=誕生日 7age=年齢 8male=男性 9female=女性 10gender=性別

試したこと

下記の確認

  • ソースコード差分
  • getMessageメソッドの使用方法
  • propertiesファイルのファイル名

補足情報(FW/ツールのバージョンなど)

Spring Boot 2.4.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2023/01/07 11:07

> messaegs.properties このファイル名なんでしょうか?
Mason

2023/01/07 12:41

getMessageでキーにした値をこのファイルにある値でとってくるためのファイルです。 ファイル名間違えていたので修正しました。
jimbe

2023/01/07 16:36

単に質問への書き間違いということで良いでしょうか。 他に気になるのは、例外のメッセージは "age" が無いと言っているのに、行番号の該当コードは "male" を得ようとしていることです。ご提示のコードは例外が発生したコードそのままでしょうか。 また、messages.properties は示されていますが messages_ja.properties の有無は言及されていません。もしあれば当然優先されると思いますが、如何でしょう。
guest

回答3

0

application.properties

に次の行を登録したら,なぜかうまくいきました。理由は全くわかりません。

user.signup.title=ユーザ登録

投稿2023/04/23 07:26

dfighsaldighal

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

回答

前提

WebでもアプリでもSpringでも何でも国際化やローカライズはある程度以上の規模になると必要です。何か文字列を表示させる場合に、ハードコードしてしまうとそれができなくなってしまうので、ほとんどのシステムではそれらを意識した設計が可能になっています。Javaでは言語(標準ライブラリ)でそれらの仕組みを昔から持っており、ResourceBundleというものが使用されてきました。Springのorg.springframework.context.MessageSourceもその辺のクラスに該当します。

原因

今回クライアント側は/signupを日本語(ja)最優先でGETしてきたので、MessageSourceを使ってLocale.JAPANESEでメッセージを取得しようとします。しかし、リソースにmessages_ja.propertiesファイルがないので、例外が発生しているのではないかと思います。

対策

messages_ja.propertiesmessages.propertiesと同じディレクトリに同じ内容で作成すると動作が変わると思います。

ドキュメントについては↓の辺が該当しますが、あまり明快ではありません。
https://docs.spring.io/spring-boot/docs/2.4.1/reference/html/spring-boot-features.html#boot-features-internationalization

おまけ

確認用に用意したコードを置いておきます。

環境

String Boot 2.7.7
Java 11

ソースディレクトリ構造

text

1├── main 2│   ├── java 3│   │   └── com 4│   │   └── example 5│   │   └── demo 6│   │   └── MessageTestApplication.java 7│   └── resources 8│   ├── application.properties 9│   ├── messages.properties 10│   ├── messages_en.properties 11│   └── messages_ja.properties 12└── test 13 └── java 14 └── com 15 └── example 16 └── demo 17 └── MessageTestApplicationTests.java

ファイルの内容

※テストは未作成

MessageTestApplication.java

Java

1package com.example.demo; 2import java.util.HashMap; 3import java.util.Locale; 4import java.util.Map; 5import org.springframework.beans.factory.annotation.Autowired; 6import org.springframework.boot.SpringApplication; 7import org.springframework.boot.autoconfigure.SpringBootApplication; 8import org.springframework.context.MessageSource; 9import org.springframework.web.bind.annotation.GetMapping; 10import org.springframework.web.bind.annotation.RestController; 11@SpringBootApplication 12@RestController 13public class MessageTestApplication { 14 @Autowired 15 MessageSource messageSource; 16 @GetMapping ("/") 17 public Map<String, String> home() { 18 var map = new HashMap<String, String>(); 19 Locale[] locales = new Locale[] {Locale.JAPANESE, Locale.ENGLISH, Locale.CHINESE}; 20 for (var locale: locales) { 21 map.put(locale.getDisplayName(), messageSource.getMessage("hello", null, locale)); 22 } 23 return map; 24 } 25 public static void main(String[] args) { 26 SpringApplication.run(MessageTestApplication.class, args); 27 } 28}

application.properties

properties

1spring.messages.basename=messages 2spring.messages.encoding=UTF-8

messages.properties

properties

1hello=hellodefault

messages_en.properties

properties

1hello=hello

messages_ja.properties

properties

1hello=こんにちは

実行結果

sh

1$ wget -q -O - 'http://localhost:8080/';echo 2{"English":"hello","Chinese":"hello","Japanese":"こんにちは"} 3$

最後に

最初は大変だと思いますが、いきなりsignupを含んだコードで質問せず、現象を起こすために最小限の確認用コード一式を作成してから質問してください。

投稿2023/01/07 18:57

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Mason

2023/01/08 03:46

原因の内容を理解しました。優先順位がある中で、必要なファイルがなくてエラーになってるのでは?とのことですね。 ご指摘いただいたとおり、修正してみましたが再度同じエラーになります。 エラーメッセージが「No message found under code 'male' for locale 'ja_JP'.」となったくらいです。 しかし、書籍と同じバージョンで同じように進めていく中で他に原因はありますでしょうか? messages_ja.propertiesファイルも書籍には記載がありませんでした。
退会済みユーザー

退会済みユーザー

2023/01/08 04:29 編集

書籍は持っていません。何か内容に文句があるなら出版社か著者に直接問い合わせてください。 それよりも原因の内容を理解したのであれば、あとはもう自分で調べられると思いますよ。 「再度同じエラーになる」とか、理解してないとしか思えません。 Springは(他もそうだけど)それほど丁寧なマニュアルがないので、手探りや書籍・解説記事を参考にしたソース解析が必要な所謂オープンソースなソフトです。これだけ情報があるのに自分で調べられないなら、素直に諦めてもいいかもしれません。 解説記事としてはこの辺でしょうか・・・ https://reflectoring.io/spring-boot-internationalization/ https://www.javatpoint.com/restful-web-services-internationalization ご参考までに。
guest

0

https://start.spring.io/#!type=gradle-project-kotlin&language=kotlin&platformVersion=2.7.7&packaging=jar&jvmVersion=11&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo

補足情報(FW/ツールのバージョンなど)
Spring Boot 2.4.1

diff

1- id("org.springframework.boot") version "2.7.7" 2+ id("org.springframework.boot") version "2.4.1"
$ tree . ├── src │ ├── main │ │ ├── kotlin │ │ └── resources │ │ ├── messages.properties ... あなたのものをコピペ │ └── test │ ├── java │ │ └── com │ │ └── example │ │ └── demo │ │ └── MsgTest.java

java

1package com.example.demo; 2 3import org.junit.jupiter.api.Test; 4import org.springframework.beans.factory.annotation.Autowired; 5import org.springframework.boot.test.context.SpringBootTest; 6import org.springframework.context.MessageSource; 7import java.util.Locale; 8 9@SpringBootTest 10public class MsgTest { 11 12 @Autowired 13 private MessageSource _messageSource; 14 15 @Test 16 public void hogege() throws Exception { 17 System.out.println("xxx : " + this); 18 System.out.println("_messageSource : " + _messageSource); 19 20 { 21 String msg = _messageSource.getMessage("age", new Object[]{}, Locale.getDefault()); 22 System.out.println("msg : " + msg); 23 } 24 25 { 26 String msg = _messageSource.getMessage("age", new Object[]{}, Locale.JAPAN); 27 System.out.println("msg : " + msg); 28 } 29 30 { 31 String msg = _messageSource.getMessage("age", new Object[]{}, new Locale("ja")); 32 System.out.println("msg : " + msg); 33 } 34 35 { 36 String msg = _messageSource.getMessage("age", null, new Locale("ja")); 37 System.out.println("msg : " + msg); 38 } 39 } 40}

結果。別に問題なさげ。

_messageSource : org.springframework.context.support.ResourceBundleMessageSource: basenames=[messages] msg : 年齢 msg : 年齢 msg : 年齢 msg : 年齢

投稿2023/01/07 14:01

shiketa

総合スコア4041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問