Menu

PM Closed (error)/ Forcibly closing PM(warn)

Help
chopras
2007-08-09
2013-04-15
  • chopras

    chopras - 2007-08-09

    Hi,

    I'm posting from my get() method below. 

        this.pm_ = pmf.getPersistenceManager();
        Collection objColl = null;
        Collection returnColl = new ArrayList();
            Transaction tx = pm_.currentTransaction();
            Query q = null;
        try{
                tx.begin(); //xact boundary begins here

                .....
                objColl = (Collection) q.execute();
            returnColl.addAll(objColl);
                q.close(objColl);
                tx.commit(); //commit, xact boundary ends here
            }finally
            {
                //make sure to rollback the transaction if still active
                if(tx.isActive())
                    tx.rollback();
        }
        //pm_.close();
            return returnColl;

    In the code above, if I comment out pm_.close() I get a warning here:
    WARN  [com.triactive.jdo.PersistenceManagerImpl] Forcibly closing com.triactive.jdo.PersistenceManagerImpl
    com.triactive.jdo.PersistenceManagerNotClosedException: The PersistenceManager allocated at this point was never closed.

    If I uncomment the line above, I get the following error:
    javax.jdo.JDOFatalUserException: Persistence manager has been closed

    Any way I can avoid the warning and the error?

    Note that this warning was never occuring with MySQL; I only discovered the warning with SQL Server 2005

     
    • Heiko Busch

      Heiko Busch - 2007-08-09

      Hi,

      I would place the pm_.close() line at the end of the finally branch.

      Best regards
      Heiko

       
    • chopras

      chopras - 2007-08-09

      I tried placing the pm_close() line at the end of the finally branch and it made no difference.  I still get the javax.jdo.JDOFatalUserException: Persistence manager has been closed ERROR. 

      I even tried placing the pm_.close() inside an if statement that only closes the persistence manager if it's not already closed.  The log indicated that the if block is entered indicating that the persistence manager is not yet closed; yet when I try to close the persistence manager, I get the ERROR above.

      Any suggestions?

       
      • Mike Martin

        Mike Martin - 2007-08-09

        Your method returns persistent objects to its caller, who presumably uses them.
        You can't use persistent objects whose PersistenceManager has been closed.

        The lifetime of the PM either has to span over all the code that will use the
        persistent objects, or your query method needs to return objects which are
        not persistent.  There are typically two ways of handling the latter:

        1.  Use "value object" classes, and return value objects instead of persistent
            objects.

        2.  Make sure the persistent objects are fully loaded into memory
            (pm.retrieve()) and then transition them to transient (pm.makeTransient()).
            Then they're no longer persistent and no longer tied to a PM.  Note that if
            you do this the objects lose their JDO identity.

        In JDO 2.0 they've introduced methods to "detach" objects from a PM and later
        "reattach" them to a different one.  It works much like makeTransient() except
        the objects don't lose their identity.

        I very much want to upgrade TJDO to support JDO 2.0, but it's been hard to find
        the time.  I have added most of the new JDO 2.0 Query features though.

        HTH,

        Mike

         
    • chopras

      chopras - 2007-08-09

      Hi Mike,

      I very much appreciate your help over the past few weeks!

      If I'm understanding you correctly, the returnColl object that is returned at the end of the method is a persistent object.  One of your suggestions is to make returnColl a non persistent object.

      Regarding pm.retrieve and pm.transient, am I use to these methods to load returnColl completely into memory and then transition it to transient, and finally pass it back at the end of the method. 

      Could you confirm the above, and provide an example.  That would be great.

      Thanks...

       
      • Mike Martin

        Mike Martin - 2007-08-09

        returnColl is not itself persistent, but the objects returned by the Query are
        persistent and you return them in the collection.

        The makeTransient approach would look something like this:

            Collection objColl = (Collection)q.execute();

            for (Object obj : objColl)
            {
                pm.retrieve(obj);
                pm.makeTransient(obj);
                returnColl.add(obj);
            }

        Mike

         
    • chopras

      chopras - 2007-08-09

      Mike,

      Could you expand on what you meant by "objects losing their JDO identity" above if one uses retrieve/makeTransient way.  I tried the method above but I'm getting a null pointer exception in my JSP code where I access the object returned. 

      Thanks..

       
      • Mike Martin

        Mike Martin - 2007-08-09

        chopras wrote:
        > Could you expand on what you meant by "objects losing their JDO identity"
        > above if one uses retrieve/makeTransient way.

        After pm.makeTransient(obj), JDOHelper.getObjectId(obj) == null.  Also
        see section 5.5.1 of the JDO spec:

            http://tjdo.sourceforge.net/docs/jdo101.pdf

         
    • chopras

      chopras - 2007-08-09

      I'm posting my new get() method here.  As suggested, I used the retrieve and transient method calls before copying over the objects to returnColl.  Nonetheless, I'm still getting a null pointer exception.  Any ideas?
        
              this.pm_ = pmf_.getPersistenceManager();
          Collection objColl = null;
          Collection returnColl = new ArrayList();
              Transaction tx = pm_.currentTransaction();
              Query q = null;
          try{
                  tx.begin(); //xact boundary begins here

                  ...
                  objColl = (Collection) q.execute();
              //returnColl.addAll(objColl);
              for (Iterator it = objColl.iterator(); it.hasNext(); )
              {
                  Object obj = it.next();
              pm_.retrieve(obj);
              pm_.makeTransient(obj);
              returnColl.add(obj);
              }       
                  q.close(objColl);
                  tx.commit(); //commit, xact boundary ends here
          }finally
              {
                  //make sure to rollback the transaction if still active
                  if(tx.isActive())
                      tx.rollback();
              pm_.close();
          }
          //pm_.close();
              return returnColl;

       
      • Mike Martin

        Mike Martin - 2007-08-09

        I think you'll need to pursue the NullPointerException to the source based
        on its stack trace.

         
    • chopras

      chopras - 2007-08-09

      Sorry to split this over two, please see above: I am  not really performing any other operations on "obj" beyond adding it over to "returnColl". 

       

Log in to post a comment.