前回までのプロジェクトを、マルチモジュール構成にしていきます。
結論
先に結論から。
前回の記事では、以下のような形を想像していました。
jersey_sample
|- pom.xml
|- src/main/java/package/xxx/sampleapp
|- serverapi
| |- pom.xml
| |- src/main/java/package/yyy/server
|- repository
|- pom.xml
|- src/main/java/package/zzz/repository
まず、マルチモジュールのparentがソースコードを持つことはMavenでは出来ないみたいで、全部を子モジュールにしなければなりませんでした。
で、こう出来ないかと考えたのですが、
jersey_sample
|- pom.xml
|- sampleapp
| |- pom.xml
| |- src/main/webapp (※javaコードを持たない)
|- serverapi
| |- pom.xml
| |- src/main/java/package/yyy/server (※webappフォルダを持たない)
|- repository
|- pom.xml
|- src/main/java/package/zzz/repository
WebAppだけのモジュールを作って、serverapiモジュールを参照してAPI呼び出し出来ないかと考えたのですが、どうにもうまくいきませんでした。
Eclipseなら、クラスパスを追加する方法があるみたいなのですが、IntelliJでは方法がわからず。。。それに、IDE上で出来たとしても、配布するときにどうなるんだ?
ということで、結局こういう形になりました。
jersey_sample
|- pom.xml
|- serverapi
| |- pom.xml
| |- src/main/
| |- java/package/yyy/server
| |- webapp
|- repository
|- pom.xml
|- src/main/java/package/zzz/repository
諦めてAPI層がwebapp
も持つ形にしました。まあ、これで実は必要十分だったことが分かったので、よしとします(汗)
しかし、この界隈はバージョンアップが早くて、普通にググっても古い情報ばかりで、なかなか欲しい情報にたどり着けませんね。検索スキルを磨かないと(汗)
マルチモジュール構成にする
1. 親pom.xml
の作成
まず、今プロジェクトルートにあるpom.xml
をそのまま親として使います。
依存関係は本来、モジュールごとに必要なものを入れるべきかと思いますが(repository層がservletとか要らないはずなので)、今は動かなくなると怖いので(笑)、いったんこのままにしておきます。
<package>
を、pom
に変更するだけです。
<groupId>com.example</groupId>
<artifactId>simple-webapp</artifactId>
<packaging>pom</packaging>
<version>1.1-SNAPSHOT</version>
<name>simple-webapp</name>
バージョンも変えておきました。
2. サブモジュールの作成
まずは、空のサブモジュールを作ります。
- IntelliJのプロジェクトルートを右クリックして、[New]-[Module]
![new_module.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2Fd62cc5d7-a80a-ebe6-4451-5e72689a3cc7.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=f5190026e6695e7e96ed67bb09f18a0e)
- Mavenを選び、[Next]をクリック
![new_mave_module.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2Fc31e8818-eafc-aa9c-74cf-026d9949bdca.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=532434da6dd0496814e8dac2f934164e)
-
serverapi
(任意名称)と入力して[OK]をクリック
![serverapi_module.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2Ff008fc6d-da5b-7c76-cc58-c9c72026fae0.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=7a539381a7f246d683b9105834096462)
- モジュールが追加される
![module_added.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2Fa855cedd-e5d5-7cb8-ccda-ce2ef62a6f99.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=f35a666d5e00ad06389e91bb98428684)
上記手順を繰り返し、repository
モジュールを追加します。
終わると、このような構成になっているはずです。(サブフォルダは閉じてあります)
3. repository
モジュールの作成
今は空っぽのrepository
モジュールに、以下のクラスソースファイルを移動していきます。
- Employees
- EmployeeRepository
- 各例外クラス
- 例外ハンドラーは除く
(1) pom.xml
の編集
<packaging>
をjar
にします。
<artifactId>repository</artifactId>
<packaging>jar</packaging>
(2) DnDでEmployee
クラスをリポジトリモジュールに移動する
-
ファイルをリポジトリモジュールの
src/main/java
フォルダにDrag&Dropする -
移動先を聞かれるので、[To package]を選び、任意のパッケージ名をフルパスで記述する
- ここでは、元々の
com.example
から、com.example.jerseysimple.repository.models
にパッケージを変更しています
- ここでは、元々の
-
パッケージを新たに作るか聞かれるので、[Yes]をクリック
![recactor_make_dir.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F8521bb0b-bcc7-2a6d-e7f1-fcdab16ef271.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=03d36d6f36a6a5c7316fadf41b65ed8e)
- コンフリクト警告が出るが、いったんそのまま[Continue]する
- パッケージ関連は後でまとめて直します。
![refacgtor_conflict.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F7495637d-ecdd-daec-62ce-69fe56fea3d9.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=6c40d71ee929d3d155376fd77dfb4fe8)
他のクラスについても、それぞれ、下記のパッケージに移動していきます。
- EmployeeRepositpry => com.example.jerseysimple.repository
- 例外クラス => com.example.jerseysimple.repository.exceptions
(2)モジュールへ移動後
全て移動が完了すると、このような形になります。
また、このモジュールの一部のクラスにもテストを作っておきました。後で、親レベルでmvn test
としたときに、サブモジュールのテストが全部走ることの確認をしたいので。
EmployeeRepository
はあまり本質的なものじゃないので書きませんが、例外系クラスが簡単なgetMessage
のテストが出来るのでそれらを用意しました。
この時点で、EmployeeRepository.java
を開くと、コンパイルエラーが警告されています。
これを直していきましょう。
(3)モジュールのビルドを通す
- 例外系クラスのimport文を全部消す
![delete_imports.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F932b92d9-2441-0bb2-5791-f8f75350c5da.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=3cd05f685c0cdb0366100af26cf86894)
- 赤字の
Employee
にカーソルを合わせて少し待つと、importを促すポップアップが出るので、表示されている通りのショートカットキーを押す。(Macならoption+エンター)
![import_employee.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2Fa5c667d6-2b81-d043-e591-22f6626ea802.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=6a0a7ba533b4208b47b633cd2e635063)
- その他の例外クラスについても、同様の操作を繰り返す
- メニューの[Build]から、[Build Module
repository
]を選ぶ
![build_repository_module.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2Ff7db0244-04e3-95f7-9a46-78ed58e104f9.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=b1a51370a7915ac1e7546378fd119020)
これで、テストも通過するはずです。
なお、ビルドとテストの確認は、ターミナルなどでrepository
モジュールに移動して、mvn install
としても良いですね。
4. serverapi
モジュールの作成
(1)serverapi/pom.xml
の編集
-<packaging>
をwar
にする
-reipository
モジュールへの依存関係を追加
<artifactId>serverapi</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>repository</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
(2)ソースファイルを移動
repositoryモジュールの時と同じ手順で、下記クラスを移動し、参照を修正します。
- EmployeeResource
-
com.example.jerseysimple.api
パッケージに
-
- MyResource (これはもう削除しても良いがw)
-
com.example.jerseysimple.api
パッケージに
-
- 例外ハンドラクラス
-
com.example.jerseysimple.api.handlers
パッケージに
-
- テストクラス
-
com.example.jerseysimple.api
パッケージに
-
(3)webappディレクトリを移動
serverapi
モジュールのsrc/main
下に移動します。
(4)モジュールへ移動後
モジュールをビルドし、テストを実行してください。
※mvnコマンドの方は現時点で依存関係が解決できず動かないみたいです。IntelliJから行ってください。たぶん、親モジュールのpom
がまだ一度も作られてないからでしょうね。
5. ルートのクリーンアップ
(1)フォルダの削除
ルートにある諸々のフォルダを削除します。
src
resources
(2)クリーン
プロジェクトのルートで、mvn clean
を実行します。
6. 実行
(1)デプロイ対象の変更
Tomcatから起動しますが、[Edit Configuration]の変更が必要です。
- [Deployment]タブを表示し、下部の[+]をクリック
![add_war.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F983c65d4-7253-ea41-3872-13a780c8287f.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=dbe945507d19af2fc7ca57303b6f9393)
- [Articat...]を選ぶ
![select_artifact.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F4c6d655a-61a7-b67f-59c8-a59ce639f4c3.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=7da50a6a4aaf9d48a35845eb0357fe4f)
-
serverapi:war exploded
を選択して、[OK]をクリック
![add_new_war.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F138120f6-cac6-36f7-04be-10e185cb9113.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=eee306e55d663ac874402c89f119ee4e)
-
simple-webapp:war exploded
をクリックして、下部の[-]をクリック
![remove_old_war.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F103886%2F64df2480-edde-0a6c-16a3-f25703217fc5.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=9d7b43093cafd507002eb2784532ac09)
- [OK]をクリック
(2)実行
実行ボタンをクリックします。
ブラウザから各APIにアクセスしてみてください。curlコマンドやPostmanから実行するときは、warが変わったことでURLが変わっていますから気をつけてください。
それから、mvnコマンドでも、ルートからビルド、テストが全部実行されることを確認しましょう。
下記コマンドで、レポートを出すと、モジュールごとのレポートをまとめてくれるので、確認しやすいです。
※こちらの記事にあるプラグインを入れてあることが前提です。
$ mvn clean \
test -Dmaven.test.failure.ignore=true \
site -DgenerateReports=false \
-Daggregate=true \
surefire-report:report
プロジェクトルートのtarget/site
下にhtmlで出力されています。
感想
APIを作るのも楽しくなってきました。でもやっぱりGradle使いたいし、Kotlinが書きたいです(しつこい)
次は、SpringFramework(not Boot)+Jerseyという構成に挑戦してみます。
SpringFrameworkだけでもRESTfulAPIは作れるので、わざわざJerseyと連携させるのも?というところもあるのですが、やってみたいのでやります(笑)
ここまでのソースは、以下にアップしてあります。
参考
- Spring Bootアプリケーションをmavenのmulti moduleで構成する
https://qiita.com/rubytomato@github/items/118817023845b4284553