-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: JBoss: NonUniqueObjectException trashes EntityManager
PostPosted: Wed Nov 14, 2007 10:53 am 
Newbie

Joined: Wed Nov 14, 2007 10:23 am
Posts: 5
Location: Brooklyn, NY
I have a stateless session bean which parses and loads content from an XML file into a database. The document structure gets parse like so:

Code:
foreach section
    load descriptive data into descriptive table
    foreach alternate ID
        load base, alternate ID into mapping table
    done
    foreach dated entry
         load dated information into calendar
     done
done


The problem I'm encountering is that, sometimes, the XML file will contain a duplicate entry in an section, e.g., the "alternate ID" part above. I have a "plain" Hibernate application which works fine, using an explicit session and transaction boundaries with rollbacks like this:

Code:
String code = n.selectSingleNode("id");
List<Element> altCodeList = n.selectNodes("keys/alt_id");
for (Element altCode : altCodeList) {
    CodeMapEntry cme = new CodeMapEntry();
    cme.setCode(code);
    cme.setAltCode(altCode.getText());
    if ("".equals(cme.getAltCode())) {
        continue;
    }
    try {
        session.saveOrUpdate(cme);
    } catch (NonUniqueObjectException nue) {
        log.warn("duplicate mapping entry " + cme + ", only one will be saved");
    }
}


When I moved this to JBoss, I broke the code into methods which handle each piece with annotations describing the transaction, like this:

Code:
@PersistenceContext(unitName="dcs") private EntityManager manager;
...
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void loadMapEntry(String code, String altCode) {
    CodeMapEntry cme = new CodeMapEntry();
    cme.setCode(code);
    cme.setAltCode(altCode);
    if ("".equals(altCode)) {
        return;
    }

    try {
        manager.persist(exex);
    } catch (PersistenceException pe) {
        if (pe.getCause() instanceof NonUniqueObjectException) {
            log.warn("duplicate mapping entry " + cme + ", only one will be saved");
        } else {
            throw(pe);
        }
    }
}


The problem is that the exception, even the NonUniqueObjectException, seems to invalidate the EntityManager. This is documented in the EntityManager documentation (Hibernate 3.1 beta7 PDF):
Quote:
If the EntityManager throws an exception (including any SQLException), you should immediately rollback the database transaction, call EntityManager.close() (if createEntityManager() has been called) and discard
the EntityManager instance. Certain methods of EntityManager will not leave the persistence context in a consistent state. No exception thrown by an entity manager can be treated as recoverable. Ensure that the EntityManager will be closed by calling close() in a finally block. Note that a container managed entity manager will do that for you. You just have to let the RuntimeException propagate up to the container.


Once the exception is thrown, even the one I catch and try to ignore, the next call to manager.persist() throws "javax.persistence.TransactionRequiredException: EntityManager must be access within a transaction". This call is in the next method (in my pseudocode, the section processing the dated entries) which is also marked a REQUIRES_NEW.

My question is, how do I recover and continue with the rest of the file?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.