Objectify context not started / ObjectifyFilter missing
Asked Answered
W

2

6

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.

Wines answered 27/12, 2015 at 0:0 Comment(0)
U
5

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.

Unasked answered 27/12, 2015 at 20:51 Comment(3)
factory().run() doesn't seem to exist. I'm guessing you meant ObjectifyService.run()?Wines
Dropping ObjectifyService.run() in to your code worked perfectly, Stick. Thanks A MILLION, sir. Really saved my bacon! It never really occurred to me that init(), unlike every other method in a Servlet isn't actually in the context of an HTTP request. Staggeringly obvious once I actually thought about it...but I had not prior to today. Again, thanks a million, Stick.Wines
Oops yep! I updated the answer. Glad you're back up and running :)Unasked
L
0

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()
    ));
Lauralee answered 3/4, 2019 at 1:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.