はじめに
本記事は2025年08月時点の内容です。AI技術は急速に発展しているため、将来的には解決される可能性があります。
AIコードエディタ Cursor で Spring Boot をベースに Slack Socket Mode を使ったアプリを開発しようとしたところ、完成までたどり着けませんでした。自分で Slack 公式ドキュメントを読んで解決しましたが、いくつか注意すべき点がありました。
本記事では、Spring Boot で Slack Socket Mode を動かす際の注意点と、実際に遭遇したエラーとその解決方法について紹介します。
Slack Socket Mode の魅力
Slack Socket Mode の最大の魅力は、公開URLを持たない非公開の環境(開発中のローカルPCや社内ネットワーク内のサーバーなど)でも、SlackアプリやBotを簡単に動作・開発できる点です。
特に仕事(会社)で使う場合は社内サーバーで bot が運用できるので便利です。
Spring Boot を使うメリット
Spring Boot で Slack Socket Mode を実装するメリットは以下の通りです:
- Docker Image の作成が容易:Spring Boot には標準のタスクとして用意されており、Slack Socket Mode と Docker の相性が良い
- 設定の手軽さ:Spring のリソース値の設定方法が簡単
- Web画面の作成が容易:bot の設定や実行結果を確認するweb画面を作るときに便利
実装サンプルと重要な設定
完全な実装サンプルは GitHub リポジトリ で公開しています。
Spring Boot で Slack Socket Mode を動かす際は、適切なライブラリの選択が重要です。特に Java EE から Jakarta EE への移行により、使用するライブラリによってエラーが発生する可能性があります。
以下が特に重要な build.gradle の設定です:
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.5'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.github.hiroshikubobeng'
version = '0.0.1-SNAPSHOT'
description = 'sample of spring boot web x slack socket mode'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.slack.api:bolt-jakarta-socket-mode:1.45.3'
implementation 'org.glassfish.tyrus.bundles:tyrus-standalone-client:2.2.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
重要なポイント
-
com.slack.api:bolt-socket-modeではなくcom.slack.api:bolt-jakarta-socket-modeを使用 (AI はcom.slack.api:bolt-socket-modeを追加しがち) -
org.glassfish.tyrus.bundles:tyrus-standalone-clientの Version 1.x ではなく 2.x を使用 (AI は Version 1.x を追加しがち) -
org.springframework.boot:spring-boot-starter-websocketは不要(WebSocket 関連のエラーが出た時に AI に解決方法を聞くと追加されがちだが不要)
参考:AIが提案した初期実装で発生したエラーと解決方法
エラーの内容
上記の正しい設定にたどり着く前に、AI コーディングツールが生成した初期のコードで以下のような WebSocket 関連のエラーが発生しました:
2025-09-30T05:10:00.968+09:00 ERROR 33100 --- [slack-bot] [ restartedMain] o.s.boot.SpringApplication : Application run failed
java.lang.NoClassDefFoundError: javax/websocket/DeploymentException
at com.slack.api.Slack.socketMode(Slack.java:174) ~[slack-api-client-1.38.0.jar:1.38.0]
at com.slack.api.bolt.socket_mode.SocketModeApp.lambda$buildSocketModeClientFactory$2(SocketModeApp.java:76) ~[bolt-socket-mode-1.38.0.jar:1.38.0]
at com.slack.api.bolt.socket_mode.SocketModeApp.run(SocketModeApp.java:187) ~[bolt-socket-mode-1.38.0.jar:1.38.0]
at com.slack.api.bolt.socket_mode.SocketModeApp.start(SocketModeApp.java:177) ~[bolt-socket-mode-1.38.0.jar:1.38.0]
at com.example.slackbot.component.SlackBotInitializer.run(SlackBotInitializer.java:30) ~[main/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:770) ~[spring-boot-3.2.0.jar:3.2.0]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:na]
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:765) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331) ~[spring-boot-3.2.0.jar:3.2.0]
at com.example.slackbot.SlackBotApplication.main(SlackBotApplication.java:10) ~[main/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.2.0.jar:3.2.0]
Caused by: java.lang.ClassNotFoundException: javax.websocket.DeploymentException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ~[na:na]
... 23 common frames omitted
エラーの原因
このエラーは Java EE から Jakarta EE への移行 が原因で発生しています。
- Spring Boot 3.x が使用している tomcat は Jakarta EE に依存している
- 古い
javax.websocketパッケージではなく、新しいjakarta.websocketパッケージを使用する必要がある
解決方法
このエラーは、前述の正しい build.gradle の設定に変更することで解決できます。重要なのは:
-
JakartaEE 対応のライブラリを使用:
bolt-jakarta-socket-mode -
適切な WebSocket クライアントを使用:
tyrus-standalone-client:2.2.0
このエラーは、AI が生成した初期コードで古い JavaEE 対応のライブラリを使用していたことが原因でした。
参考:Java Slack SDK公式ドキュメントで注意すべき点
Java Slack SDK 公式ドキュメント を読んでいて、理解が難しいと感じた部分を解説します。
JavaEE と JakartaEE の選択について
Java Slack SDK の socket mode のページでは、Slack のライブラリの依存の定義が JavaEE 対応のものが先に書かれていて、その直後に JakartaEE 対応のものが書かれています。Spring Boot の Version 3.x が使用している Tomcat は Jakarta EE に依存しているので JakartaEE 対応の方を選択する必要があります。
Spring Boot での Socket Mode の情報について
Java Slack SDK の対応 Web フレームワークのページでは、SpringBoot について記載されていますが、Events API の実装方法の記述しか記載されておらず Slack Socket Mode の記載がありません。
まとめ
Spring Boot 3.x 以降 で Slack Socket Mode を動かす際は、以下の点に注意してください:
- JakartaEE 対応のライブラリを使用する
- 適切な WebSocket クライアントのバージョンを使用する
- 不要な依存関係を追加しない
これらの点を押さえることで、Spring Boot で Slack Socket Mode を正常に動作させることができます。