Web Apps の Java SE スタックについて

## はじめに
本記事は Microsoft Azure Tech Advent Calendar 2022 の投稿です。

Web Apps の Java ランタイムスタックを眺めていると、Tomcat は具体的にわかるのですが、Java SE (Embedded Web Server) という一般的なスタックが出てきます。このスタックはどのような場合に使うのか本記事では調べていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691192/868ba789-c6c0-2898-6271-1d818f575cd1.png)

## TL;DR
- Java SE は、`java -jar` で動作する Web アプリケーション向けのスタック
- たとえば Tomcat などのサーブレットコンテナが内蔵されている Spring Boot では Java SE スタックを選ぶ

## Java SE (Embedded Web Server)
Tomcat スタックでは、war ファイルを wwwroot 配下に配置することで、Web Apps が用意した Tomcat が war ファイルを動作させます。
一方、Java SE スタックでは、wwwroot に配置された実行可能アーカイブに対して、`java -jar 実行可能アーカイブ`にて Web アプリケーションを動作させます。

Spring Boot を例にとると、実行可能なアーカイブに Tomcat が同梱されており、`java -jar 実行可能アーカイブ`にて Tomcat や Web アプリケーションが動作することになります。
たとえば、Spring Initializr (https://start.spring.io/) の GENERATE から生成した Maven プロジェクトを実際にビルドして実行可能なアーカイブ (jar ファイル) の中身を見てみましょう。Maven プロジェクトの設定は下図の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691192/b05f751b-840a-127d-8131-8c73d38ce17e.png)

ダウンロードした zip を展開して、`pom.xml` があるディレクトリで `./mvnw package` を実行しましょう。すると `target/demo-0.0.1-SNAPSHOT.jar` が生成されているはずです。その jar を `unzip -v` で覗くと tomcat が同梱されていることが分かります。

```
unzip -v target/demo-0.0.1-SNAPSHOT.jar | grep tomcat
 3427929  Stored  3427929   0% 2022-11-09 18:43 e62e8005  BOOT-INF/lib/tomcat-embed-core-9.0.69.jar
  255944  Stored   255944   0% 2022-11-09 18:43 930ec74d  BOOT-INF/lib/tomcat-embed-el-9.0.69.jar
  279178  Stored   279178   0% 2022-11-09 18:43 6d93f012  BOOT-INF/lib/tomcat-embed-websocket-9.0.69.jar
```

`java -jar target/demo-0.0.1-SNAPSHOT.jar` を実行すると、Spring Boot がよしなに Tomcat を起動し、またその Tomcat でサーブレットが動作し、作成した Web アプリケーションが動作する次第です。

```
java -jar target/demo-0.0.1-SNAPSHOT.jar

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

2022-12-16 00:01:43.870  INFO 43657 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to 1 default profile: "default"
2022-12-16 00:01:48.787  INFO 43657 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-12-16 00:01:48.843  INFO 43657 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-12-16 00:01:48.844  INFO 43657 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.69]
2022-12-16 00:01:49.179  INFO 43657 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-12-16 00:01:49.179  INFO 43657 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4738 ms
2022-12-16 00:01:50.571  INFO 43657 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-12-16 00:01:50.593  INFO 43657 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 9.085 seconds (JVM running for 10.634)
```

## Web Apps で動かしてみる
`./src/main/java/com/example/demo/DemoApplication.java` を以下のように修正し、/hello への HTTP リクエストに hello と返すようにします。

```java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	@GetMapping("/hello")
	public String hello() {
		return "hello";
	}
}
```

`./mvnw clean package` で jar を再作成したのち、以下のコマンドで Web App (Linux|Java SE|Java11) にアプリケーションをデプロイします。

```shell
az webapp deploy --resource-group <group-name> --name <app-name> --src-path ./target/demo-0.0.1-SNAPSHOT.jar --type jar
```

`https://<app-name>.azurewebsites.net/hello`をブラウザで開くと hello と表示され、無事 Java SE スタックで Web アプリケーションが動作していることが分かります。

## さいごに
Java SE スタックの具体的なユースケースが、本記事にてクリアになりましたら幸いです。