読者です 読者をやめる 読者になる 読者になる

scalaからappengineのapiをたたくシェルがようやくできたっぽい

普通にスクリプトからたたくのは発火村のときにいけてたのですがね。
やっぱり対話的なのがいいでしょうと(元の目論みではそうじゃないと意味ない)。

なんとなくInterpreterLoopかなぁ、と思ったのが正解っぽかった。こちらのエントリを参考にさせてもらいつつつ、jar追加するのどうやるのか、どう見てもsettingsをどうにかすればいいんだけれど。。とか思いつつ、なんやかんやでこんな感じです。

#!/bin/sh
exec scala "$0" "$@"
!#

class AppengineRemoteCallableInterpreterLoop(out : PrintWriter) extends InterpreterLoop(None, out) {
  override val prompt = "scala-appengine>"
  
  override def bindSettings() {       
    super.bindSettings()
    interpreter beQuietDuring {
      interpreter.interpret("import com.google.appengine.api.datastore.DatastoreService")
      interpreter.interpret("import com.google.appengine.api.datastore.DatastoreServiceFactory")
      interpreter.interpret("import com.google.appengine.api.datastore.Entity")
      interpreter.interpret("import balmysundaycandy.scala.client.RemoteCaller")
    }
  }
}

val out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)))
val settings = new GenericRunnerSettings(out.println _)
settings.classpath.value = settings.classpath.value + ":lib/appengine-api-1.0-sdk-1.3.1.jar:lib/appengine-api-labs-1.3.1.jar:lib/appengine-api-stubs.jar:lib/appengine-local-runtime.jar:lib/balmysundaycandy-core.jar:lib/balmysundaycandy-scala.jar:lib/commons-io-1.4.jar:lib/commons-lang-2.4.jar:lib/gaejtools-util-1.3.0-SNAPSHOT.jar:lib/geronimo-servlet_2.5_spec-1.2.jar"

val interpriter = new AppengineRemoteCallableInterpreterLoop(out)
interpriter.main(settings)

試すのはこんなかんじ。

marblejenka:bin marblejenka$ scala-appengine
Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.
scala-appengine>def hoge() : Unit = {
     |   val datastoreService = DatastoreServiceFactory.getDatastoreService()
     |   val entity = new Entity("scala")
     |   entity.setProperty("scala", "scaladaze")
     |   datastoreService.put(entity);
     |   return
     | }
hoge: ()Unit
scala-appengine>
scala-appengine>RemoteCaller.call(hoge)
serviceName:datastore_v3
methodName:Put
spendTimeMilles:493
request:
<Text: entity <
  key <
    app: "balmysundaycandy-scala"
    path <
      El...>
response:
<Text: key <
  app: "balmysundaycandy-scala"
  path <
    Element {
      typ...>

scala-appengine>


今後の課題。
・まぁなんかもうちょっときれいにしたいです。言い訳すると、ここ最近eclipseが言うこと聞かないのです。。
・appidとかjavaに直書きなので他の人が使えない。なんだそれは。
・いちいちサービスをつくるのもめんどいし、デフォルトでdatastore serviceとかがいたらうれしいかも
・クライアント側でログをとってるのでログ出力の意味があまりないのでサーバー側ももうちょっとあんなことやこんなことができるようにする
・runnableをサーバーに飛ばして、api呼び出しとかcpu timeをとってきて、一回いくらの呼び出しになってるかとかわかったら面白いかも
・そうすると、ローカル環境ではマルチスレッドで動かせてサーバー側でも実行できるとか面白いかも。メンテナンスで便利そう。