追記
このエントリを書いた数時間後に、この問題に対する対策が実施されたslim3-1.0.10
がリリースされています。このエントリは無視してそれを使いましょう!
Slim3の単体テスト環境で、先週リリースされた Google App Engine SDK 1.4.3を適用するとQueueへTaskをaddする処理で次のような例外が発生します。
java.lang.IllegalArgumentException: Task name does not match expression [a-zA-Z\d-]{1,500}; given taskname: 'null' at com.google.appengine.api.taskqueue.TaskHandle.validateTaskName(TaskHandle.java:103) at com.google.appengine.api.taskqueue.TaskHandle.(TaskHandle.java:30) at com.google.appengine.api.taskqueue.QueueImpl.add(QueueImpl.java:489)
あれこれ見てみた結果、この原因は、1.4.3 からSDK内でtaskqueue#BulkAddのresponseをチェックするようになった、という事かなと思います。
対処方法
Slim3内部でなんとかするしか無いですが、急いでいる方は次のようにすると応急処置になります。
- Slim3を使ったプロジェクトに、
org.slim3.tester.AppEngineTester
を作成する - Slim3の
org.slim3.tester.AppEngineTester
をそのクラスにまるごとコピーする - 次の箇所を探す。
} else if (service.equals(TASKQUEUE_SERVICE) && method.equals(BULK_ADD_METHOD)) { TaskQueueBulkAddRequest taskPb = new TaskQueueBulkAddRequest(); taskPb.mergeFrom(requestBuf); TaskQueueBulkAddResponse responsePb = new TaskQueueBulkAddResponse(); for (int i = 0; i < taskPb.addRequestSize(); i++) { tasks.add(taskPb.getAddRequest(i)); responsePb.addTaskResult(); } return responsePb.toByteArray();
- その箇所を次のように変更する。
} else if (service.equals(TASKQUEUE_SERVICE) && method.equals(BULK_ADD_METHOD)) { TaskQueueBulkAddRequest taskPb = new TaskQueueBulkAddRequest(); taskPb.mergeFrom(requestBuf); TaskQueueBulkAddResponse responsePb = new TaskQueueBulkAddResponse(); for (int i = 0; i < taskPb.addRequestSize(); i++) { tasks.add(taskPb.getAddRequest(i)); TaskResult taskResult = new TaskResult(); taskResult.setChosenTaskName("task" + String.valueOf(System.nanoTime())); responsePb.addTaskResult(taskResult); // responsePb.addTaskResult(); } return responsePb.toByteArray();
ついでに
どうせSlim3のクラスにパッチをあてるなら…という事で、テスト時の初期ファイルをSlim3の単体テストで使用してテストの処理時間を短縮したい、等考えている人は次の対処をしておくと便利かもしれません。
AppEngineTester#tearDown()
内のApiProxy.setDelegate(originalDelegate);
となっている箇所の後ろに次の処理を追加する。
if (!AppEngineUtil.isProduction()) { ClassLoader loader = loadLibraries(); Class apiProxyLocalImplClass = loader.loadClass(API_PROXY_LOCAL_IMPL_CLASS_NAME); Method stopMethod = apiProxyLocalImplClass.getMethod("stop"); stopMethod.setAccessible(true); stopMethod.invoke(apiProxyLocalImpl); ApiProxy.setEnvironmentForCurrentThread(originalEnvironment); new File("build/test-classes/WEB-INF/appengine-generated/local_db.bin").delete(); }
単体テスト用の初期データファイルをSlim3の単体テスト実行フォルダ(build/test-classes/WEB-INF/)にコピーしてテストする際は、データストアを正しく終了する処理をしておかないとデータファイルが正しく読めなくなってくる(タイミングによっては問題なく読める時もあるw)ための対処です。念には念を入れてlocal_db.binの削除も行っています。この対策を行って、AppEngineTester#setUp()の前に初期データファイルを"build/test-classes/WEB-INF/appengine-generated/local_db.bin
へコピーしておけばテストのための初期データ作成が高速になります。
0 件のコメント:
コメントを投稿