はじめに
LINE BOTのトライアルの頃は、自分でJSONをマッピングし、JAX-RS Clientでリプライしたりしていました。
Line Messaging APIになり、Java向けのSDKが提供されているので、今回はこれを利用してみようと思います。
現時点ではSpring Bootから利用するのが便利
今回、JAX-RSからSDKを利用してみて、一番扱いにくさを感じたのが、イベントのマッピングです。
Spring Bootを利用した場合、この辺りが逆に一番楽に扱えるようになっています。
現時点では、Spring Bootのサポートの方が手厚い印象を持ちました。
実装してみる
何はともあれ実装してみます。
お手軽にテキストメッセージをオウム返しするだけのBOTを作成します。
環境
Windows 10 Pro 64bit
Java SE 8 Update 121 64bit
Line Messaging API SDK for Java 1.6.0
Mavenの依存情報を設定する
SDKを利用する為、以下の依存情報をpom.xmlに追加します。
<dependency>
<groupId>com.linecorp.bot</groupId>
<artifactId>line-bot-servlet</artifactId>
<version>1.6.0</version>
</dependency>
SDKは以下の構成になっており、それぞれ一つ上のモジュールに依存しています。
- line-bot-model
- line-bot-api-client
- line-bot-servlet
- line-bot-spring-boot
最後のは当然Spring Boot用なので、line-bot-servletを利用します。
line-bot-servletには、HttpServletRequestをインプットとしたJSONのパーサーが提供されています。
HttpServletRequestからイベント情報を取得する
public Response post(@Context HttpServletRequest request) {
LineSignatureValidator validator = new LineSignatureValidator(channelSecret.getBytes());
LineBotCallbackRequestParser parser = new LineBotCallbackRequestParser(validator);
CallbackRequest callbackRequest = parser.handle(request);
...
@Contextを付けて引数としてHttpServletRequestを受け取ります。
LineSignatureValidatorは、API ReferenceのSignature validationに書いてある処理を行ってくれます。
LineBotCallbackRequestParserのコンストラクタに渡すことで、handle()実行時に署名検証が行われます。
Eventオブジェクトの型からイベントの種類を判断する
パーサーが返すCallbackRequestから取得できるのはList<Event>です。
Eventはインターフェースで、それを実装する各イベントのクラスがあります。
- メッセージ受信 → MessageEvent
- フォローされた → FollowEvent
のような感じです。
これを判定する為のメソッドなどが無く、結局instanceofを使うしかなさそうです。
以下のように指定したイベントのみ返すメソッドを用意しました。
private <T extends Event> List<T> filterEvents(List<Event> events, Class<T> clazz) {
return events.stream().filter(t -> clazz.isAssignableFrom(t.getClass())).map(t -> clazz.cast(t)).collect(Collectors.toList());
}
Spring Bootの場合、@EventMappingを付与したメソッドを用意し、引数の型で各イベントとマッピングできるようです。
APIを利用して返信する
TextMessageに返信したいメッセージを設定し、ReplyMessageに渡します。
LineMessagingServiceBuilderからLineMessagingServiceを生成し、ReplyMessageを渡して返信します。
TextMessage textMessage = new TextMessage(messageContent.getText());
ReplyMessage replyMessage = new ReplyMessage(event.getReplyToken(), textMessage);
LineMessagingServiceBuilder
.create(channelToken)
.build()
.replyMessage(replyMessage)
.execute();
最後のexecute()はretrofit2.Callのメソッドで、Retrofit2というライブラリのクラスです。
あんまりSDK内部で利用しているライブラリは外に出さない方がいいのではないかと感じました。
まとめ
SDKを利用すると、自分でJSONのマッピングする必要が無く、リプライなどもAPI化されていて便利になりました。
気になったこと
前述しましたが、以下の点ですね。
- Eventインターフェースから、イベントの種類を判別する手段が欲しい。
- Retrofit2のAPIがSDKを利用する側から見えている。SDKとして利用するライブラリの変更がしづらくなるのではないか。
JAX-RSでも便利に使えるようになって欲しい
SDKはアップデートされ続けているようなので、今後に期待します。
Spring Bootの@EventMapping並みに便利な仕組みが提供されると嬉しいです。