後からMaven+SpringBootでマルチモジュールプロジェクト

# 記事の内容
Maven ProjectでSpring Bootのプロジェクトを後からマルチモジュール化しなくてはいけなくなった場合の対応方法を残す。
ここでのマルチモジュール化の目的は、後述するCommonプロジェクトのJava実装やResourceを各プロジェクトで使えるようにすることである。
事例が見当たらなかったので残すことで誰かの役に立つことを祈る。

## 制約
Parentプロジェクトが必要だが、Parentプロジェクトは、現在のプロジェクトの上位パスには用意できない（プロジェクトルートは変えない）。

# 初期の構成
## Maven
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/c5246f4d-ee38-b2d9-6cd8-fea7b292509f.png)

### Service1, Service2
Spring Boot Applicationである。それぞれが単独のWebアプリケーションになる。

### Common
Spring Boot Applicationである。Test時のみ単独起動する。基本的には、Service1,2の共通実装。
application-common.ymlを持ち、Service1, Service2の共用プロパティを持つ。

この構成は、Eclipse上は、リソースファイルの共用が可能だが、Mavenによるパッケージングを行うとリソースファイルは取得できない。

## まとめるとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/32deacd1-f6d8-34a3-8bd8-9d557f9f1ee4.png)

### buildイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/22803723-7acd-b7bb-fd1c-5d46989d106e.png)

## 要件をまとめると
* Parentプロジェクトを上位フォルダに用意したくない
* Service1 + Common, Service2 + Commonのマルチモジュールを目指す

# 結論構成
Service1を例に構成を示す。
この構成で、要件を満たしながら以下すべて可能となる。

* `mvn package`
* `mvn spring-boot:run`
* 個別のプロジェクトのSpring Boot Applicationの実行

※この構成は、常に`-Dspring.profiles.active=common`オプションが必要となる
※環境別のapplication-*.yml（local,develop,staging,production）はServiceプロジェクト配下に作成し制御する。
　この場合、`-Dspring.profiles.active=common,local`といような指定で起動することになる。
※Jarの場合、`java -Dspring.profiles.active=common,local -jar Service1-0.0.1-SNAPSHOT.jar`の形。

## フォルダ構成
```
Service1　・・・この単位でソース管理
└ ParentPom
  └ pom.xml
└ pom.xml
Common　・・・この単位でソース管理
└ pom.xml
```
Service1とCommonは同じディレクトリに存在することが前提。
Service1,CommonはそれぞれMavenプロジェクトとして管理し、ソース管理するからこの前提は満たしやすい（というかそういう状況のはず）。

### イメージ
Service1プロジェクトの中にParentプロジェクトを作ってしまう。
こうすることで、ソース管理上も実装上のJavaプロジェクトの管理上もパッケージングの単位も要件通りになる。

* Mavenマルチモジュールプロジェクトとしての依存関係は、
    * Common --> Service1 --> Service1Parent
    * Common --> Service1Parent

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/12741858-9d21-9d9a-fd9b-053804c3a13e.png)

# 実際の対応
## Service1へ行った対応。
### ParentPomディレクトリの作成
マルチモジュールのために、ParentPomを作成する必要があるが、Service1プロジェクト内に作成する。

```
Service1
└ ParentPom
  └ pom.xml
```

#### ParentPomの pom.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <packaging>pom</packaging>

    <modules>
        <!-- ../で上位ディレクトリを遡るのがミソ -->
        <module>../../Common</module>
        <module>../../Service1</module>
    </modules>

    <groupId>com.example</groupId>
    <artifactId>Service1Parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Service1</name>

    <properties>
        <java.version>15</java.version>
    </properties>

    <dependencies>
    </dependencies>
</project>

```

### Service1 pom.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- Parentへの参照 -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>Service1Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/>
    </parent>
    <!-- package成果物 -->
    <packaging>jar</packaging>

    <artifactId>Service1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Service1</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>15</java.version>
        <spring.base.profile>common</spring.base.profile>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.4.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- Mavenマルチモジュールの構成で必要 -->
    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>Common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Spring-Boot用 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.2</version>
                <configuration>
                    <mainClass>com.example.SampleApplication</mainClass>
                    <layout>JAR</layout>
                    <jvmArguments>-Dspring.profiles.active=${spring.base.profile}</jvmArguments>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!-- Compile -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <compilerArgs>
                        <arg>-Xlint:all,-options,-path</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
            <!-- Test -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>-Dspring.profiles.active=${spring.base.profile}</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

```

### Common pom.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- Parentへの参照 -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>Service1Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <!-- package成果物 -->
    <packaging>jar</packaging>
    <artifactId>Common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Common</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>15</java.version>
    </properties>

    <dependencies>
    </dependencies>

</project>

```