为什么我得到“Persistence Manager已关闭”异常

时间:2012-12-24 01:15:58

标签: java google-app-engine jdo

我的应用程序偶尔抛出以下异常

Javax.jdo.JDOFatalUserException: Persistence Manager has been closed
    at org.datanucleus.jdo.JDOPersistenceManager.assertIsOpen(JDOPersistenceManager.java:2125)
    at org.datanucleus.jdo.JDOPersistenceManager.newQuery(JDOPersistenceManager.java:1247)
    at org.datanucleus.jdo.JDOPersistenceManager.newQuery(JDOPersistenceManager.java:1198)
    at org.datanucleus.jdo.JDOPersistenceManager.newQuery(JDOPersistenceManager.java:1352)
    at vik.sakshum.sakshumweb.server.LoginModuleServiceImpl.recoverPassword(LoginModuleServiceImpl.java:377)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_$1.run(Method_.java:165)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.privilegedInvoke(Method_.java:163)
    at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.invoke_(Method_.java:124)
    at com.google.apphosting.runtime.security.shared.intercept.java.lang.reflect.Method_.invoke(Method_.java:43)
    at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:561)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    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.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:102)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
    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 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.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:266)
    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 com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:146)
    at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:447)
    at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:454)
    at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:461)
    at com.google.tracing.TraceContext.runInContext(TraceContext.java:703)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:338)
    at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:330)
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:458)
    at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
    at java.lang.Thread.run(Thread.java:679)

这样一段代码就在这里

public class AdminDashBoardServiceImpl extends RemoteServiceServlet
implements AdminDashBoardService{   
private static final Logger log =
Logger.getLogger(AdminDashBoardServiceImpl.class.getName());

private PersistenceManager pm;

private static final long serialVersionUID = 1L;

@Override
public List<NotificationBean> pullNotifications() throws Exception {
    log.info("start of pullNotifications");
     Long userId = getUserId();
    try{ 
         pm = PMF.get().getPersistenceManager();
         log.info("Logged in user is:" + userId);

         Query query = pm.newQuery(NotificationRecepient.class, "userId == :userId");
         @SuppressWarnings("unchecked")
         List<NotificationRecepient> notifyList = (List<NotificationRecepient>)query.execute(userId);
         if(notifyList.size() == 0)
             return null;

         //find associated notifications
         List<NotificationBean> nList = new ArrayList<NotificationBean>();
         for(NotificationRecepient notify: notifyList){
                Notification nData = pm.getObjectById(Notification.class, notify.getNotificationSeq());
                NotificationBean bean = new NotificationBean(nData.getNotificationSeq(), nData.getTitle(), nData.getDetail(),
                        nData.getCreationDate(), nData.isClosable());

                //#41769745 add notification in the right order
                boolean inserted = false;
                for(int i=0; i < nList.size(); i++){
                    if(bean.getCreationDate() != null && nList.get(i).getCreationDate() != null )
                    if(bean.getCreationDate().before(nList.get(i).getCreationDate())){
                        nList.add(bean);
                        inserted = true;
                        break;
                    }
                }

                if(inserted == false)
                    nList.add(bean);
             }  

         return nList;

    }catch(Exception e) {
        CommonServiceCode csc = new CommonServiceCode();
        csc.postToPivotalTracker("Error while pulling notifications", "User Data: userId:" + userId, e);

        log.severe("Exception in execute of pullNotifications");
        log.severe("Exception class is :" + 
                             e.getClass().getName());
        log.severe("Exception is :" + e.getMessage());
        e.printStackTrace();

        throw new Exception(e.getMessage() + "\nError while pulling notifications");

      } finally {
          try {
              if(pm != null && pm.isClosed() == false)
                  pm.close();
          } catch (Exception e) {
              log.severe("Exception in finally of execute of pullNotifications");
              log.severe("Exception class is :" + 
                                 e.getClass().getName());
              log.severe("Exception is :" + e.getMessage());
              throw new Exception(e.getMessage() + "Unable to close persistence manager");
          }
           log.info("end of pullNotifications");
      }
}

}

1 个答案:

答案 0 :(得分:3)

我有两条建议,即使可能无法解决您的问题,也可能间接有所帮助。

  1. 不要将pm声明为类级别数据成员。你有这个需要吗?我从来没有做。如果可以,请根据需要在方法内声明pm。一旦你关闭它,它就可以被丢弃(并且可以最大限度地减少你获得例外的机会)。

  2. 简化您的pm.close()代码。如果您不使用交易,为什么不尝试这样的事情:

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try
    {
      //
      // Do your query stuff...
      //
    }
    catch(Exception e)
    {
      //
      // Your code...
      //
    }
    finally
    {
      pm.close();
    }