Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Expecting EntityExistsException but getting DatabaseException (possible bug?)
Expecting EntityExistsException but getting DatabaseException (possible bug?) [message #829796] Mon, 26 March 2012 16:00 Go to next message
Shelli Orton is currently offline Shelli Orton
Messages: 73
Registered: September 2009
Member
Hi,

I am using Glassfish 3.1.1 and EclipseLink as my JPA provider. I have a GenericServiceBean that looks like this:

public class GenericServiceBean implements GenericService
{
    @PersistenceContext(unitName = "myDB")
    EntityManager em;

    private final Logger log = LoggerFactory.getLogger(GenericServiceBean.class);

    public GenericServiceBean()
    {
        // empty
    }

    public <T> T create(T t) throws IllegalArgumentException,
            PersistenceException, EntityExistsException
    {
        try
        {
            em.persist(t);
        }
        catch (IllegalArgumentException ex)
        {
            log.error("Caught IllegalArgumentException attempting to create "
                    + t, ex);
            throw ex;
        }
        catch (EntityExistsException ex)
        {
            log.warn("Entity already exists in the database - " + t);
            throw ex;
        }
        catch (PersistenceException ex)
        {
            log.error("Caught unexpected PersistenceException creating " + t,
                    ex);
            throw ex;
        }

        return t;
    }


My BatchService class extends the GenericServiceBean and does operations on a Batch entity class:

public class BatchService extends GenericServiceBean
{
    private final Logger logger = LoggerFactory.getLogger(BatchService.class);

    public BatchService()
    {
        // empty
    }

    public Batch create(final Batch batch)
    {
        logger.info("Attempting to insert batch: " + batch.getBatchId());
        return super.create(batch);
    }
}


Finally, I have a Servlet that uses the BatchService to insert new batches in the database (code snippet):

try
{
    this.batchService.create(dbBatch);
    log.info("Successfully inserted batch into database - batch ID: " + batchID);
}
catch(EntityExistsException ex)
{
    log.warn("Batch and/or MTA IDs already exist in the database - Batch ID: " + batchID);
    throw ex;
}
catch (PersistenceException ex)
{
    String message = "Error saving batch to database - Batch ID: " + batchID; 
    log.error(message);
    throw ex;
}
catch (Throwable t)
{
    String message = "Error saving batch to database - Batch ID: " + batchID; 
    log.error(message);
    throw new Exception (message, t);
}


When trying to insert a duplicate Batch into the database, instead of catching the EntityExistsException as I expected, I'm catching the Throwable. When looking at the Glassfish server logs, I see this:

[#|2012-03-26T13:23:23.197-0600|WARNING|glassfish3.1.1|org.eclipse.persistence.session.file:/opt/glassfishv3/glassfish/domains/domain1/applications/ESwimBatchReceiver-1.0-20120326.181321-19/WEB-INF/lib/eswim-data-model-1.0-20120326.181239-7.jar_eswim|_ThreadID=27;_ThreadName=Thread-2;|
Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '12345462-2279-4516-af7d-cf9716f7748a' for key 1
Error Code: 1062
Call: INSERT INTO BATCH (BATCH_ID, MESSAGE, STATUS, UPLOAD_DATE) VALUES (?, ?, ?, ?)
        bind => [4 parameters bound]
Query: InsertObjectQuery(BatchID=12345462-2279-4516-af7d-cf9716f7748a;Status=new;Message=null)
        at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:840)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:906)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:592)
        at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
        at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1702)


It appears that EclipseLink is throwing a vendor implementation specific exception instead of the JPA specified EntityExistsException. See attached file for full error logging (>400 lines).

According to a post on this StackOverflow question, this is likely a bug:

http://stackoverflow.com/questions/2519902/elegantly-handling-constraint-violations-in-ejb-jpa-environment/2522643#2522643

My questions are:

1. Is this a bug?
2. If so, has a bug report been created for it?
3. If not, how can I catch this in my code that tries to do the database insert? I want to do different actions for duplicates than I do for general exceptions.
  • Attachment: Log.txt
    (Size: 41.49KB, Downloaded 107 times)
Re: Expecting EntityExistsException but getting DatabaseException (possible bug?) [message #831954 is a reply to message #829796] Thu, 29 March 2012 11:13 Go to previous messageGo to next message
Shelli Orton is currently offline Shelli Orton
Messages: 73
Registered: September 2009
Member
I find it hard to believe that no one has encountered this issue before. Does no one else do any exception handling using EclipseLink?
Re: Expecting EntityExistsException but getting DatabaseException (possible bug?) [message #832088 is a reply to message #831954] Thu, 29 March 2012 14:58 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris Delahunt
Messages: 1016
Registered: July 2009
Senior Member
The log shows that the container is correctly throwing a javax.ejb.EJBException: "Transaction aborted" as it should - this will occur when the container commits the transaction as JPA providers are not required to throw exceptions on the persist call and can delay it until the transaction commits. Your code is not set up to handle the EJBException and unwrap the internal exeption (which will still be the EclipseLink DatabaseException though).

My understanding is that most people trying to handle the exceptions will wrap an entityManager.flush() call in a try/catch block to get the exception immediately rather than wait for the container to commit and handle the TransactionRollbackException . ie they would put em.flush() right after the persist call.

Please file a bug to have the beforeCompletion method invoked by JTA throw a PersistenceException instead of the DatabaseException, and vote for it.

Best Regards,
Chris
Re: Expecting EntityExistsException but getting DatabaseException (possible bug?) [message #832891 is a reply to message #832088] Fri, 30 March 2012 14:23 Go to previous message
Shelli Orton is currently offline Shelli Orton
Messages: 73
Registered: September 2009
Member
Bug created: https://bugs.eclipse.org/bugs/show_bug.cgi?id=375745

Others are also invited to vote for it!!
Previous Topic:Problem with LEFT JOIN and long field
Next Topic:@OrderColumn on inverse @ManyToMany + @JoinTable question
Goto Forum:
  


Current Time: Tue Jul 22 15:48:55 EDT 2014

Powered by FUDForum. Page generated in 0.01801 seconds