Darkly Darkly - 2 months ago 24
Java Question

Objectify context not started / ObjectifyFilter missing

App Engine is (all of a sudden) telling me that I have Objectify set up incorrectly. It was working before and I do have the Objectify Filter in my web.xml.

Here's the full stacktrace from my logs:

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$1.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)


Here's my 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>


...and then here's the code:

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.
}
}
}





The
IllegalStateException
is thrown as soon as it gets to the
ofy().load().type(MyEntity.class).list()
. This code worked before. I am at a loss why this has suddenly blown up in my face as none of the code shared here was changed prior to this blowing up.

If anyone has ANY ideas that might get me moving in the right direction, I am 100% interested in hearing them.

Answer

Filters apply to requests. Your servlet init method is not being called in the context of a request, so the ObjectifyFilter is not being run - notice it's not in your stacktrace.

Get rid of the oFactory.begin() in your contextInitialized(), that is not the correct use of that method.

If you want to use Objectify within your servlet init(), run your code within ObjectifyService.run():

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

This will set up & tear down the Objectify context in the same way that the filter does.