Darkly
Darkly

Reputation: 147

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.

Upvotes: 6

Views: 4814

Answers (2)

Ian Newland
Ian Newland

Reputation: 1744

For me the issue was in the web.xml file. I had to add the filter and filter-mappings...

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

However, I was using the ObjectifyFactory in my ServletContextListener; like so:

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

Upvotes: 0

stickfigure
stickfigure

Reputation: 13556

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.

Upvotes: 5

Related Questions