事象
GAE/JでBatchジョブを起動しようとBatchServiceClient.create()をコールすると、以下のエラーが発生しました。
java.lang.NullPointerException: Cannot invoke "String.lastIndexOf(int)" because "endpoint" is null
ソースコードはGoogleのスニペットどおりで、ヌルポなど発生するわけがないはずです。しかし何度実行しても、ビルドしなおしても状況に変化はありません。
調査
BatchServiceClient.create()ではどのようにしてBatchServiceClientが生成されているのかわかりませんが、BatchServiceClient.create(BatchServiceSettings settings)メソッドを使用して自分でBatchServiceSettingsを生成して渡せば、生成されるBatchServiceClientの内容をある程度推測できそうです。
とりあえず以下のようなスニペットでBatchServiceSettings.newBuilder()でデフォルト設定のBatchServiceSettingsを生成し、別のBatchジョブの起動に成功しているプロジェクトとBatchServiceSettingsの内容を比較してみました。
BatchServiceSettings settings = BatchServiceSettings.newBuilder().create();
生成されたBatchServiceSettingsの内容で、有意な差異は以下のとおりでした。
成功しているプロジェクト :
endpoint=batch.googleapis.com:443,
失敗するプロジェクト :
endpoint=null,
エラーメッセージどおりですが、endpointがnullです。
endpointは文字列ですし、BatchServiceSettings.Builder.setEntpoint(String endpoint)で設定できます。そこで強制的にendpointに成功しているプロジェクトと同じ値をセットしてBatchServiceSettingsを生成し、それを渡してBatchServiceClientを生成してみると、発生するエラーが以下に変わりました。
com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: Batch API has not been used in project プロジェクト名 before or it is disabled.
Batchが有効になっていない...
解決方法
その1
BatchのAPIを有効にします。GCPコンソールからなら以下の手順になります。
- GCPコンソールの「APIとサービス」-「ライブラリ」を表示。
- 「APIとサービス」にBatchと入力してBatchを探す。
- 検索結果のリストから「Batch API」をクリック。
- Batch APIのページの「有効にする」をクリック。
Batchは手動で有効化する必要があったのを忘れていただけでした。そして最初に目にするエラーメッセージはそれを連想しにくいものなので、気づけないというワナもあったということでした。
その2
とりあえず上記調査と同様にendpointを強制的に設定することで、Batchジョブの実行はできるようになりました。
しかしなぜプロジェクトによって挙動が違うのかは不明のままです。