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

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

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

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

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Spring Boot

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

Q&A

解決済

1回答

1283閲覧

docker + Spring BootでAPIを作成する際のエラーについて

jabberwocky3376

総合スコア14

Java

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

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Spring Boot

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

0グッド

0クリップ

投稿2020/05/28 02:18

編集2020/05/28 03:00

やりたいこと

  • docker + spring boot で、簡単なCRUDのrestAPIを作成したいと考えています

問題

  • curlコマンドでPOSTすると、リクエストパラメータをいれているにも関わらず、nullエラーのようなものが返ってきます

具体的なエラー部分

  • アプリを実行後、ターミナルでcurl -X POST -H "Content-Type: application/json" -d '{"name":"aaa", "message":"bbb"}' localhost:8080/tweet としたところ、Internal Server Errorが返ってきました。
  • アプリのデバッグログには以下のようなログが出てきました
// 返ってきたエラー 2020-05-28 10:55:59.693 DEBUG 8975 --- [nio-8080-exec-6] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update 2020-05-28 10:55:59.696 DEBUG 8975 --- [nio-8080-exec-6] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=? 2020-05-28 10:55:59.704 DEBUG 8975 --- [nio-8080-exec-6] org.hibernate.SQL : insert into tweet (message, name, id) values (?, ?, ?) 2020-05-28 10:55:59.707 WARN 8975 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000 2020-05-28 10:55:59.707 ERROR 8975 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'message' cannot be null 2020-05-28 10:55:59.712 ERROR 8975 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause java.sql.SQLIntegrityConstraintViolationException: Column 'message' cannot be null ~~~

やったこと

  • 下記のServiceクラスのコードを書き換えて、idだけにしたり、nullable = trueにして試したりしましたが、エラーは治りませんでした
  • dockerとの接続がうまく行っていないのかと思いましたが、urlは問題なさそうなのでそこでエラーは発生しない
  • 手動でmySQLにtweetテーブルを作成し、id,name,messageの値もいれてPOSTしてみたけど、エラー変わらず
  • 手動で値をいれた状態でGETしたところ、データが入っているにも関わらず[{}]と空のレスポンスが返ってきた
  • その際のデバッグログのSQL文を直接DBで叩いたら、正常にデータが取得できた
// 0_などはhibernateが出力するエイリアスらしいので、それを削除してDBに接続して以下を実行したら、正常に値が帰ってきた select tweet0_.id as id1_0_, tweet0_.message as message2_0_, tweet0_.name as name3_0_ from tweet tweet0_
  • POST時に値をいれてリクエストしているのに、nullだと認識されてしまっているのが原因かと考えているのですが、有効な対処が見つからず難儀しています、、、

コード

dockerイメージ

yml

1// docker-compose.yml 2 3version: "3" 4services: 5 database: 6 image: mysql:5.7 7 command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 8 environment: 9 MYSQL_ROOT_PASSWORD: hoge 10 MYSQL_DATABASE: testdb 11 volumes: 12 - /tmp/test_mysql:/var/lib/mysql 13 ports: 14 - 3306:3306

Spring Bootのapplication.yml

spring: datasource: sqlScriptEncoding: UTF-8 driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/testdb?useSSL=false&requireSSL=false username: root password: hoge # アプリケーション起動時にデータベースを初期化しないようにする jpa: hibernate: ddl-auto: update # spring boot起動時にDBにテーブル作成できない問題の対応 properties: hibernate: dialect: org.hibernate.dialect.MySQL57Dialect logging: level: sql: debug

Spring Bootコード

java

1// Tweet.java 2// Entityクラス 3 4@Entity 5@Data 6@NoArgsConstructor 7@AllArgsConstructor 8@Table(name = "tweet") 9public class Tweet { 10 11 @Id 12 @GeneratedValue 13 @Column 14 private int id; 15 16 @Column(nullable = false) 17 private String name; 18 19 @Column(nullable = false) 20 private String message; 21 22}

java

1// TweetRepository.java 2// Repositoryクラス 3 4@public interface TweetRepository extends JpaRepository<Tweet,Integer>{}

java

1// TweetService.java 2// Serviceクラス 3 4@Service 5@Transactional 6public class TweetService { 7 @Autowired 8 TweetRepository tweetRepository; 9 10 public Tweet postTweet(Tweet tweet){ 11 return tweetRepository.save(tweet); 12 } 13 14 public List<Tweet> getTweet(){ 15 return tweetRepository.findAll(); 16 } 17}

java

1// TweetController.java 2// コントローラー 3 4@RestController 5@RequestMapping("tweet") 6public class TweetController { 7 @Autowired 8 TweetService tweetService; 9 10 @RequestMapping(method = RequestMethod.POST) 11 Tweet postTweet(@RequestBody Tweet tweet) { 12 return tweetService.postTweet(tweet); 13 } 14 15 @RequestMapping(method = RequestMethod.GET) 16 List<Tweet> getTweet() { 17 return tweetService.getTweet(); 18 } 19}

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

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

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

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

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

rubytomato

2020/05/28 08:39

以下の点についてご確認頂き、結果を質問内容に追記してください。 1) MySQLを立ち上げない状態でSpring Bootのアプリケーションを起動したときに、正常に起動できるか?(データベース接続エラーが起きるかどうか) 2) postTweetメソッドで受け取るTweetクラスの引数の値をSystem.out.println等で出力したときに、どのようなデータがセットされているか?
jabberwocky3376

2020/05/29 02:40

rubytomato様 ありがとうございます。 > 1) MySQLを立ち上げない状態でSpring Bootのアプリケーションを起動したときに、正常に起動できるか?(データベース接続エラーが起きるかどうか) docker stop で環境を停止した状態で アプリを実行したところ、 起動に失敗しました。 いくつかエラーが出ましたが、主に以下の部分が原因のようです ``` ~~~ 2020-05-29 11:09:09.666 ERROR 35626 --- [ task-1] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization. com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. ~~~ ``` ``` ~~~ 2020-05-29 11:09:11.331 WARN 35626 --- [ task-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08S01 2020-05-29 11:09:11.332 ERROR 35626 --- [ task-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. ~~~ ``` > 2) postTweetメソッドで受け取るTweetクラスの引数の値をSystem.out.println等で出力したときに、どのようなデータがセットされているか? `System.out.println(tweet);` とすると、 `com.example.demo.Tweet@591cece5` の値が出力されました。
jabberwocky3376

2020/05/29 02:42

rubytomato様 すいません、2) テストで引数のtweetの中身を取りたかったので、 Tweet.javaクラスの定数を全てpublicにしてcurlコマンドを叩いたところ、 正常にPOSTが実行されました。 問題は、単純にprivateな定数に他クラスからアクセスできなかった為、 nullとしてPOSTされてしまっており、エラーが発生したものと思われます。 ご助言のおかげで助かりました。 ありがとうございました。
jabberwocky3376

2020/05/29 03:01 編集

rubytomato様 なんどもすいません、よくよく考えたら、Entityの値がprivateだからアクセスできずエラーが返ってきているのは少しおかしい気がしています 普通APIのEntityはprivateにして永続化するものだと思うのですが、、、 なので、Entityを全てprivateに戻して、 Tweet.javaのTweetクラス内にコンストラクタを追加しました ``` public Tweet(int id,String name, String message) { this.id = id; this.name = name; this.message = message; } ``` この状態でcurlコマンドを叩いたところ、正常に値がDBに保存されていた為、問題ないか、、とは思うのですが、 curlコマンドを叩いた他とのターミナルで返ってくる返り値が `{}` と空の状態になってしまいます、、
rubytomato

2020/05/29 03:05

Lombokを使われていると思いますが、それが反映されていないように思います。 クラスに@Dataアノテーションを付けているのに > `System.out.println(tweet);` とすると、 > `com.example.demo.Tweet@591cece5` の値が出力されました。 というような出力がされる点がそうです。通常はtoStringメソッドがLombokによって自動的に生成されます。 EclipseであればLombokのプラグインとアノテーションプロセッサーを有効にする必要があったと思います。
jabberwocky3376

2020/05/29 04:29

rubytomato様 > Lombokを使われていると思いますが、それが反映されていないように思います。 おっしゃる通りでした。 VSCodeでSTSの拡張を入れてSpring BootでAPIを作っていましたが、 Spring Bootによるlombokの依存関係だけだと正しく反映されないようです。 https://qiita.com/asukahime1021/items/1a7b5c1843168df27333 lombok単体の拡張を追加したところ、当初のコードで正常に動作致しました。 ありがとうございました!
guest

回答1

0

自己解決

Tweet.javaクラスの定数が全てprivateの為、controllerからentityにアクセスできず、
したがって値が全てnullで登録されていたことが原因と思われる

投稿2020/05/29 02:44

jabberwocky3376

総合スコア14

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問