I've got an app that, in some situation I can't reproduce, locks up both Firefox and Chrome. I have no insight into what's causing the problem. I can't get any information because both browsers just lock up - even firebug and Chrome's developer tools freeze. Impressive, I know!
Anyway, I thought I'd run the app with the debugger hooked up in eclipse, but using RemoteApi to use the actual data so I can see what's happening here. I wrote a ServletFilter:
public class RemoteApiFilter implements Filter {
RemoteApiOptions options;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
chain.doFilter(request, response);
installer.uninstall();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void init(FilterConfig config) throws ServletException {
options = new RemoteApiOptions().server(
config.getInitParameter("host"), 443).credentials(
config.getInitParameter("email"),
config.getInitParameter("password"));
}
}
I run every request through this filter, and I thought this would make my whole app work like normal, but with the live, production datastore instead of with the development datastore. But it didn't work! Instead, on the very first call I make to the datastore api, I get some sort of threading access violation exception:
java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
at java.security.AccessController.checkPermission(AccessController.java:546)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:166)
at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkAccess(DevAppServerFactory.java:191)
at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:299)
at java.lang.Thread.init(Thread.java:336)
at java.lang.Thread.<init>(Thread.java:626)
at java.util.concurrent.Executors$DefaultThreadFactory.newThread(Executors.java:542)
at java.util.concurrent.ThreadPoolExecutor.addThread(ThreadPoolExecutor.java:672)
at java.util.concurrent.ThreadPoolExecutor.addIfUnderCorePoolSize(ThreadPoolExecutor.java:697)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:652)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:92)
at com.google.appengine.tools.remoteapi.RemoteApiDelegate.makeAsyncCall(RemoteApiDelegate.java:98)
at com.google.apphosting.api.ApiProxy.makeAsyncCall(ApiProxy.java:184)
at com.google.appengine.api.datastore.DatastoreApiHelper.makeAsyncCall(DatastoreApiHelper.java:81)
at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.get(AsyncDatastoreServiceImpl.java:306)
at com.googlecode.objectify.cache.CachingAsyncDatastoreService.getFromDatastore(CachingAsyncDatastoreService.java:111)
at com.googlecode.objectify.cache.CachingAsyncDatastoreService.get(CachingAsyncDatastoreService.java:372)
at com.googlecode.objectify.impl.AsyncObjectifyImpl.get(AsyncObjectifyImpl.java:68)
at com.googlecode.objectify.impl.AsyncObjectifyImpl.find(AsyncObjectifyImpl.java:192)
at com.googlecode.objectify.impl.AsyncObjectifyImpl.get(AsyncObjectifyImpl.java:101)
at com.googlecode.objectify.impl.AsyncObjectifyImpl.get(AsyncObjectifyImpl.java:124)
at com.googlecode.objectify.impl.ObjectifyImpl.get(ObjectifyImpl.java:63)
at com.activegrade.server.data.DataCoordinatorAppengineImpl.verifyUser(DataCoordinatorAppengineImpl.java:471)
at com.activegrade.server.servlets.MainPageChooser.doGet(MainPageChooser.java:54)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.activegrade.server.filter.RemoteAPIFilter.doFilter(RemoteAPIFilter.java:25)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:58)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:351)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
I'm using Objectify and Resteasy but otherwise this is a pretty plain setup. I'm totally stumped about what to try next.
Is this a good way to try to debug my GWT application with live data on GAE? What's going wrong, and what should I try next to get more information?