G*でGCMを試した時のメモ
ことしの G* Advent Calendar 2012 : ATND は
さんの言ではないけど皆さん気合入ってますね〜*1。
みなさんみたいなカッコいいお話も書けないので
ちょっと下調べ的メモのお話を*2
GaelykというGroovyでGAEを簡単に触るためのライブラリがあります
エントリが雑多したので分割しました
Gaelyk自体の説明は さん , さんのスライドを参照
JGGUGの先生方は既に通った道を後追いしてるだけのはずなのに
スムーズに行かずに唸ってる自分が居ますですねorz
とりあえず先に進めます
- Download and release notes -- Gaelyk - a lightweight Groovy toolkit for Google App Engine Java からダウンロードしてきたものを展開
- build.gradle環境を修正*3
- この時にデプロイ用のサイト登録等は事前に用意してください*4
classpath 'org.gradle.api.plugins:gradle-gae-plugin:0.8' classpath 'org.gradle.api.plugins:gradle-gaelyk-plugin:0.4' def gaeVersion = '1.7.3'
あたり
でIDE用の設定ファイル作成
./gradlew eclipse
./gradlew idea
graldeのIDEA設定ファイル系の話は @mike_neckさんの記事を参考に
で、eclipseでプロジェクトをインポートすると
なエラーが出るので
Groovy:Unexpected problem with AST transform: The Spock compiler plugin cannot execute because Spock 0.6.0-groovy-1.8 is not compatible with Groovy 2.0.0. For more information, see http://versioninfo.spockframework.org
な感じで対処。
一応、プロジェクト単位でGroovyCompileの設定で 1.8 な指定があるけど効かないね・・
「設定切り替え & ./eclipse -clean」
で動くようになりましたが・・・
何時も思うけどeclipseの対応甘いような*5
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
追記してみて
してみてもダメ*6
./gradlew eclipse
まあココらへんは Gも駆使できるTDDクラスタの
さん、 さん さん さん
あたりならサクッと修正できるんだろうけどなー
とか思いつつ、自分には難しそうなので先に進みます*7
第1段階>
で GCMのでもアプリを動かしてみましょう
でメモった kojiokbさんのスライドより
$ANDROID_HOME/extras/google/gcm/samples
を動かしやすい処にコピーしてきます
gcm-demo-server の方はjettyで動かすことになっていますので
build.gradleファイルをちゃっと作って動かしてみましょう*8
javax.servlet:servlet-api 自体は mavenCentral()に存在はしていますので
libの物を参照しなくてもいいかも・・・
apply plugin : 'jetty' repositories { //mavenCentral() flatDir name: 'servlet', dirs: 'lib' flatDir name: 'gcm', dirs: 'WebContent/WEB-INF/lib' } dependencies { compile 'javax.servlet:servlet-api:2.5' compile 'com.google.android.gcm.server:gcm-server:' compile 'org.json.simple:json_simple:1.1' } sourceSets.main.java.srcDirs=['src'] sourceSets.main.output.classesDir = 'WebContent/WEB-INF/classes' jettyRun { contextPath = "gcm-demo" webAppSourceDirectory=new File('WebContent') httpPort = 9090 }
Google API Consoleから取得したapikeyは
samples/gcm-demo-server/WebContent/WEB-INF/classes
api.key に設定します
gradlew jettyRun
まだこの段階だとローカルアクセスになりますので
jettyを起動するPC と Android を同一Wifi上につなぎます
でJettyを動かしているPCで
ipconfig
あとはSENDER_IDは
https://code.google.com/apis/console/#project:4815162342
だとすると [4815162342]の部分とのお話。
これをgcm-demo-client のAndroidサンプルに転記
public final class CommonUtilities { /** * Base URL of the Demo Server (such as http://my_host:8080/gcm-demo) */ static final String SERVER_URL = "http://192.168.1.101:9090/gcm-demo"; /** * Google API project id registered to use GCM. */ static final String SENDER_ID = "4815162342";
なイメージ。
第2段階>
で 今度はGaelykで動かしてみましょう(途中)
いちから作るのは面倒なので
gcm/sample/gcm-demo-appengine からファイルをチョピチョピコピーしていきましょう
WebContents/favicon.png => src/main/webapp/images/favicon.png
GCMライブラリのコピー>
WebContents/WEB-INF/lib => src/main/webapp/WEB-INF/lib
gcm-server.jar
json_simple-1.1.jar
=>
この方法は gralde gaeRun タスク時等に 毎度 src/main/webapp/WEB-INF/lib 等も cleanされてしまいますので
libフォルダを作成しその中に
gcm-server.jar
json_simple-1.1.jar
を設置します
buildscript { repositories { mavenCentral() flatDir name: 'gcm', dirs: 'lib' //★ } dependencies { classpath 'org.gradle.api.plugins:gradle-gae-plugin:0.8' classpath 'org.gradle.api.plugins:gradle-gaelyk-plugin:0.4' classpath 'eu.appsatori:gradle-fatjar-plugin:0.1.1' classpath 'com.google.android.gcm.server:gcm-server:' //★ classpath 'org.json.simple:json_simple:1.1' //★ } } repositories { mavenCentral() flatDir name: 'gcm', dirs: 'lib' //★ } dependencies { //略 compile 'com.google.android.gcm.server:gcm-server:' //★ compile 'org.json.simple:json_simple:1.1' //★ } task copyRuntimeLibraries(type: Sync) { def webAppLibDirName = 'src/main/webapp/WEB-INF/lib' description = "Copies runtime libraries to $webAppLibDirName." from configurations.runtime into webAppLibDirName //gcm from 'lib' //★ into webAppLibDirName //★ }
でGroovletに起き直せるServletは
src/main/webapp/WEB-INF/groovy
にコピーして改変
書き直しの情報自体は
- Gaelyk - Google App Engine Java用軽量Groovyツールキット
- Growth Curve: GoogleAppEngineにGaelykとT2を仕込んでみる
- The Groovy programming language - 404
- groovlet コードサンプル | プログラマメモ2
や本家のチュートリアル & 上記に上げたスライドを参照
ざっと見る限り
src/main/groovy
src/main/java
src/main/webapp/groovy .. controller と service 用
の構成でよいようです
と思ったのですが、src/main/java に書いている所のコンパイルには
buildscriptの段階でのclasspath参照が必要なようです<でないと参照エラーが出る。
最新版のgaelykだと
src/main/java にライブラリ参照有りの物を置く想定には
なっていないのかもしれません*9
src/main/webapp/WEB-INF/routes.groovy に登録を記載
get "/", forward: "/home" get "/home", forward: "/HomeServlet.groovy" //post "/send", forward: "/SendMessageServlet.groovy" post "/sendAll", forward: "/SendAllMessagesServlet.groovy" post "/unregister", forward: "/UnregisterServlet.groovy" post "/register", forward: "/RegisterServlet.groovy" get "/favicon.ico", redirect: "/images/gaelyk-small-favicon.png"
置き直しが無理なものに関しては
src/main/java
ApiKeyInitializer.java
BaseServlet.java
Datastore.java
SendMessageServlet.java
にコピー。ついでに api.key もコピー
src/main/webapp/WEB-INF/web.xml に登録します
<listener> <listener-class>groovyx.gaelyk.GaelykServletContextListener</listener-class> <!-- //append start--> <listener-class>com.google.android.gcm.demo.server.ApiKeyInitializer</listener-class> <!-- //append end--> </listener> <!-- //append start--> <servlet> <servlet-name>SendMessageServlet</servlet-name> <servlet-class> com.google.android.gcm.demo.server.SendMessageServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SendMessageServlet</servlet-name> <url-pattern>/send</url-pattern> </servlet-mapping> <!-- //append end-->
src/main/webapp/WEB-INF/ に
queue.xml もコピーします
で 一般の例にあるような groovletのみのデフォルトの状態のような実装であれば
通常は
ローカル実行は
gradlew gaeRun
アップロードは
gradlew gaeUpdate
で行くはずなのですが、
src/main/java で参照しているGCMのライブラリの方で
「Loggerが見つからないよ!」 と起動時エラーが出てしまいます *10
という形でタイムアウトな感じです。
ここらへんは
- デモサンプルのようにライブラリに頼る形ではなく自前で実装する?
- ローカル鯖版のように実行、デプロイのみのgradleを作る?
- GroovletでRestfulなサービスを作る方法 - TEPPEI STUDIO みたいなgroovletを作る?
の形になるかもしれません
一応PHP等で実装されている方はいらっしゃるようです
groovlet置換で引っかかってるのはキューイングしてGCM飛ばす所だったりするので
そこら辺差っ引いちゃうと楽なのかなと思ったりも
結論として
Gaelykだけでやろうとすると移植が難しいものがあるよ・・・
というお話になってしましました
しまりが悪くて大変残念です〜><
追記)
下記の記述+αで
gradlew gaeRun
までは行くけと
gradlew gaeUpdate
は行かず。。。。すごく残念><
gradle-gae-plugin 今だとgaelyk前提で作られてるっぽいかな。。。 もしくはgradleの普通のプロジェクト構成前提で作られているのかも。。。有無。。。厳しいですわん
Gaelyk対応のお話は書いてあるんだけどね。。
ピンで GitHub - bmuschko/gradle-gae-plugin: Gradle plugin that provides tasks for uploading, running and managing Google App Engine projects は厳しいのかも
要)
- src/main/webapp/WEB-INF/lib => lib にjarを退避
- 下記のbuild.gradleを作って実行
//apply plugin : 'jetty' apply plugin : 'gae' buildscript { repositories { mavenCentral() } dependencies { classpath 'org.gradle.api.plugins:gradle-gae-plugin:0.8' classpath 'eu.appsatori:gradle-fatjar-plugin:0.1.1' //need optimizeWar task } } repositories { mavenCentral() flatDir name: 'gcm', dirs: 'lib' } dependencies { gaeSdk 'com.google.appengine:appengine-java-sdk:1.7.3' def gaeVersion = '1.7.3' compile "com.google.appengine:appengine-api-1.0-sdk:$gaeVersion", "com.google.appengine:appengine-api-labs:$gaeVersion" compile 'javax.servlet:servlet-api:2.5' compile 'com.google.android.gcm.server:gcm-server:' compile 'org.json.simple:json_simple:1.1' } sourceSets.main.java.srcDirs=['src'] sourceSets.main.output.classesDir = 'WebContent/WEB-INF/classes' gae { httpPort = 9090 webAppSourceDirectory=new File('WebContent') optimizeWar = true appcfg { email = E_MAIL passIn = true //passIn = false //password = PASS_WD logs { severity = 1 outputFile = new File('mylogs.txt') } app { id = 'gradle-gae-test' } } jvmFlags = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000'] downloadSdk = true //warDir = file('WebContent') } task copyRuntimeLibraries(type: Sync) { def webAppLibDirName = 'WebContent/WEB-INF/lib' description = "Copies runtime libraries to $webAppLibDirName." from configurations.runtime into webAppLibDirName //gcm from 'lib' into webAppLibDirName } gaeRun.dependsOn copyRuntimeLibraries
- gradle.properties
E_MAIL=XXXXXXX@gmail.com
*1:orange_cloverさんもすごい記事書いてた。さすがGエバンジェリストw
*2:実際はgaelykの話をしたかったけどタイムアウト気味・・
*3:gaeやpluginが更新されていますので
*4:GAEのランタイムに関してはgradleが落としてきます
*5:STSなら効くという落ちなのかな? あれだいぶ拡張されてるらしいし
*6:ちなみにこのeclipseコマンド追記型っぽい ので再実行する場合は .classpath、.project を消してから行うこと
*7:残念ですが1開発者レベル何度で。。。#なごやこわい
*8:ディレクトリ構成がいい加減なのでチョット変速気味な感じですが・・
*9:日本語訳の旧版だと動きそうなお話に読めるのですが・・・
*10:src/main/webapp/WEB-INF/java のようなスコープ参照でlogging.properties が参照できないと無理そう