Dockerを使用したVSCode,SpringBoot,Mybatis,Gradle,MySQL,Vue.jsを使用した開発環境の構築

# 初めに
　本記事は、Dockerを勉強中(2週間ほど)の投稿者のメモとして使用する記事のため、正しい情報とは限りません。ご注意ください。


https://github.com/Chestnut-TH/Docker_Spring_Vue_MySQL.git

>本記事は、以下を参考にしております。
[Spring boot + Vue.js + MySql + VS Code + Docker で開発環境を構築する](https://qiita.com/PoKoPoKoTa2ry/items/2f9b54518b8158809192)
上記URLです
https://qiita.com/PoKoPoKoTa2ry/items/2f9b54518b8158809192
# 今回目指すもの
タイトルの通りDocker、VSCode,SpringBoot,Mybatis,Gradle,MySQL,Vue.jsを連携した簡易アプリ(検索ボタンを押すとDBのデータが表に反映される)の作成を目指す。また、Bootstrap5(見た目)やVue-Router(ルーティング)、axios(FEとBE間の通信)等も使用します。

# 前提事項
DockerやVSCodeのインストール、VSCodeの拡張機能(Spring Initializrとかlombokなど)がある程度インストールされていること

# 使用環境について
本記事で、タイトルの通りDocker、VSCode、SpringBoot、Mybatis、Gradle、MySQL、Vue.jsを使用した開発環境となります。以下は使用環境のバージョンになります。
OSは、Macを使用しております。
```:MacのOS
macOS Montery 12.3.1
```
```:Dockerのバージョン
Client:
 Cloud integration: v1.0.22
 Version:           20.10.11
 API version:       1.41
 Go version:        go1.16.10
 Git commit:        dea9396
 Built:             Thu Nov 18 00:36:09 2021
 OS/Arch:           darwin/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.11
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.9
  Git commit:       847da18
  Built:            Thu Nov 18 00:35:39 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.12
  GitCommit:        7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```
```:build.gradle (springbootとMybatisのバージョン)
plugins {
	id 'org.springframework.boot' version '2.6.7'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
	id 'war'
}

group = 'app'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'mysql:mysql-connector-java'
	annotationProcessor 'org.projectlombok:lombok'
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

```
```:Gradleのバージョン
------------------------------------------------------------
Gradle 7.4
------------------------------------------------------------

Build time:   2022-02-08 09:58:38 UTC
Revision:     f0d9291c04b90b59445041eaa75b2ee744162586

Kotlin:       1.5.31
Groovy:       3.0.9
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          16.0.1 (Oracle Corporation 16.0.1+9-24)
OS:           Mac OS X 11.3 x86_64
```
```:Javaのバージョン
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)
```
```:MySQLのバージョン
mysql  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)
```
```:Vueのバージョン
app@0.1.0 /usr/src/app
+-- @vue/cli-plugin-babel@5.0.4
| `-- @vue/babel-preset-app@5.0.4
|   `-- vue@3.2.33 deduped
+-- bootstrap-vue@2.22.0
| `-- portal-vue@2.1.7
|   `-- vue@2.6.14
+-- vue-router@4.0.13
| `-- vue@3.2.33 deduped
`-- vue@3.2.33
  `-- @vue/server-renderer@3.2.33
    `-- vue@3.2.33 deduped
```

# 手順の大まかな流れ
```:構築フロー
①最低限のフォルダ、ファイル構成の準備  #shを作ったので実行するだけ
②Dockerfileや設定ファイルの作成
③spring_projectの作成 #spring initializrを使用
④コンテナの作成(DockerのBuildを実施）
⑤vue_projectの作成(vue-cliのインストール等の実施)
⑥DBの作成(Tableの作成やデータの挿入)
⑦開発1(Vue.js編)
⑧開発2(Spring編)
⑨動作確認
⑩コンテナの削除
```
次の見出しから手順です。

# 手順１：ファイル・フォルダ構成の確認・準備
初めに準備する最低限のファイル・フォルダの構成です。
任意の場所で作成してください。フォルダ名は任意に設定して問題ないですがこの後に作成するDockerfileの指定するパスが変更されるので注意してください。
```:ファイル・フォルダ構成
「*」はファイルです
「-」はフォルダです

・プロジェクト名(名前は任意)
　　　　　　 -.devcontainer
　　　　　　 　　　　　　 *devcontainer.json　　　　　　　
    -docker
        -mysql
    　　　　　　 　　　　　　 -settings
    　　　　　　 　　　　　　 -sql
                *init.sql
　　　　　　 　　　　　　     *Dockerfile
　　　　　　 　　　　　　     *my.cnf
        -spring
　　　　　　 　　　　　　     *Dockerfile
        -vue
　　　　　　 　　　　　　     *Dockerfile
        *docker-compose.yml
    -spring_project
    -vue_project
        *gitkeep
```
以下のようなシェルを作成し、任意の場所で実行すれば、上記の最低限のフォルダやファイルを作成します。
※spring_projectはSpring Initializrでこの後別途作成するので作りません。
```:init.sh
#!/bin/bash
echo -n "任意のプロジェクト名を入力してください:"

read PROJECTNAME

mkdir $PROJECTNAME

#devcontainer関連を作成
mkdir $PROJECTNAME/.devcontainer

touch $PROJECTNAME/.devcontainer/devcontainer.json

mkdir $PROJECTNAME/docker

#mysql関連を作成
mkdir $PROJECTNAME/docker/mysql

mkdir $PROJECTNAME/docker/mysql/settings

mkdir $PROJECTNAME/docker/mysql/sql

touch $PROJECTNAME/docker/mysql/sql/init.sql

touch $PROJECTNAME/docker/mysql/Dockerfile

touch $PROJECTNAME/docker/mysql/my.cnf

#spring関連を作成
mkdir $PROJECTNAME/docker/spring

touch $PROJECTNAME/docker/spring/Dockerfile

#vue関連を作成
mkdir $PROJECTNAME/docker/vue

touch $PROJECTNAME/docker/vue/Dockerfile

#docker-compose.ymlを作成
touch $PROJECTNAME/docker/docker-compose.yml


#vue_project関連を作成
mkdir $PROJECTNAME/vue_project

touch $PROJECTNAME/vue_project/gitkeep

cd $PROJECTNAME

#VSCodeを起動
code .
```
任意の場所で実行する
```:init.shの実行コマンド
sh ./init.sh
```
プロジェクト名を「Docker_Spring_Vue_MySQL」で作成する

![スクリーンショット 2022-05-08 18.53.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/e330003d-20c2-32ff-1d1f-f1765f04a32d.png)


# 手順2：Dockerfileや設定ファイル等の作成

## (1)docker-compose.ymlの作成
```:.Docker_Spring_Vue_MySQL/docker/docker-compose.yml
version: '3.6'
services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    command: --default-authentication-plugin=mysql_native_password
    build: ./mysql
    environment:
      MYSQL_DATABASE: "testdb"     #DBの名前は任意に設定してください
      MYSQL_ROOT_USER: "root"       #root権限のユーザ名は任意に設定してください
      MYSQL_ROOT_PASSWORD: "root"   #root権限のパスワードは任意に設定してください
      MYSQL_USER: "user"            #作業ユーザ権限のユーザ名は任意に設定してください
      MYSQL_PASSWORD: "user"        #作業ユーザ権限のパスワードは任意に設定してください
      TZ: "Asia/Tokyo"
    ports:
      - 3306:3306
    volumes:
      - ./mysql/sql:/docker-entrypoint-initdb.d # 「:」の左がローカル環境で右がコンテナの環境
      - ./mysql/settings/:/var/lib/mysql        # 「:」の左がローカル環境で右がコンテナの環境
  spring:
    image: openjdk:8
    container_name: spring
    build: ./spring
    depends_on:
      - mysql
    ports:
      - "8080:8080"
    tty: true
    volumes:
      - ../spring_project:/srv:cached          # 「:」の左がローカル環境で右がコンテナの環境
    working_dir: /srv
  vue:
    container_name: vue
    build: ./vue
    ports:
      - 9000:8080
    volumes:
      - ../vue_project:/usr/src/app:cached    # 「:」の左がローカル環境で右がコンテナの環境
    stdin_open: true
    tty: true
volumes:
  mysql_db:
    driver: local
```
## (2)mysqlのDockerfileと設定ファイル等の作成
```:.Docker_Spring_Vue_MySQL/docker/mysql/Dockerfile
FROM mysql

EXPOSE 3306

ADD ./my.cnf /etc/mysql/conf.d/my.cnf

CMD ["mysqld"]
```
```:.Docker_Spring_Vue_MySQL/docker/mysql/my.cnf
[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8
```
テーブルの作成とデータを挿入する任意のSQL文を作成してください
```:.Docker_Spring_Vue_MySQL/docker/mysql/sql/init.sql
CREATE DATABASE IF NOT EXISTS testdb;

CREATE TABLE IF NOT EXISTS user(
    id INTEGER not null,
    name varchar(20) not null,
    PRIMARY KEY (id, name)
);

INSERT INTO user(id, name)VALUES(1, 'Tarou');
```
## (3)springのDockerfileの作成
```:.Docker_Spring_Vue_MySQL/docker/spring/Dockerfile
FROM openjdk:8

VOLUME /tmp
WORKDIR /app
```
## (4)vueのDockerfileの作成
```:.Docker_Spring_Vue_MySQL/docker/vue/Dockerfile
FROM node:14

WORKDIR /usr/src/app/

RUN npm install -g npm && \
    npm install -g @vue/cli
```

# 手順3：spring_projectの作成
Spring Initializrを使用して、spring_projectを作成します。
本手順では、VSCodeの拡張機能を使用しています。
「Spring Boot Extension Pack」をインストールすれば、自動で必要な拡張機能がインストールされるはずです。
![スクリーンショット 2022-05-08 20.45.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/65f15290-37a6-3f5e-6cc1-33b1254656ff.png)
「command + shift + p」を押下し、「Spring Initializr: Create Gradle Project...」を選択
![スクリーンショット 2022-05-08 20.50.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/41c2558c-f142-4c62-5b69-2aefd58a0acd.png)
「バージョン2.6.7」を選択
![スクリーンショット 2022-05-08 20.55.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/75c221b8-2741-27db-58cf-7e854e2a0957.png)
「Java」を選択
![スクリーンショット 2022-05-08 21.00.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/b768e890-7a00-2147-2813-46b49f26e24e.png)
デフォルトのパッケージ名を決めます。
![スクリーンショット 2022-05-08 21.04.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/6906d25b-fc1e-6982-a605-5aa2e3e2c090.png)
何でも良いかと思いますが、今回はシンプルに「app」とします。
![スクリーンショット 2022-05-08 21.07.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/8a4e2f3f-b027-919d-fa33-3687de85e991.png)
プロジェクト名を決めます。
![スクリーンショット 2022-05-08 21.09.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/fe56ed19-d789-7d6e-d63e-587e9314cd52.png)
「spring_project」にします。任意のプロジェクト名にしたい場合は、「docker-compose.yml」の「volumes:」の「spring_project」を任意のプロジェクト名と一致させる必要があるので注意してください。
![スクリーンショット 2022-05-08 21.19.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/07a29a13-dcc0-eafe-a83e-bddbfe8ea41d.png)
今回、デプロイまでは実施しないのでどちらでも構いません。一応「War」で実施します。
![スクリーンショット 2022-05-08 21.23.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/c921908e-687d-20a6-3bdb-035c24422f90.png)
Javaのバージョン8を選択します。変更したい場合は、「docker-compose.yml」と「spring」の「Dockerfile」の修正も必要になります。
![スクリーンショット 2022-05-08 21.24.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/bfba2074-168f-f1e5-b4f1-2dbb6f10584a.png)
依存ライブラリを注入します。
![スクリーンショット 2022-05-08 21.29.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/68a3d88b-499d-436a-df5e-6c4cdae5e10e.png)
いくつ追加していただいても構いませんが、最低限以下のものを追加してください。
```:依存ライブラリ名
Spring Boot Devtools
Lombok
Spring Web
Mybatis Framework
MySQL Driver
```
![スクリーンショット 2022-05-08 21.35.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/9ccf70ac-a8f5-d82a-0f76-a5d9df38961a.png)
「Generate into this folder」を押下
![スクリーンショット 2022-05-08 21.38.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/caa93412-ac06-e78a-5d6b-d853ee43679b.png)
プロジェクトの作成成功すると以下のように「spring_project」が追加されます。
![スクリーンショット 2022-05-08 21.45.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/95edb7f4-fdfc-5cc7-ac07-2ae0a3685491.png)

# 手順4:コンテナの作成
dockerコマンドを実行して、コンテナの作成を行います。
```:実行コマンド
$ cd docker
$ docker-compose build
(以下のようになればOK)
Building mysql
[+] Building 50.4s (7/7) FINISHED
...
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Building spring
[+] Building 70.9s (6/6) FINISHED
...
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Building vue
[+] Building 214.9s (7/7) FINISHED
...
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them 
$ docker-compose up -d
(以下のようになればOK)
Creating network "docker_default" with the default driver
Creating vue   ... done
Creating mysql ... done
Creating spring ... done
```
「docker-compose build」実行時に以下のようなエラーが出た場合は、「code ERR_SOCKET_TIMEOUT」とあるようにタイムアウトなので再度実行を試してみてください。
```:ERRORが出た場合
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Building vue
[+] Building 181.0s (6/6) FINISHED                                                                                         
 => [internal] load build definition from Dockerfile                                                                  0.0s
 => => transferring dockerfile: 36B                                                                                   0.0s
 => [internal] load .dockerignore                                                                                     0.0s
 => => transferring context: 2B                                                                                       0.0s
 => [internal] load metadata for docker.io/library/node:14                                                            2.1s
 => [1/3] FROM docker.io/library/node:14@sha256:2f39686f6d0b2687550659367fa11f56018a0f782b7e30f1a0ea56b11dece124      0.0s
 => CACHED [2/3] WORKDIR /usr/src/app/                                                                                0.0s
 => ERROR [3/3] RUN npm install -g npm &&     npm install -g @vue/cli                                               178.7s
------                                                                                                                     
 > [3/3] RUN npm install -g npm &&     npm install -g @vue/cli:                                                            
#6 32.47 /usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js                                              
#6 32.47 /usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js                                              
#6 32.60 + npm@8.9.0                                                                                                       
#6 32.60 added 63 packages from 18 contributors, removed 299 packages and updated 138 packages in 30.03s                   
#6 178.6 npm ERR! code ERR_SOCKET_TIMEOUT
#6 178.6 npm ERR! errno ERR_SOCKET_TIMEOUT
#6 178.6 npm ERR! network Invalid response body while trying to fetch https://registry.npmjs.org/express: Socket timeout
#6 178.6 npm ERR! network This is a problem related to network connectivity.
#6 178.6 npm ERR! network In most cases you are behind a proxy or have bad network settings.
#6 178.6 npm ERR! network 
#6 178.6 npm ERR! network If you are behind a proxy, please make sure that the
#6 178.6 npm ERR! network 'proxy' config is set properly.  See: 'npm help config'
#6 178.6 
#6 178.6 npm ERR! A complete log of this run can be found in:
#6 178.6 npm ERR!     /root/.npm/_logs/2022-05-08T14_52_17_816Z-debug-0.log
------
executor failed running [/bin/sh -c npm install -g npm &&     npm install -g @vue/cli]: exit code: 1
ERROR: Service 'vue' failed to build : Build failed
```

成功した場合
![スクリーンショット 2022-05-09 0.16.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/c18d2c64-c1ec-51e8-0d71-2a50d18b9ced.png)
![スクリーンショット 2022-05-09 0.17.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/cb08fe38-ef37-6d7c-032c-8e1725fc2748.png)

失敗した場合
![スクリーンショット 2022-05-09 0.18.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/56ccbdf7-bc41-53c2-3590-9e2a5ed19847.png)
正常にインストールできたか確認しましょう。
```:実行コマンド
$ docker exec -it mysql /bin/bash
root@06d477b04065:/# mysql --version
(以下が表示されればMySQLは正常にインストールされる。)
mysql  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)
root@06d477b04065:/# exit
exit

docker $ docker exec -it spring /bin/bash
root@3fcb4e4b0fe5:/srv# java -version
(以下が表示されればJavaは正常にインストールされる。)
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)
root@3fcb4e4b0fe5:/srv# exit
exit

docker $ docker exec -it vue /bin/bash
root@8fcff5f29ed5:/usr/src/app# npm -version
(以下が表示されればNode.jsは正常にインストールされる。)
8.9.0
root@8fcff5f29ed5:/usr/src/app# node --version
(以下が表示されればNode.jsは正常にインストールされる。)
v14.19.1
root@8fcff5f29ed5:/usr/src/app# exit
exit
```
![スクリーンショット 2022-05-09 0.44.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/22c56459-a4a6-862d-5c7c-bfb80d14d544.png)

Gitを使用する方は一旦この辺りでpushしましょう。

# 手順5:vue_projectの作成
```:実行コマンド
$ docker exec -it vue /bin/bash
root@8fcff5f29ed5:/usr/src/app# vue create .
Vue CLI v5.0.4
? Generate project in current directory? (Y/n) Y

Vue CLI v5.0.4
? Please pick a preset: (Use arrow keys)
> Default ([Vue 3] babel, eslint) 
  Default ([Vue 2] babel, eslint)
  Manually select features

Vue CLI v5.0.4
? Please pick a preset: Default ([Vue 3] babel, eslint) 
? Pick the package manager to use when installing dependencies:
  USE Yarn
> USE NPM
(以下のようになればVueのインストール成功)
...
🎉  Successfully created project app.
👉  Get started with the following commands:

 $ npm run serve
```
![スクリーンショット 2022-05-09 0.47.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/8b4bc07d-e46a-a4fe-1fbe-c3680b47ad46.png)
![スクリーンショット 2022-05-09 0.49.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/70ab5cb4-753d-b8cf-b944-c6db958e5f4f.png)
![スクリーンショット 2022-05-09 0.50.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/990eb556-5562-d59f-e1e2-7e95d11ae57c.png)
![スクリーンショット 2022-05-09 1.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/1ebb89aa-2c16-b298-28bc-4b8066f17038.png)

Vueの実行をして、正常にインストールされた確認します。
```:実行コマンド
root@b330486c1252:/usr/src/app# npm run serve
(以下のようになれば成功)
> app@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 26011ms                                                                          4:24:15 PM


  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://172.19.0.3:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.
```
![スクリーンショット 2022-05-09 1.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/594e6834-a9ee-13b2-dd18-2dbbbf34cbde.png)
ブラウザで以下のURLにアクセスし、以下の画像のように表示されるか確認する。
http://localhost:9000/
![スクリーンショット 2022-05-09 1.26.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/5b95a13d-1bbb-a283-3c8a-b64a6bf3602c.png)

# 手順6:DBの作成(Tableの作成やデータの挿入)
コンテナ作成時に既にデータは挿入されているはずですが、もしない場合は、以下のコマンドを試してください。
```:実行コマンド
$ docker-compose exec mysql /bin/bash
root@5edee7944240:/# mysql -h 127.0.0.1 -P 3306 -uroot -proot
mysql>  show databases;
mysql>  use testdb;
mysql>  show tables;
mysql>  select * from user;
(データがあれば問題なし、なかったら以下を実行する)
mysql>  source /docker-entrypoint-initdb.d/init.sql;
mysql>  select * from user;
(以下のように表示されれば成功)
+----+-------+
| id | name  |
+----+-------+
|  1 | Tarou |
+----+-------+
```
# 手順7:開発1(Vue.js編)
以下は作成する機能の大まかなイメージです。
```:大まかなイメージ
(1)ホーム画面(Home.vue):検索画面(Search.vue)にアクセスできる
(2)検索画面(Search.vue):検索ボタンがあり、押下すると表にデータが表示される。ホーム画面(Home.vue)に戻る
(3)ヘッダー(Header.vue):ホーム画面(Home.vue)、検索画面(Search.vue)共通のヘッダー
```
Vue.jsの開発は以下のものを作成します。
```:開発工程
(1)モジュールのインストール(Bootstrap5)
(2)モジュールのインストール(Vue Router)
(3)モジュールのインストール(axios)
(4)main.jsの修正
(5)vue.config.jsの修正
(6)route.jsの作成
(7)Header.vueの作成
(8)Home.vueの作成
(9)Search.vueの作成
(10)App.vueの修正
(11)Vueの動作確認
```
## (1) モジュールのインストール(Bootstrap5)
Vue.jsでBootstrap5を使えるようにします。
```:実行コマンド
$ docker exec -it vue /bin/bash
root@b330486c1252:/usr/src/app# npm install vue bootstrap-vue bootstrap
npm WARN deprecated popper.js@1.16.1: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1

added 16 packages, and audited 940 packages in 1m

100 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```
![スクリーンショット 2022-05-09 23.23.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/e7b3c920-533c-9f32-3245-057314df44ec.png)

警告メッセージが出るかもしれませんが、一旦無視していただいても問題ないと思います。
(いくつか調べましたがうまくいきませんでした。すみません・・・)
一応調べたことを記載しときます。
```:調べたこと
$ docker exec -it vue /bin/bash
(1) 警告メッセージのとおり、「popper」のバージョンが古いと言われているので、新しいバージョンにする。
npm uninstall @popperjs/core
npm install @popperjs/core

(2)以下のコマンドを実行
npm audit fix
npm audit fix --force

※もしかしたらvueのバージョンが変更される可能性があるのでその場合は
$ npm uninstall vue
$ npm install vue@3.2.13

```
動作確認は他のモジュールのインストールが終わった後に行います。

## (2)モジュールのインストール(Vue Router)
Vue Routerをインストールします。
```:実行コマンド
$ docker exec -it vue /bin/bash
root@b330486c1252:/usr/src/app# npm install vue-router@4

added 2 packages, and audited 957 packages in 8s

101 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```
![スクリーンショット 2022-05-09 23.43.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/738e5e87-e9dc-0372-4e63-e57443454270.png)

## (3)モジュールのインストール(axios)
axiosをインストールします。
```:実行コマンド
docker $ docker exec -it vue /bin/bash
root@b330486c1252:/usr/src/app# npm install axios

added 5 packages, and audited 962 packages in 8s

101 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```
![スクリーンショット 2022-05-09 23.48.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/52490309-b3a1-93b1-1537-e8489620b53d.png)

## (4)main.jsの修正
main.jsを以下のように修正してください。
```:.Docker_Spring_Vue_MySQL/vue_project/src/main.js
import App from './App.vue'
import router from './router/router.js'
import { createApp } from 'vue'
import "bootstrap/dist/css/bootstrap.min.css"
import "bootstrap/dist/js/bootstrap.js"

createApp(App).use(router).mount('#app')
```

## (5)vue.config.jsの修正
vue.config.jsを以下のように修正してください。
```:.Docker_Spring_Vue_MySQL/vue_project/vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  configureWebpack: {
    devtool: 'source-map',
  },
})
```
## (6)route.jsの作成
「.Docker_Spring_Vue_MySQL/vue_project/src/」の下に「route」フォルダーを作成し、「route」フォルダー内に「route.js」を新規作成します。
```:.Docker_Spring_Vue_MySQL/vue_project/src/router/route.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../pages/Home.vue'
import Search from '../pages/app/Search.vue'

const routes = [
    { 
        path: '/', 
        name: 'Home',
        component: Home
    },
    {
        path: '/search', 
        name: 'Search',
        component: Search
    }
]

const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes
})

export default router
```
## (7)Header.vueの作成
「GameGenreSelector/vue_project/src/components/」の下に「Header.vue」を新規作成します。
```:GameGenreSelector/vue_project/src/components/Header.vue
<template>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
        <div class="navbar-nav">
            <a class="nav-link active" aria-current="page" href="/">Home</a>
            <a class="nav-link" href="/search">search</a>
        </div>
        </div>
    </div>
    </nav>
</template>
```
## (8)Home.vueの作成
GameGenreSelector/vue_project/src/の下に「pages」フォルダーを作成し、「pages」フォルダー内に「Home.vue」を新規作成します。

```: GameGenreSelector/vue_project/src/pages/Home.vue
<template>
    <h1>Home</h1>
</template>
```
## (9)Search.vueの作成
GameGenreSelector/vue_project/src/の下に「app」フォルダーを作成し、「app」フォルダー内に「Search.vue」を新規作成します。
```:GameGenreSelector/vue_project/src/pages/app/Search.vue
<template>
    <div>
        <button @click="search" type="button" class="btn btn-primary">検索</button>
        <table class="table">
            <thead>
                <tr>
                <th scope="col">ID</th>
                <th scope="col">ユーザ名</th>
                </tr>
            </thead>
            <tbody>   
                <tr  v-for="item in items" :key="item.message">
                    <th scope="row">{{item.id}}</th>
                    <td>{{item.name}}</td>
                </tr>   
            </tbody>
        </table>
    </div>
</template>
<script>
    import axios from 'axios';
    export default {
        data(){
            return{
                items: []
            }
        },
        methods: {
            search (){
                axios
                .get('http://localhost:8080/search')
                .then(
                    response => {
                        for (let i=0; i<response.data.length; i++) {
                            this.items.push(response.data[i]);
                        }
                        console.log(this.items);
                    } 
                ).catch(
                    error => {
                        let errorData1 = {id: 2, name: "Jirou"};
                        let errorData2 = {id: 3, name: "Saburou"};
                        this.items.push(errorData1);
                        this.items.push(errorData2);
                    }
                );
            }
        }
    }
</script>
```
## (10)App.vueの修正
vue.config.jsを以下のように修正してください。
```:.GameGenreSelector/vue_project/src/App.vue
<template>
    <div id="app">
      <Header/>
      <router-view name="Header"></router-view>
      <router-view></router-view>
    </div>
</template>

<script>
  import Header from './components/Header'
  export default {
    name: 'App',
    components: {
      Header
    }
  }
</script>
```
## (11)Vueの動作確認
お待たせしました。Vueの動作確認をしましょう。
```:実行コマンド
docker $ docker exec -it vue /bin/bash
root@b330486c1252:/usr/src/app# npm run serve

> app@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 37356ms                                                                         3:48:51 PM


  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://172.19.0.3:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.
```
もし警告メッセージが出た場合は次のコマンドを実行してください。
```:警告メッセージが出た場合
docker $ docker exec -it vue /bin/bash
root@b330486c1252:/usr/src/app# npm run serve
> app@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 WARNING  Compiled with 1 warning                                                                               3:37:56 PM

 warning  in ./node_modules/bootstrap/dist/css/bootstrap.min.css

Module Warning (from ./node_modules/postcss-loader/dist/cjs.js):
Warning

(6:29521) autoprefixer: Replace color-adjust to print-color-adjust. The color-adjust shorthand is currently deprecated.


  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://172.19.0.3:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

####(このコマンドを実行)####
root@b330486c1252:/usr/src/app# npm install autoprefixer@10.4.5 --save-exact

changed 1 package, and audited 962 packages in 11s

101 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

####(再度をサービスを起動する)####
root@b330486c1252:/usr/src/app# npm run serve

> app@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 37356ms                                                                         3:48:51 PM


  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://172.19.0.3:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

```
ブラウザでアクセスしてください。
http://localhost:9000/
![スクリーンショット 2022-05-10 0.57.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/57c8d9ca-eb8d-bc3a-6b71-fbd0f0f197f4.png)

検索画面へアクセス(searchをクリック)してください。
または以下へブラウザでアクセスしてください。
http://localhost:9000/search
![スクリーンショット 2022-05-10 0.59.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/d0f75b1b-2544-4a3e-1fc9-d6f44fc6084a.png)

検索ボタンを押下してください。
![スクリーンショット 2022-05-10 1.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/34ac56ab-e2ce-dc6b-79d7-92bbeb3fe7d6.png)

・Bootstrap5はナビゲーションバーやボタンのレイアウトが上手くいけば成功です。
・Vue Routerは画面遷移が上手くいっていたら成功です。
・axiosはまだspringと連携していないので、catchで作成したerrorData1,errorData2の内容が反映されていれば成功です。

お疲れ様です。これで、Vueの開発は成功です。
次からSpringの開発を行います。

# 手順8:開発2(Spring編)
初めにVSCodeで「Remote Development」と「Remote - SSH: Editing Configuration Files」の拡張機能をインストールしましょう。コンテナ内のspringプロジェクトを直接操作したりデバッグ等をするのに使用します。
![スクリーンショット 2022-05-09 1.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/a3ff3693-c6d4-3af4-1b01-390833df6c17.png)
次に、今まで触れていなかった「.Docker_Spring_Vue_MySQL/.devcontainer/」の「devcontainer.json」を作成しましょう。
```:.Docker_Spring_Vue_MySQL/.devcontainer/devcontainer.json
{
    "name": "spring-vue-mysql",
    "workspaceFolder": "/srv",
    "dockerComposeFile": "../docker/docker-compose.yml",
    "settings": { 
        // Macの場合
        "terminal.integrated.defaultProfile.osx": "/bin/bash" 
        // Windows(WSL)の場合(おそらく・・・動作確認はしていません。)
        // "terminal.integrated.defaultProfile.linux": "/bin/bash",        
    },
    "service": "spring", //attachするコンテナはspringを指定
    "extensions": [
        "vscjava.vscode-java-pack", // JavaExtensionPack
        "pivotal.vscode-boot-dev-pack", // Spring Boot Extension Pack
        "gabrielbb.vscode-lombok" //Lombok Annotations Support For VS Code
    ]
}
```
作成したら、VSCodeの左下、歯車(設定)の下の「><」のような部分をクリックしましょう。
![スクリーンショット 2022-05-10 18.16.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/d3bba194-b7c7-264f-e2fa-7c01bd6ed9d5.png)
次に、「Reopen in Container Remote-Containers」を選択します。
![スクリーンショット 2022-05-10 18.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/ed0a576b-13b9-10d9-35f4-57048302d2d6.png)
すると以下のようにVSCodeが切り替わると思います。
![スクリーンショット 2022-05-10 18.26.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/1d6001ce-1b60-68a1-1b37-2c6ff7932d64.png)
springのプロジェクトが表示されていると思います。
最初はインストール等を行なうので時間がかかるかもしれが、時間がたてば上記のようにspringのプロジェクトが表示されるはずです。
![スクリーンショット 2022-05-10 17.37.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/fd9ac145-5384-78c7-cb79-45f6f380328b.png)
お待たせしました。それでは、Springの開発を始めましょう。

以下は作成する機能の大まかなイメージです。
```:大まかなイメージ
(1)検索ボタン押下後、DBにアクセスし、user情報を取得する。
(2)取得したDBの情報を画面に返す
```
Springの開発は以下のものを作成します。
```:開発工程
(1)application.propertiesの設定
(2)Accessorの実装
(3)Interfaceの実装
(4)Controllerの実装
(5)Mapper.javaの実装
(6)Mapper.xmlの実装
(7)Serviceの実装
(8)実行
```

## (1)application.propertiesの設定
「application.properties」はMySQLへ接続するための設定を記載します。そのために、VSCodeではないターミナルを開いて、MySQLのコンテナに入り、catコマンドでコンテナのIPアドレスを調べましょう。
```:実行コマンド
$ docker exec -it mysql /bin/bash
root@5edee7944240:/# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.19.0.3	5edee7944240
```
catコマンドの最後のIPアドレスが自身のMySQLが存在する環境のIPアドレスです。
今回、投稿者の場合は、「172.19.0.3」ですが、人によってIPアドレスは違うと思うので任意で読み替えてください。
それでは、「application.properties」の設定を行いましょう。

```:/srv/src/main/resources/application.properties
#※localhostを指定すると、springコンテナのIPアドレスを指定していることになるのでエラーになる
#spring.datasource.url=jdbc:mysql://localhost:3306/testdb
#※IPアドレスに注意(localhost:3306はコンテナが違うため)
spring.datasource.url=jdbc:mysql://172.19.0.3:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.configuration.map-underscore-to-camel-case=true

##以下はログ詳細に出してくれるものなのであってもなくても良いです。
# Web関連のロガーのログレベルをDEBUG or TRACEへ
logging.level.web=trace

# Spring MVCへのリクエスト/レスポンスログの詳細情報出力を有効化
spring.mvc.log-request-details=true
```
ローカル環境だと1行目のようにlocalhostと指定しがちですが、localhostを指定するとspringコンテナのIPアドレスを指定していることになるのでMySQLのコンテナのIPアドレスと異なるので接続できずにエラーになってしまいます。
なので最初に、catコマンドでMySQLのコンテナのIPアドレスを調べてもらいました。

## (2)Accessorの実装
DBからデータを取得するときと画面にデータを返すための「UserInfo.java」を実装しましょう。
```:/srv/src/main/java/app/spring_project/testapp/accessors/UserInfo.java
package app.spring_project.testapp.accessors;

import lombok.Data;

@Data
public class UserInfo {
    private int id;
    private String name;
}
```
## (3)Interfaceの実装
ControllerクラスとServiceクラスを繋げるためのInterfaceを実装します。
```:/srv/src/main/java/app/spring_project/testapp/interfaces/SearchServiceImpl.java
package app.spring_project.testapp.interfaces;

import java.util.List;

import app.spring_project.testapp.accessors.UserInfo;

public interface SearchServiceImpl {
    List<UserInfo> callService();
}

```

## (4)Controllerの実装
Controllerの実装をします。今回は検索機能なので「SearchController.java」を実装しましょう。
「Search.vue」のaxiosで「 http://localhost:8080/search 」にリクエストしているのでそれを受け取れるようにします。

```:/srv/src/main/java/app/spring_project/testapp/accessors/SearchController.java
package app.spring_project.testapp.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import app.spring_project.testapp.accessors.UserInfo;
import app.spring_project.testapp.interfaces.SearchServiceImpl;

@RestController
@CrossOrigin(origins = {"http://localhost:9000"})
public class SearchController {
    
    @Autowired
    private SearchServiceImpl service;
    @RequestMapping("/search")
    public List<UserInfo> search() {
        return service.callService();
    }
}
```
## (5)Mapper.javaの実装
検索するSQLを呼び出すためのインターフェース、「SearchMapper.java」を実装しましょう。
```:/srv/src/main/java/app/spring_project/testapp/mapper/SearchMapper.java
package app.spring_project.testapp.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import app.spring_project.testapp.accessors.UserInfo;

@Mapper
public interface SearchMapper {
    List<UserInfo> selectUser();
}

```
## (6)Mapper.xmlの実装
「user」テーブルから「id,name」を取得するSQLを作成するために「SearchMapper.xml」を実装しましょう。
```:/srv/src/main/resources/app/spring_project/testapp/mapper/SearchMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="app.spring_project.testapp.mapper.SearchMapper">
    <select id="selectUser" resultType="app.spring_project.testapp.accessors.UserInfo">
        SELECT id, name FROM user
    </select>
</mapper>
```

## (7)Serviceの実装
SQL結果を呼び出す「SearchService.java」クラスを実装しましょう。
```:/srv/src/main/resources/app/spring_project/testapp/services/SearchService.java
package app.spring_project.testapp.services;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import app.spring_project.testapp.accessors.UserInfo;
import app.spring_project.testapp.interfaces.SearchServiceImpl;
import app.spring_project.testapp.mapper.SearchMapper;

@Service
public class SearchService implements SearchServiceImpl{
    @Autowired
    private SearchMapper mapper;
    @Override
    public List<UserInfo> callService() {
        return mapper.selectUser();
    }
}
```
## (8)spring実行
「/srv/src/main/java/app/spring_project/SpringProjectApplication.java」を開くとmainメソッドの上に「Run | Debug」と表示されていると思うのでどちらでも構いませんがクリックするとspringのプロジェクトがされるのでエラーがないか確認しましょう。
![スクリーンショット 2022-05-10 21.50.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/a3e98e42-dc81-2e4d-b570-d6793606c3bb.png)

成功すると以下のようになります。
![スクリーンショット 2022-05-10 21.57.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/ca60ae3f-0928-e155-172f-db217bcc90f9.png)

自分は一度以下のエラーに合いました。原因は正確にはわからなかったのですが、最初は「SearchMapper.xml」の2~4行目(<!DOCTYPE mapper~>)の部分を1行にしていたのですが、改行させました。また、「~[/srv/bin/main/app/spring_project/testapp/mapper/SearchMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.」のようなエラーが出ていたので、「SearchMapper.xml」の1~4行目をそのままコピペして、エラーが出るかもしれません。手入力してみると良いかもしれません。
```:エラーログ
root@e1c653c4dcd1:/srv#  cd /srv ; /usr/bin/env /usr/local/openjdk-8/bin/java -cp /tmp/cp_3eelvnh0sq5e0cqtb2r7qdf0l.jar app.spring_project.SpringProjectApplication 
12:01:52.636 [Thread-2] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@5de3c9de

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

2022-05-10 12:01:59.957  INFO 59857 --- [  restartedMain] a.s.SpringProjectApplication             : Starting SpringProjectApplication using Java 1.8.0_332 on e1c653c4dcd1 with PID 59857 (/srv/bin/main started by root in /srv)
2022-05-10 12:01:59.981  INFO 59857 --- [  restartedMain] a.s.SpringProjectApplication             : No active profile set, falling back to 1 default profile: "default"
2022-05-10 12:02:01.171  INFO 59857 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2022-05-10 12:02:20.938  INFO 59857 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-05-10 12:02:21.049  INFO 59857 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-05-10 12:02:21.051  INFO 59857 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.62]
2022-05-10 12:02:21.568  INFO 59857 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-05-10 12:02:21.569  INFO 59857 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 20391 ms
2022-05-10 12:02:21.603 TRACE 59857 --- [  restartedMain] o.s.b.w.s.ServletContextInitializerBeans : Added existing Servlet initializer bean 'dispatcherServletRegistration'; order=2147483647, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class]
2022-05-10 12:02:21.732 TRACE 59857 --- [  restartedMain] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'characterEncodingFilter'; order=-2147483648, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class]
2022-05-10 12:02:21.739 TRACE 59857 --- [  restartedMain] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'formContentFilter'; order=-9900, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]
2022-05-10 12:02:21.742 TRACE 59857 --- [  restartedMain] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'requestContextFilter'; order=-105, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]
2022-05-10 12:02:21.805 DEBUG 59857 --- [  restartedMain] o.s.b.w.s.ServletContextInitializerBeans : Mapping filters: characterEncodingFilter urls=[/*] order=-2147483648, formContentFilter urls=[/*] order=-9900, requestContextFilter urls=[/*] order=-105
2022-05-10 12:02:21.806 DEBUG 59857 --- [  restartedMain] o.s.b.w.s.ServletContextInitializerBeans : Mapping servlets: dispatcherServlet urls=[/]
2022-05-10 12:02:24.262 ERROR 59857 --- [  restartedMain] o.m.spring.mapper.MapperFactoryBean      : Error while adding the mapper 'interface app.spring_project.testapp.mapper.SearchMapper' to configuration.

org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
        at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:263) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.parsing.XPathParser.<init>(XPathParser.java:127) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.xml.XMLMapperBuilder.<init>(XMLMapperBuilder.java:81) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.xml.XMLMapperBuilder.<init>(XMLMapperBuilder.java:76) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(MapperAnnotationBuilder.java:178) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:118) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.session.Configuration.addMapper(Configuration.java:864) ~[mybatis-3.5.9.jar:3.5.9]
        at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:80) ~[mybatis-spring-2.0.7.jar:2.0.7]
        at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44) [spring-tx-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) [spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.19.jar:5.3.19]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.19.jar:5.3.19]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.7.jar:2.6.7]
        at app.spring_project.SpringProjectApplication.main(SpringProjectApplication.java:10) ~[main/:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_332]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_332]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_332]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_332]
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.6.7.jar:2.6.7]
Caused by: org.xml.sax.SAXParseException: Premature end of file.
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:399) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:326) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1466) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1013) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:601) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:504) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:338) ~[na:1.8.0_332]
        at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:261) ~[mybatis-3.5.9.jar:3.5.9]
        ... 60 common frames omitted

2022-05-10 12:02:24.332  WARN 59857 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'searchController': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'searchService': Unsatisfied dependency expressed through field 'mapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchMapper' defined in file [/srv/bin/main/app/spring_project/testapp/mapper/SearchMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
2022-05-10 12:02:24.488  INFO 59857 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2022-05-10 12:02:24.761  INFO 59857 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-05-10 12:02:25.476 ERROR 59857 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'searchController': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'searchService': Unsatisfied dependency expressed through field 'mapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchMapper' defined in file [/srv/bin/main/app/spring_project/testapp/mapper/SearchMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.19.jar:5.3.19]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.19.jar:5.3.19]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) [spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) [spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) [spring-boot-2.6.7.jar:2.6.7]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) [spring-boot-2.6.7.jar:2.6.7]
        at app.spring_project.SpringProjectApplication.main(SpringProjectApplication.java:10) [main/:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_332]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_332]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_332]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_332]
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.6.7.jar:2.6.7]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'searchService': Unsatisfied dependency expressed through field 'mapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchMapper' defined in file [/srv/bin/main/app/spring_project/testapp/mapper/SearchMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.19.jar:5.3.19]
        ... 25 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchMapper' defined in file [/srv/bin/main/app/spring_project/testapp/mapper/SearchMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:656) ~[spring-beans-5.3.19.jar:5.3.19]
        ... 39 common frames omitted
Caused by: java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
        at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:83) ~[mybatis-spring-2.0.7.jar:2.0.7]
        at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44) ~[spring-tx-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.19.jar:5.3.19]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.19.jar:5.3.19]
        ... 49 common frames omitted
Caused by: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.
        at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:263) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.parsing.XPathParser.<init>(XPathParser.java:127) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.xml.XMLMapperBuilder.<init>(XMLMapperBuilder.java:81) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.xml.XMLMapperBuilder.<init>(XMLMapperBuilder.java:76) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(MapperAnnotationBuilder.java:178) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:118) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72) ~[mybatis-3.5.9.jar:3.5.9]
        at org.apache.ibatis.session.Configuration.addMapper(Configuration.java:864) ~[mybatis-3.5.9.jar:3.5.9]
        at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:80) ~[mybatis-spring-2.0.7.jar:2.0.7]
        ... 52 common frames omitted
Caused by: org.xml.sax.SAXParseException: Premature end of file.
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:399) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:326) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1466) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1013) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:601) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:504) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243) ~[na:1.8.0_332]
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:338) ~[na:1.8.0_332]
        at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:261) ~[mybatis-3.5.9.jar:3.5.9]
        ... 60 common frames omitted
...

```
お疲れ様です。これでspringの開発も完了です。

# 手順9：動作確認
お待たせしました。これでやっと動作確認ができますね。
springとvueの両方を起動します。springは直前の手順で起動していると思うのでvueを起動します。

```:実行コマンド
docker $ docker exec -it vue /bin/bash
root@b330486c1252:/usr/src/app# npm run serve

> app@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 22511ms                                                                                                                                                           1:21:14 PM


  App running at:
  - Local:   http://localhost:8080/
  - Network: http://172.19.0.2:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.
```
以下にブラウザでアクセスします。
http://localhost:9000/

![スクリーンショット 2022-05-10 22.24.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/222b791f-f4b7-7c5c-42f7-508084b4b1bb.png)

search画面に遷移し、検索ボタンを押下します。
![スクリーンショット 2022-05-10 22.25.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/01c5b6e2-3a13-bf51-ed86-e5a1fb2b696d.png)

DB情報が表示されました!
![スクリーンショット 2022-05-10 22.25.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658090/6a8bf45a-185d-9728-c69d-716212c2b4ee.png)

# 手順10:コンテナの削除
```:実行コマンド
docker $ docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                               NAMES
77b7a254a3fe   openjdk:8    "bash"                   12 seconds ago   Up 10 seconds   0.0.0.0:8080->8080/tcp              spring
29099a8d550f   mysql:8.0    "docker-entrypoint.s…"   15 seconds ago   Up 12 seconds   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql
0224b9a6d45f   docker_vue   "docker-entrypoint.s…"   15 seconds ago   Up 12 seconds   0.0.0.0:9000->8080/tcp              vue
docker $ docker-compose down
Stopping spring ... done
Stopping mysql  ... done
Stopping vue    ... done
Removing spring ... done
Removing mysql  ... done
Removing vue    ... done
Removing network docker_default
docker $ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
docker $ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

次のコマンドで未使用リソースの全削除もあり
docker $ docker system prune -a
```
これで終わりです。

# 最後に
大変長い記事になってしまい申し訳ございません。最後にいくつか自分が上手くいかなかった、つまずいた部分についてと解消した方法についてです。

```:つまずいた点
(1) springの実行でエラーになる。
    - Mybatisに関するエラーで、SearchMapper.xmlの1~4行目の修正でうまくいった。
    - アノテーションのつけ忘れ。@Mapper,@Service, @Controllerなど
(2) springの実行でエラーにならないが、DBアクセスでエラーになる。
    - apprication.propertiesの修正(mysqlコンテナのIPアドレスの確認)
(3) なぜか、lombokが読み込めない。
    - 何回か、「Reopen in Container Remote-Containers」でspringコンテナに入ったり出たりを繰り返す。

以上、ここまでお読みいただきありがとうございます。もしかしたら誤字やミスがあるかもしれません。その場合はご指摘いただけると助かります。