arcanum_jp’s blog

おっさんの日記

LINE botをSpringBootで作る

表題の通りです。前提として言語はJava、LINE Developperサイトでの設定は済んでいると仮定します。

pom.xmlに次の依存性を追加


pom.xml

<dependency>
    <groupId>com.linecorp.bot</groupId> 
    <artifactId>line-bot-spring-boot</artifactId>
    <version>2.7.0</version>
</dependency>


バージョンの最新版は以下で確認してください。
mvnrepository.com


application.propertiesにボットのトークンなどを設定します。line.bot.handler.pathはLINE Developperサイトで設定したものです。


application.properties

#---------------------------------------
# LINE
#---------------------------------------
line.bot.channel-token=xxxxxxxxxxxxxxxxxx
line.bot.channel-secret=xxxxxxxxxxxxxxx
line.bot.handler.path=/path/to/line/webhook


あとはコントローラーを作ります。サンプルはこちらにありますね。

github.com

リプライにリプライを返すだけのエコーボットです。

@LineMessageHandler
public class EchoController {

    @EventMapping
    public TextMessage handleTextMessageEvent(MessageEvent<TextMessageContent> event) {
        System.out.println("event: " + event);
        return new TextMessage(event.getMessage().getText());
    }

    @EventMapping
    public void handleDefaultMessageEvent(Event event) {
        System.out.println("event: " + event);
    }
}


クラスに@LineMessageHandlerをつけて、LINEからの目的のWebhookイベントのメソッドを作って@EventMappingをつければ良いようです。では、他の友達追加やブロックなどのイベントはどうやってフックするのでしょうか?例えば友達追加は以下のようなメッソッドを作成します。

@EventMapping
public TextMessage handleFollowEvent(FollowEvent event) {
    return new TextMessage("フォローありがとう!!");
}


どうやら目的のイベントごとの引数をとるメソッドを作るだけのようですね。Eventクラスについては以下を参考にしました。

static.javadoc.io

Eventクラスの既知のサブクラスは以下です。ブロックした場合などは相手にリプライを返せないので戻り値はvoidだったりしますが概ね同じですね。

イベントクラス名 説明
BeaconEvent LINEビーコンを受信した際に発生します。
FollowEvent 友達に入れられたときまたはブロックを解除された時に発生します。
JoinEvent グループやトークルームにジョインした際に発生します。
LeaveEvent グループから離れたときに発生します。
MessageEvent メッセージを受け取った時に発生します。
PostbackEvent 表示したテンプレートメッセージに反応した場合に発生します
UnfollowEvent ブロッックされた時に発生します。
UnknownEvent 上記以外で不明なメッセージを受信した際に発生します。


以前、ServletベースでLINEボットを作っていたことがあり、あの時はWebhookに来るJsonオブジェクトを認証して、自前で解析してtypeでテキストメッセージなのかフォローしてきたのかとか判定して云々なんてやっていたので本当に簡単に作れる感じですね。


その他

line-bot-spring-bootのバージョンを上げたら、こんな感じでokioにそんなメソッドねぇよ!!(意訳)なエラーが出ることがあります。

Exception in thread "OkHttp Dispatcher" java.lang.NoSuchMethodError: okio.BufferedSource.getBuffer()Lokio/Buffer;
        at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:252)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at com.linecorp.bot.client.HeaderInterceptor.intercept(HeaderInterceptor.java:39)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:221)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:172)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

経緯としては始め、Webにあるサンプル通り、line-bot-sdkのバージョンを1.11.0で確認していましたが、上記のリポジトリを見るに2.7.0が最新とわかり、pom.xmlのバージョンを変更、サーバーにアップしてみたところ、上記のような事象が発生するようになりました。


例外メッセージでググるとまさにこれについて検索できました。
github.com

コントリビューターからバージョンを合わせて使ってね?的なメッセージを得てことなきを得ていたようですが、さっぱり意味がわからない。その時にpom.xmlに記載していたのは下記であり、どれもMavenリポジトリを確認してもokHttp3なんて使っていない。

spring-boot-starter-thymeleaf
spring-boot-starter-web
spring-boot-starter-web-services
spring-boot-starter-tomcat


結論として、バージョンを上げた後、プロジェクトのクリーンしてからビルドし、サーバーにデプロイする事で事象は発生しなくなりました。上記のイシューは多分他の依存してるライブラリででokHttpを使っていたのかなと思います。