0

我正在尝试升级我们用于 Play 的 App Engine SDK 版本!从 1.6.0 到 1.7.6 的 Web 应用程序。

升级后,我们不再能够将文件写入本地开发服务器的 blobstore。我们使用下面的代码来写一个文件:

Image img = ImagesServiceFactory.makeImage(uploadedData);

FileService fileService = FileServiceFactory.getFileService();
AppEngineFile file = fileService.createNewBlobFile("image/png", "__initial_data/" + vf.getName());

FileWriteChannel writeChannel = fileService.openWriteChannel(file, true);
OutputStream output = Channels.newOutputStream(writeChannel);

调用fileService.openWriteChannel失败并显示以下堆栈跟踪:

Caused by: java.lang.NullPointerException
    at com.google.appengine.tools.development.RequestEndListenerHelper.register(RequestEndListenerHelper.java:39)
    at com.google.appengine.api.files.dev.LocalFileService.open(LocalFileService.java:247)
    at com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.callInternal(ApiProxyLocalImpl.java:527)
    at com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.call(ApiProxyLocalImpl.java:481)
    at com.google.appengine.tools.development.ApiProxyLocalImpl$AsyncApiCall.call(ApiProxyLocalImpl.java:458)
    at java.util.concurrent.Executors$PrivilegedCallable$1.run(Executors.java:461)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.util.concurrent.Executors$PrivilegedCallable.call(Executors.java:458)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:680)

虽然 App Engine 的 SDK 是开源的,但我无法找到这些开发特定类的源文件来了解内部发生的情况。

有谁知道自 1.6.0 版以来将对象写入 blobstore 的实现细节是否发生了变化?

4

1 回答 1

0

原来这是一场戏!具体问题。play-gae 模块为 App Engine 实现了它自己的 LocalServerEnvironment,称为PlayDevEnvironment. 这包含一个获取属性列表的方法。在 App Engine 版本 1.6.0 和 1.7.7 之间进行了更改,需要返回额外的属性。我们通过如下更改该类来解决它:

public class PlayDevEnvironment implements Environment, LocalServerEnvironment {

    ...

    @Override
    public Map<String, Object> getAttributes() {
        HashMap<String, Object> hashMap = new HashMap<String, Object>();
        hashMap.put(LocalEnvironment.REQUEST_END_LISTENERS, new ArrayList<RequestEndListener>());
        return hashMap;
    }
}
于 2013-04-09T07:48:10.683 回答