Objectify 上下文未启动/缺少 ObjectifyFilter

Objectify context not started / ObjectifyFilter missing

App Engine(突然)告诉我我的 Objectify 设置不正确。它之前工作正常,我 在我的 web.xml.

中使用了 Objectify Filter

这是我日志中的完整堆栈跟踪:

javax.servlet.ServletContext log: unavailable
java.lang.IllegalStateException: You have not started an Objectify context.
                                 You are probably missing the ObjectifyFilter.
                                 If you are not running in the context of an http request, see the ObjectifyService.run() method.
    at com.googlecode.objectify.ObjectifyService.ofy(ObjectifyService.java:44)
    at com.mydomain.gae.defaultmodule.MyObject.loadEverything(MyObject.java:21)
    at com.mydomain.gae.defaultmodule.MyServlet.init(MyServlet.java:40)
    at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:440)
    at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:263)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:685)
    at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
    at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
    at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:206)
    at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:179)
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:136)
    at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:469)
    at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:437)
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:444)
    at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:256)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:308)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:300)
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:441)
    at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:235)
    at java.lang.Thread.run(Thread.java:745)

这是我的 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <listener>
        <listener-class>
            com.mydomain.gae.defaultmodule.Initializer
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.mydomain.gae.defaultmodule.MyServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>ObjectifyFilter</filter-name>
        <filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ObjectifyFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

...然后是代码:

public class Initializer implements ServletContextListener {

    @Override
    public void contextInitialized(@Nonnull final ServletContextEvent SCE) {
        ObjectifyFactory oFactory = ObjectifyService.factory();
        oFactory.register(MyEntity.class);
        oFactory.register(MyOtherEntity.class);
        oFactory.begin();
    }
}

public final class MyServlet extends HttpServlet {

    private MyObject = myObj;

    @Override
    public void init() throws ServletException {
        myObj = new MyObject();
        myObj.loadEverything();
    }
}

public class MyObject extends MyOtherObject {

    public void loadEverything() {
        for (MyEntity me : ofy().load().type(MyEntity.class).list()) {
            // Do very important things.
        }
    }
}

IllegalStateException 一到达 ofy().load().type(MyEntity.class).list() 就被抛出。此代码以前有效。我不知道为什么这突然在我面前爆炸了,因为这里共享的代码 none 在爆炸之前被更改了。

如果有人有任何想法可以让我朝着正确的方向前进,我 100% 有兴趣听取他们的意见。

过滤器适用于请求。您的 servlet init 方法未在请求的上下文中被调用,因此 ObjectifyFilter 未被调用 运行 - 请注意它不在您的堆栈跟踪中。

去掉你 contextInitialized() 中的 oFactory.begin(),那不是该方法的正确用法。

如果您想在 servlet init() 中使用 Objectify,运行 您在 ObjectifyService.run() 中的代码:

ObjectifyService.run(new VoidWork() {
    public void vrun() {
        myObj = new MyObject();
        myObj.loadEverything();
    }
});

这将以与过滤器相同的方式设置和拆除 Objectify 上下文。

对我来说,问题出在 web.xml 文件中。我必须添加过滤器和过滤器映射...

<filter>
    <filter-name>ObjectifyFilter</filter-name>
    <filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>ObjectifyFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

但是,我在我的 ServletContextListener 中使用了 ObjectifyFactory;像这样:

ObjectifyService.init(new ObjectifyFactory(
    DatastoreOptions.newBuilder()
        .setProjectId("PROJECT_ID")
        .build()
        .getService()
    ));