Why do I get “Persistence Manager has been closed”

2019-09-20 08:52发布

My application various pieces occasionaly throw following exception

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)

The one of such piece of code is here

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条回答
我只想做你的唯一
2楼-- · 2019-09-20 09:20

I have two suggestions which, even though may not solve your problem, might help indirectly.

  1. Do not declare pm as a class-level data member. Do you have a need to do this? I never do. If you can, declare your pm inside a method as needed. Once you have closed it, it can be discarded (and might minimise the chance of you getting your exception).

  2. Simplify your pm.close() code. If you do not use transactions, why not try something like this:

    PersistenceManager pm = PMF.get().getPersistenceManager();
    try
    {
      //
      // Do your query stuff...
      //
    }
    catch(Exception e)
    {
      //
      // Your code...
      //
    }
    finally
    {
      pm.close();
    }
    
查看更多
登录 后发表回答