Spring BootのFully Executable Warを試す


## Fully Executable War

Spring Boot 1.3.0.RELEASEからSpring Bootのアプリケーションを単なるExecutable Warではなく、Fully Executable Warとして実行できるようになりました。
Executable Warの場合、systemdを利用しなければjavaで起動するためのシェルが必要でしたが、Fully Executable Warとすることでこういったシェルを作成する必要がなくなります。

## Fully Executable Warの作成方法

spring-boot-maven-pluginをpluginに加え、executable設定をtrueにしてmvn installすると、Fully Executable Warが作成されます。  

```xml
<parent>
  	<groupId>org.springframework.boot</groupId>
  	<artifactId>spring-boot-starter-parent</artifactId>	<version>1.3.1.RELEASE</version>
</parent>

<build>
	<plugins>
    	<plugin>
       		<groupId>org.springframework.boot</groupId>
        	<artifactId>spring-boot-maven-plugin</artifactId>
        	<configuration>
            	<executable>true</executable>                
        	</configuration>                  
    	</plugin>
	</plugins>
</build>
```

Fully Executable Warの先頭に起動用のシェルが記載されています。
なおこのシェルはunzipやjar -xvfなどで解凍しても展開はされませんでした。

```bash
[user01@a12b89fed9fa /]$ more sample-api-1.0-SNAPSHOT.war
#!/bin/bash
#
#    .   ____          _            __ _ _
#   /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
#  ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
#   \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
#    '  |____| .__|_| |_|_| |_\__, | / / / /
#   =========|_|==============|___/=/_/_/_/
#   :: Spring Boot Startup Script ::
#

### BEGIN INIT INFO
# Provides:          sample-api
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: sample-api
# Description:       Spring Boot Starter Parent
# chkconfig:         2345 99 01
### END INIT INFO

[[ -n "$DEBUG" ]] && set -x

# Initialize variables that cannot be provided by a .conf file
WORKING_DIR="$(pwd)"
[[ -n "$JARFILE" ]] && jarfile="$JARFILE"
[[ -n "$APP_NAME" ]] && identity="$APP_NAME"

〜以下略〜

  echo "Usage: $0 {start|stop|restart|force-reload|status|run}"; exit 1;
esac

exit 0

〜以下バイナリ部〜
```

このシェルはspring-boot-maven-pluginによって埋め込まれているものです。  
デフォルトでは以下のシェルが適用されます。

* [launch.script](https://github.com/spring-projects/spring-boot/blob/v1.3.1.RELEASE/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script)

## サービス化

warを適当な場所に配置して/etc/init.dにシンボリックリンクを張るだけでserviceで起動できるようになります。

```bash
ln -s /opt/spring/sample-api/current/lib/sample-api.war /etc/init.d/sample-api
chkconfig --add sample-api  
service sample-api start
```

なお、service実行した時のjavaプロセスのユーザはwarファイルのオーナーになっています。

```bash
[user01@46399238b318 ~]$ ps -ef | grep spring.profiles.active
user01    2577     1  0 Dec27 ?        00:05:37 /usr/java/default/bin/java -Dsun.misc.URLClassPath.disableJarChecking=true -server -Dspring.profiles.active=local -jar /opt/spring/sample/current/lib/sample-api.war
```

### runlevelや起動停止優先順位の変更

デフォルトだとrunlevelは2345、起動優先順は99、停止優先順は01になっています。
変更するには、以下のようにinitInfoChkConfigにchkconfigの値を設定します。  
下の例ではrunlevelは2345、起動優先順は80、停優先順は20になります。
この機能はSpring Boot 1.3.1.RELEASEから利用可能です。

```xml
<plugin>
	<groupId>org.springframework.boot</groupId>
  	<artifactId>spring-boot-maven-plugin</artifactId>
   	<configuration>
   		<executable>true</executable>
   		<embeddedLaunchScriptProperties>
   			<initInfoChkconfig>2345 80 20</initInfoChkconfig>
   		</embeddedLaunchScriptProperties>                        
   	</configuration>                
</plugin>
```

### JVMオプション、PID出力先などの変更

VM引数やPIDファイルの出力場所について設定をすることが可能です。 
Fully Executable Warと同じ場所に、warファイルと同じ名称のconfファイルを作成しておくと、起動時に読み込まれます。

```bash
user01@a12b89fed9fa /]$ ls -lt /opt/spring/sample-api/current/lib/
合計 62200
-rwxr-xr-x 1 user01 user01      475 11月  7 23:59 2015 sample-api.conf
-rwxr-xr-x 1 user01 user01 63684691 11月  7 23:59 2015 sample-api.war
```

confに設定できる項目は公式のこちらに記載されています。
* [Fully Executable Warの起動設定](http://docs.spring.io/spring-boot/docs/1.3.1.RELEASE/reference/htmlsingle/#deployment-script-customization)

Fully Executable War内の起動シェルはconfファイルをsourceしているため、公式に記載されている項目以外にも環境変数を設定したり様々な処理を記載することもできます。


```bash
# Fully Executable War内の起動シェルの46行目付近
[[ -r "${jarfolder}/${configfile}" ]] && source "${jarfolder}/${configfile}"
```

例えば以下のようにumask 002を実行すると、ちゃんと出力ファイルが775のパーミッションで、出力されるようになります。

```bash
PID_FOLDER=/var/run/spring
LOG_FOLDER=/var/log/spring

umask 002

JAVA_HOME=/usr/java/jdk
JAVA_OPTS="-Dspring.profiles.active=local"
```