通常、JavalinはJettyサーバーと密接に統合されているため、Tomcatで直接動作させるのが難しいとされています。しかし、Javalinのサーブレット機能を活用することで、Tomcatコンテナ上でもJavalinを動作させることが可能です。この方法を使って、Tomcat上でJavalinアプリケーションを実行する手順をまとめました。
必要な環境と前提条件
- Java 17
- Apache Tomcat 10.1
- Maven
プロジェクト設定
まず、pom.xml
でJavalinと必要な依存関係を定義します。重要な点として、Javalin
からJetty
の依存を排除し、TomcatでサポートされているサーブレットAPIを使用します。
pom.xml
<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>
<groupId>com.example.demo</groupId>
<artifactId>TomcatJavalin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>6.3.0</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
</dependencies>
<build>
<finalName>tabi2auto</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
サーブレット設定
Tomcat上で動作するように、WEB-INFの中にweb.xml
を追加しておきます。
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Javalin on Tomcat</display-name>
</web-app>
TomcatJavalin.java
- メインのJavalinアプリケーションクラスを継承して作成
TomcatJavalin
クラスは、Javalinの機能を継承して作成しています。Javalinはjettyの依存関係があるため、Tomcat上で動作させるには、以下のように依存関係を取り除いた状態にカスタムが必要です。
package com.example.demo;
import java.util.function.Consumer;
import io.javalin.Javalin;
import io.javalin.config.JavalinConfig;
public class TomcatJavalin extends Javalin {
public TomcatJavalin(final JavalinConfig config) {
super(config);
}
public static TomcatJavalin create() {
return TomcatJavalin.create(config -> {
});
}
public static TomcatJavalin create(final Consumer <JavalinConfig> config) {
final var cfg = new JavalinConfig();
JavalinConfig.applyUserConfig(cfg, config); // mutates app.config and app (adds http-handlers)
final var app = new TomcatJavalin(cfg);
return app;
}
}
TomcatJavalinServlet.java
- Javalinのサーブレット実装
TomcatJavalinServlet
は、HttpServlet
を継承し、init
メソッドでJavalinのインスタンスを設定します。
package com.example.demo;
import io.javalin.http.servlet.JavalinServlet;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet (urlPatterns = "/api/*", name = "TomcatJavalinServlet")
public class TomcatJavalinServlet extends HttpServlet {
private JavalinServlet javalinServlet;
@Override
public void init() {
final var app = TomcatJavalin.create();
app.get("/api/hello", ctx -> ctx.result("Hello from Javalin!"));
this.javalinServlet = (JavalinServlet) app.javalinServlet();
}
@Override
protected void service(final HttpServletRequest req, final HttpServletResponse resp) {
try {
this.javalinServlet.service(req, resp);
} catch (final Exception e) {
e.printStackTrace();
}
}
}
最後に
この設定で、JavalinはTomcatサーブレットコンテナで動作するようになりました。Jettyに依存せずにTomcatで実行するには、依存関係の除外やJavalinServlet
の使用が重要です。
めっちゃ古いけど、参考にした記事