この記事は、Google Cloud Platform その1 Advent Calendar 2018 の2日目の記事です。

Google Cloud Platform その1 Advent Calendar 2018
https://qiita.com/advent-calendar/2018/gcp

GoogleAppEngineのJavaアプリからCloud Datastoreにアクセスする場合、
Objectifyというライブラリを利用することが多いのですが。
今年(2018年)、Objectifyのv6がリリースされました。

v6は、v5までとは異なるSDKに依存している影響で、
GAEのmemcacheにDatastoreのキャッシュを保存する機能が省略されています。

  • v5まで: Google App Engine SDK
  • v6から: Google Cloud SDK

このエントリでは、
SDK混在による混乱を防ぎながら、v6でGAEのmemcacheを利用する方法を説明します。

objectify:
https://github.com/objectify/objectify

また、Objectifyのv5までとv6の違いは、過去に以下のエントリにも記載しているので、
必要に応じてご覧下さい。

Objectifyのv6変更点、及びSpringBootアプリから利用する場合のメモ | takemikami’s note
http://takemikami.com/2018/05/16/Objectifyv6SpringBoot.html

v6でGAEのmemcacheを利用する方法

先ほど上げたエントリでも記載していますが、
Objectify v6でGAEのmemcacheを利用したい場合は。

Objectify v6に用意されているMemcacheSerivceのInterfaceを持ち、
AppEngineのMemcacheに保存する処理を実装したクラス作る必要があります。

以下に私が実装したコードへのリンクを示します。

AppEngineMemcacheClientService.java | takemikami/objectify-appengine-memcacheclient | Github
https://github.com/takemikami/objectify-appengine-memcacheclient/blob/master/src/main/java/com/github/takemikami/objectify/appengine/AppEngineMemcacheClientService.java

以下のように、
このクラスをObjectifyServiceを初期化する際のパラメータに指定すると、
GAEのmemcacheにDatastoreのキャッシュが保存されるようになります。

ObjectifyService.init(new ObjectifyFactory(
    DatastoreOptions.getDefaultInstance().getService(),
    new AppEngineMemcacheClientService()
));

SDK混在による混乱を防ぐために

ここまでの流れで、GAEのmemcacheを利用できるようになったのですが。

AppEngineMemcacheClientServiceが、Google App Engine SDKに依存。
Objectify v6が、Google Cloud SDKに依存。
という状態になっており、
Google App Engine SDKとGoogle Cloud SDKの両方からDatastoreの機能を利用できてしまうため、
開発を行う上で混乱を招いてしまします。

そこで、AppEngineMemcacheClientServiceの実装をライブラリ化し、
runtime時のみ取り込むようにして開発を行うことをおすすめします。
(JDBCでMySQLやPostgreSQL等のライブラリを取り込むときと同じように)

ライブラリ化したものを以下のGitHubのプロジェクトに置いています。

objectify-appengine-memcacheclient | GitHub
https://github.com/takemikami/objectify-appengine-memcacheclient

build.gradleでは以下のように指定し。

dependencies {
    // SpringBoot
    compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
    compile("org.springframework.boot:spring-boot-starter-web") {
        exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
    }
    providedRuntime "org.springframework.boot:spring-boot-starter-jetty"

    // objectify
    compile group: 'com.googlecode.objectify', name: 'objectify', version: '6.0.2'
    runtime group: 'com.github.takemikami', name: 'objectify-appengine-memcacheclient', version: '0.0.2'
    runtime group: 'com.google.appengine', name: 'appengine-api-1.0-sdk', version: '1.9.65'
}

Objectifyの初期化時に以下のように指定します。

ObjectifyService.init(new ObjectifyFactory(
    DatastoreOptions.getDefaultInstance().getService(),
    (MemcacheService) Class.forName("com.github.takemikami.objectify.appengine.AppEngineMemcacheClientService")
      .getDeclaredConstructor().newInstance()
));

このライブラリを利用するコードの全体は、以下のサンプルをご覧下さい。

example | objectify-appengine-memcacheclient | GitHub
https://github.com/takemikami/objectify-appengine-memcacheclient/tree/master/example

以上の方法で、Google App Engine SDKとGoogle Cloud SDKの
SDK混在による混乱を防ぎながら開発を進められるようになります。

このような工夫が不要になるよう、早くSDKが整理されることを願っています。