Herokuに初めてのデプロイ体験。難しかった。

# はじめに

こんにちは。takunと申します。
この記事では初めてWebアプリをデプロイするときにぶつかったエラーとその解決策について、備忘録を箇条書きで挙げて行きます。

投稿者は初心者エンジニアです。間違ったことや不適切な内容となってしまう可能性もあることをご承知ください。また、助言など頂けると嬉しいです。

前提として以下の通り。設計の詳細は、前回記事をご参考にいただけたら幸いです。
使用PC：MacbookAir(Intel)
開発環境：Eclipse
使用言語：Java
使用DB：MySQL5.7
大まかな構成：JSP,サーブレットクラス,DAOクラス

https://qiita.com/takun/items/9ba715007c797e7ed21c




# 目次
① Herokuとは。選んだ理由。
② Heroku CLIがインストールできない
③ 作成したDBへのクエリがロストした。
④ ビルドができない。ビルドって奥が深い。(Java11→8に変更)
⑤ コンテキストルートの設定

# ① Herokuとは。選んだ理由。
HerokuはPaasの１つです。
Paasとはクラウドプラットフォーム、つまりアプリケーションの実行環境とサーバー構築・運用サポート等のインフラを提供してくれるサービスのことです。詳しくは他記事を参考にしてください。


#### 選定理由
> 実際にアプリをリリースしてみたい。
そしたら知り合いからの意見を取り入れやすくなって、アプリをよりよくアップデートしやすくなるよなー。
でも、サーバーとか詳しくないしどうしよう。

上記のような気持ちがあり、今回アプリを上げるに至って以下を重視した結果、Herokuがマッチしてると感じました。
- サーバーの知識が不要なこと
- デプロイが簡単であること
- 比較的安価で使えること
- 使ってる人が多いサービスであること(参考記事も多い)

# ② Heroku CLIがインストールできない
まずは、HerokuのHPでアカウント作成し、以下URLを参考にして進めていきます。

https://devcenter.heroku.com/ja/articles/getting-started-with-java?singlepage=true

> Heroku CLIのインストールが必要らしい。丁寧にコードも載せてくれてるしコピペでいけるなら、余裕かよーw

なんて思っていたら早速 command not found。
そんなちょろくはなかったようです。原因はhomebrewのPATH設定の問題だったようです。私はIntel Mac使っているのですが、同様の方法で解決しました。

https://www.edyhub.com/entry/2022/06/26/193420

その後チュートリアルでは、問題なくサンプルアプリケーションをデプロイできました。

# ③ 作成したDBへのクエリがロストした。
DBの登録についてはclearDB(MySQL)を使いました。

https://phoeducation.work/entry/20210311/1615388400#アプリケーション用の領域確保

上記ブログを参考にしました。途中clearDBのアカウント名とパスワードが表示されるので、DAOへの記載に必要となります。メモを忘れずに。

順調に行ったかのように思えたのも束の間。
作成したDBでshow databases;で4秒以上かかったり、テーブルから1列1行より多くクエリを打ち込むと以下のエラーが現れました。
~~~
ERROR 2013 (HY000) at line :Lost connection to MySQL server during query
~~~

https://qiita.com/shy_azusa/items/9f6ba519cfda626db52b

https://qiita.com/kakudaisuke/items/73aa165bc0f0db522f4f

MySQLの設定ファイルなんてあるんだー（白目
上記記事のおかげで解決しました。本当にありがとうございます。



# ④ ビルドができない。ビルドって奥が深い。(Java11→8に変更)

~~~
remote: -----> Determining which buildpack to use for this app
remote:  !     No default language could be detected for this app. 
~~~
これはHerokuへプロジェクトをプッシュする際にみられたエラーです。
「このアプリはHerokuがサポートするビルドパックに適合しない」といったような意味です。
> んーなんだか色々わからないことがあるぞ・・・

### そもそもビルドってなんだっけ？
ビルドとはコンパイル＋リンク。ソースコードから実行ファイルを作成することです。
一つのアプリケーションを実行するときは、パスの通った複数のファイルからコンパイル(翻訳)、リンク(結合)してできた実行ファイルを読み込みます。
Eclipseでよく使うビルドパスというのは、実行プログラムが指定ファイルを認識するために必要な位置情報の設定を指します。

### ビルドパックって何？
Herokuが提供するような実行環境にプロジェクトをデプロイするとき、今まで自分のPC上のJDKが担っていたコンパイル・実行を代わってくれるファイルです。
pushする際にHerokuがプロジェクトのソースから言語を検知して、必要なビルドパックを供に配置してくれる仕組みとなっています。

> え、HerokuはJava対応していないの？

いや、Javaに対応していても<font color="red">対応しているバージョンに限りがある</font>ということでした。
今回私は以下の流れでデプロイ成功しました。

作成済みの動的プロジェクト(Java11)を
↓
Mavenプロジェクトに変換し、Java8(jdk1.8)に変更。
↓
WARファイルをエクスポートしてデプロイ。


### 補足：Maven,WARファイルとは
- Maven(ビルドツールの１つ)
XMLに記述することで、プロジェクトに必要なライブラリの管理や自動インストールを行う。ビルド〜テスト、パッケージ(jar,WAR)の作成ができる。
- WARファイル
JavaベースのWebアプリケーション(プロジェクト)を圧縮した形式で、Webサーバ上で動作するパッケージ。


##### 以下はデプロイを進める上で参考にさせていただいた記事を挙げていきます。

---

### ● 大部分の手順を参考にさせていただいた記事

https://qiita.com/katsu0511/items/b4b0aef5ea02294d01a6

https://phoeducation.work/entry/20210311/1615388400#アプリケーション用の領域確保

また下記の記事は今回の手順とは異なっていますが、基本GUI操作でGitHubとの連携を用いた手順になっています。分かりやすいと思いました。

https://amybunny.work/post/servlet/

### ● Herokuデプロイコマンド時エラー
WARファイルデプロイ時はgit pushコマンドではなく、heroku deployコマンドを入力します。

https://qiita.com/__m/items/b325f044bfba17a20151
### ● JDK1.8への変更方法
EclipseでMavenに変換したはいいいけど、生成されたpom.xmlの記述を確認しなければいけません。

https://reasonable-code.com/maven-jdk-version/


### ● JDK変更手順と注意点
コンパイラーとプロジェクトファセットどちらも変更する必要があります。

https://honeycomware.hatenablog.jp/entry/2016/11/24/232340

### ● デプロイ時にERROR: Your buildpacks do not contain the heroku/jvm buildpack!
JVMのビルドパックを入れてくださいとのこと。以下を入力。
~~~
heroku buildpacks:add heroku/jvm
~~~
---

# ⑤ コンテキストルートの設定
デプロイ時は以下のようなエラーでweb.xmlの記述が足りないとエラーが出たり、
~~~
[ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-war-plugin:3.2.3:war 
(default-war) on project menu_selection: Error 
assembling WAR: webxml attribute is required (or pre-
existing WEB-INF/web.xml if executing in update mode) -
> [Help 1]
~~~
デプロイ後は、web.xmlとアノテーション (@WebServlet) が同じコンテキストパスで衝突してしまうエラーが出ることもありました。

> そもそもコンテキストパスとかコンテキストルートってなんだ？
どこから設定するんだ？

### コンテキストルート,コンテキストパスとは
コンテキストルートはプロジェクト上のルートディレクトリを指しており、
コンテキストパスはコンテキストルートからの相対パスを指します。
以下の記事を参考にさせていただきました。

https://eng-entrance.com/java-servlet-mapping#URL-5

https://eng-entrance.com/servlet-web-annotation

これらの設定はEclipse上で以下の方法でできるので、必要時パスを書くことを忘れないように気をつけないといけないですね。
- コンテキストパス
  - web.xmlからurlパターンを宣言
  - アノテーションから宣言
- コンテキストルート
  - プロパティ→Webプロジェクトの設定

# おわりに

こんな新米エンジニアの記事をここまで見て頂けて嬉しいです。拙い文章で恐縮ですが、見ていただいてる方に分かりやすい内容となるよう努めていきます！
コメントやアドバイスなど頂けたら嬉しいです！