Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

org.hibernate.AssertionFailure

I am getting this strange error sometimes while my thread executes. What could this be related to?

2011-Jun-25 09:05:22,339 ERROR AssertionFailure:45 - an assertion failure occured (this             may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: null id in com.inrev.bm.bean.IRKeyWordTweet entry (don't flush the Session after an exception occurs)
    at         org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:78)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:187)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:143)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.inrev.bm.streaming.IRKeyWordStreaminThread.run(IRKeyWordStreaminThread.java:119)

My code for inserting,

    Transaction tx = null;
    Session session = sessionFactory.openSession();
    tx = session.beginTransaction();

    int count = 0;
    try
    {
        for (Iterator itrList = statusToInsert.iterator(); itrList.hasNext();) 
        {
            try 
            {
                IRecord record = (IRecord) itrList.next();
                session.save(record);
                count++;
                if ( count % 10 == 0 ) 
                { 
                    session.flush();
                    session.clear();
                    tx.commit();
                    tx = session.beginTransaction();
                }

            }
            catch (Exception e) 
            {
                tx.commit();
                session.close();
                session = sessionFactory.openSession();
                tx = session.beginTransaction();
                StringWriter sw = new StringWriter(); 
                PrintWriter pw = new PrintWriter(sw); 
                e.printStackTrace(pw); 
                log.error(sw.toString());
            }
        }
    }
    catch (Exception e) {
        StringWriter sw = new StringWriter(); 
        PrintWriter pw = new PrintWriter(sw); 
        e.printStackTrace(pw); 
        log.error(sw.toString());
    }
    finally {
        tx.commit();
        session.close();
    }

Regards,

Rohit

like image 463
sesmic Avatar asked Jun 25 '11 09:06

sesmic


2 Answers

The problem is that your code is handling an Exception, which is a bad, bad thing to do in 99.9% of the cases, and the following is happening:

One of the interactions with the session fails in the try block, and throws an exception. When this happens, the session is invalidated and cannot be used for absolutely anything as it's in an inconsistent state. But your code interacts with the session in the catch block, which triggers the assertion.

The only safe thing to do after an exception with the session, is to rollback the transaction and close it. Any other type of interaction will probably generate another exception (in this case an assertion exception).

like image 140
Augusto Avatar answered Nov 02 '22 22:11

Augusto


one use case that is not cleanly handled is a poller of some kind. If an application is setting some "in progress status" for a large background job, commits, then separate thread/http request/session polling, while an async background thread throws an exception, that async thread needs to be responsible to catch that exception and mark the status as "failed" on the thing the poller is polling. In this case its awkward b/c the session gets invalidated b/c of a low level hibernate exception. This seems to be a valid case to catch and handle exceptions.

Is the only work around to get a new session? Clean/standard way of doing that within a managed transaction env like Seam?

like image 28
Ben Maisano Avatar answered Nov 02 '22 22:11

Ben Maisano