対応 Web フレームワーク
Bolt for Java は特定の環境やフレームワークに依存しません。
標準では Servlet コンテナー上での動作がサポートされています。そのため、開発者は Bolt アプリをほとんどの JVM 上で動作する Web フレームワークと組み合わせて動作させることができます。SlackAppServlet は、POST /slack/events
という URI に来るリクエストを受け付けて、適切に対応する Bolt アプリのハンドラーにディスパッチするだけのシンプルな Servlet です。
Micronaut や Helidon のように Servlet ではない環境も、その固有の HTTP 関連の表現(リクエスト・レスポンス)を変換するアダプターさえあれば、Bolt アプリを動作させることができます。
対応フレームワーク
このセクションでは、最小の動作するサンプルとともに以下の人気フレームワークの対応について説明します。
Spring Boot
Spring Boot は Java の世界で最も人気のある Web フレームワークの一つです。SlackAppServlet を Spring Boot アプリ内で有効にするのが最も簡単なやり方です。それでは小さな Gradle プロジェクトの例を見てみましょう。Bolt は Spring Boot 2.2 以上のバージョンで動作しますので、バージョンにご注意ください。 また、Spring Security などの拡張機能を有効にした場合に、Bolt を利用した部分が正常に動作しなくなる場合があります。 そのような場合は、アプリを複数に分割して Bolt アプリ部分についてはできるだけシンプルに保つことを検討してください。
build.gradle
build.gradle
をプロジェクトのルートディレクトリに配置するところから始めます。Spring Boot 3 を使った例は以下の通りです。見ての通り、わかりやすい普通の Spring Boot アプリのビルド設定です。
plugins {
id 'org.springframework.boot' version '3.0.0'
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.slack.api:bolt-jakarta-servlet:1.45.3'
}
もし何らかの事情で引き続き Spring Boot 2 を使う必要がある場合、設定は以下の通りとなります。
plugins {
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'com.slack.api:bolt-servlet:1.45.3'
}
src/main/java/hello/SlackApp.java
このファイルが、このアプリの本質的な部分です。全ての Slack イベントを扱うロジックはここにあります。この @Configuration
クラスでは、Spring DI コンテナーをフル活用して、他のサービスクラスやどんなコンポーネントも App に注入することができます。
package hello;
import com.slack.api.bolt.App;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SlackApp {
@Bean
public App initSlackApp() {
App app = new App();
app.command("/hello", (req, ctx) -> {
return ctx.ack("What's up?");
});
return app;
}
}
src/main/java/hello/SlackAppController.java
これはある種のボイラープレート的なコードです。リクエストを受け付けるパスは @WebServlet
アノテーションの引数で変更できます。
package hello;
import com.slack.api.bolt.App;
import com.slack.api.bolt.jakarta_servlet.SlackAppServlet;
import jakarta.servlet.annotation.WebServlet;
// Spring Boot 2 では import 部分が少し異なります
// import com.slack.api.bolt.servlet.SlackAppServlet;
// import javax.servlet.annotation.WebServlet;
@WebServlet("/slack/events")
public class SlackAppController extends SlackAppServlet {
public SlackAppController(App app) {
super(app);
}
}
src/main/java/hello/Application.java
これもボイラープレートです。このコードはただ Spring のコンポーネントスキャンの有効化と Spring Boot アプリの起動を行います。
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
もしあなたのアプリが独自の ServletContextListener
を持つ予定なら、上記の Servlet クラスを特定のパッケージに配置し、@ServletComponentScan
の引数にスキャンするパッケージを明に指定することをお勧めします。詳細は #947 を参考にしてください。
src/main/resources/application.yml
最後に、リソースディレクトリに設定ファイルを配置します。以下の例は Slack SDK for Java 関連のログレベルのみを DEBUG に変更し、起動時にリッスンするポートをデフォルトの 8080 から 3000 に変更しています。
logging.level:
com.slack.api: DEBUG
server:
port: 3000
Bolt アプリを Boot してみよう
準備は以上です!それでは gradle bootRun
でアプリを起動してみましょう。
$ gradle bootRun
> Task :bootRun
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.0)
[main] hello.Application : Starting Application on MACHNE_NAME with PID 7815 (/path-to-project/build/classes/java/main started by seratch in /path-to-project)
[main] hello.Application : No active profile set, falling back to default profiles: default
[main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 3000 (http)
[main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
[main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.29]
[main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
[main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 478 ms
[main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
[main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 3000 (http) with context path ''
[main] hello.Application : Started Application in 1.079 seconds (JVM running for 1.301)
<=========----> 75% EXECUTING [17s]
> :bootRun
そして、このアプリへと Slack API からのリクエストをフォーワードするようにします。
ngrok http 3000 --subdomain {あなたのサブドメイン}
Micronaut
ありふれた Servlet での実行環境ではなく、Micronaut を使いたい場合、bolt-micronaut というライブラリだけを追加します(bolt ライブラリもこれの依存ライブラリとして自動で解決されます)。bolt-jetty は必要ないので注意してください。以下は Maven の例ですが、もちろん Gradle でも同様です。
<!-- Micronaut 3.x と互換性があります -->
<dependency>
<groupId>com.slack.api</groupId>
<artifactId>bolt-micronaut</artifactId>
<version>1.45.3</version>
</dependency>
src/main/java/hello/Application.java
Application.java はボイラープレートです。この内容をそのまま貼り付けるだけで OK です。
package hello;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class);
}
}
src/main/java/hello/AppFactory.java
最もシンプルなやり方は App インスタンスを @Factory
なクラスの中で初期化するやり方です。Micronaut は DI 関連のアノテーションがつけられたクラスを自動でスキャンして、それらをコンポーネントの注入をするときに利用します。
package hello;
import com.slack.api.bolt.App;
import io.micronaut.context.annotation.Factory;
import javax.inject.Singleton;
@Factory
public class AppFactory {
@Singleton
public AppConfig createAppConfig() {
return new AppConfig(); // 環境変数が設定されている前提
}
@Singleton
public App createApp(AppConfig config) {
App app = new App(config);
app.command("/hello", (req, ctx) -> {
return ctx.ack("What's up?");
});
return app;
}
}
src/main/resources/application.yml
リッスンするポートを 3000 のようにデフォルトとは違うものに変更するには、以下のような設定ファイルを配置します。
---
micronaut:
application:
name: micronaut-slack-app
server:
port: 3000
Micronaut アプリを起動
準備は以上です!それでは mvn run
でアプリを起動してみましょう。
[main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1321ms. Server Running: http://localhost:3000
Quarkus Undertow
Quarkus は GraalVM と HotSpot 両方へのパッケージングをサポートしている Web アプリケーションフレームワークです。このセクションでは、どのように SlackAppServlet をこのフレームワークを使って設定するかを説明します。
code.quarkus.io からブランクプロジェクトを生成できます。シンプルな Bolt アプリであれば Web コンポーネント内で Undertow Servlet を選択することをおすすめします。それ以外には何も必要ありません。Generate your application ボタンをクリックして、生成されたプロジェクトの zip ファイルをダウンロードします。
また、もし RESTEasy を使って追加のエンドポイントを実装しないなら、デフォルトで追加されている quarkus-resteasy も外して問題ありません。