- 本稿の前半の記事⇒「JavaでWebサービスを作り続けるための戦略と戦術(前編)」
バッチ処理
ユーザーのブラウザ上での操作をトリガーとして動作するのがWebアプリケーションの基本ですが、画面操作とはまったく無関係に何らかの処理を実行する必要もあります。古いセッション情報や不要となったDBレコードを一定の間隔で破棄する機能、あらかじめ決めた時刻になったら送信するメール配信機能などです。画面処理と対比する形でバッチ処理と呼ばれることがありますが、実はバッチという単語には注意が必要です。
バッチ処理という言葉は本来、「大きめのデータに対する、時間のかかる一括処理」といった意味あいが強いものです。しかしほとんどのWebアプリケーションシステムで必要となるのはバッチ処理というよりはスケジューリング処理です。つまりUNIXのcrontabに似た機能でしょう。Spring Frameworkを使っていると、バッチと聞いてついSpring Batchの使い方を調べ始めてしまうことがありますが、大抵の場合で必要なのはSchedulerです。
@Component public BatchService { @Scheduled(cron="*/5 * * * * MON-FRI") public void execute() { // バッチ的な処理 } } @Configuration @EnableScheduling // ここがポイント @ComponentScan(...) // BatchServiceクラスが含まれるように指定 public class AppConfig { }
Spring 3.1以上であれば最低限たったこれだけの設定クラスとロジッククラスで、このアプリケーションが稼働中の間、5分おきにバッチ処理が走ります。実際にはこうしたバッチ処理をまとめたWebアプリケーションとして構築し、ブラウザ向け画面のボタンでもBatch Serviceのメソッドを実行できるようにしておくと運用しやすくなります。また、念のため二重起動を防ぐようなコーディングも必要でしょう。
Javaでクラウドサービスとつきあう
初めはクラウドと言ってもAmazon S3くらいしか使っていなかったはずのWebアプリケーションが、機能追加を続けている間にいつのまにかAmazon SESやらTwilioやら、複数のクラウドサービスに依存するようになっているのはよくあることです。AWSのサービスだけであればAWS SDK for Javaとして統制されたライブラリが提供されるので何ら心配する必要はありませんが、他のクラウドサービスが提供するJavaライブラリも同時に使おうとすると意外な問題が発生することがあります。
com.amazonaws:aws-java-sdk-s3:1.11.119とcom.twilio.sdk:twilio-java-sdk:6.3.0はそれぞれAWSとTwilioから2017年のほぼ同時期にリリースされました。しかし、RESTエントリポイントにHTTPアクセスするために使用しているライブラリが、AWSのほうはorg.apache.httpcomponents:httpclient:4.5.2ですが、TwilioのSDKではorg.apache.httpcomponents:httpclient:4.2.6です。Apache HttpComponentsライブラリは4.3を境にAPIが大きく変更されています。ここでは詳述しませんが、これらのSDKを混同して利用すると、HTTPアクセスのライブラリはどちらか一方のみを使うことになるため、確実な挙動という意味では不安が残ってしまいます。Twilioの新系統のライブラリ(ただし下位互換性無し)に乗り換えればこの問題は無くなりますが、そうするとTwilioの古いライブラリに依存した古いコードを書き直す必要に迫られます。
こういった問題を回避するコツは、クラウドサービス側が提供するJavaライブラリに頼りすぎないことです。ほとんどのクラウドサービスは根本的にREST APIとして公開されており、各種言語向けのライブラリはそのREST APIに対するHTTPアクセスをラップしているだけです。つまり、クラウドサービスが提供するクライアントJavaライブラリに必ずしも頼る必要はなく、REST APIに対するHTTPリクエスト処理を直接実装するだけで簡単に要求を満たせる場合があります。
Spring Frameworkを使っている場合はHTTPアクセス処理にRestTemplateクラスを使うとよいでしょう。リクエスト処理の調整、レスポンス処理の実装をある一定のパターンに寄せることができます。また、RestTemplateはデフォルトではJava標準のHttpURLConnectionを使いますが、Apache HttpClient、Netty、OkHttpを明示的に指定してHTTP通信することもできます。何らかの理由によりライブラリ競合が発生した場合もその対策が容易です。