org.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)

I have a hibernate and JSF2 application going to the deployment server and suddenly throwing an org.hibernate.AssertionFailure: null id in exception. I will provide the stack trace and code immediately but here are four important issues first:

  1. This happens only on the deployment server (Jboss & MySql running on Windows Sever 2008.) It does not happen on my development machine (Tomcat and MySql running on Windoes 7 Pro) and also not on the staging environment (Jboss and MySql running on Linux.)

  2. Researching this, it seems that people get this error when trying to insert an object. But I get the error when I'm doing a simple query. (various different queries, actually, as the error pops up on several pages randomly.)

  3. The error hits only every now and then. If I do a Jboss restart it goes away, but a time later returns. Also, it's not consistent, on some clicks it's there, on others it's not. Even when it hits, when I do a simple refresh of the page it returns fine.

  4. I'm using c3p0 (config below)

Any idea what's going on?

The code details:

This happens on an address object. Here's the full hbm:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.idex.auctions.model">
<class name="Address" table="address" lazy="true">
  <id name="addressID" column="AddressID">
        <generator class="native"/>            
  </id>

  <property name="street" column="street"/> 
  <property name="city" column="city"/> 
  <property name="zip" column="zip"/> 
  <property name="state" column="state"/> 
  <property name="region" column="region"/> 
  <property name="country" column="country"/> 

  <many-to-one name="user" 
       class="com.idex.auctions.model.User" 
       column="userid" 
       unique="true" 
       cascade="save-update"/>
 </class> 
</hibernate-mapping>

The Java class is straight forward:

public class Address implements Serializable {
private static final long serialVersionUID = 7485582614444496906L;

private long addressID;
private String street;
private String city;
private String zip;
private String state;
private String region;
private String country;
private User user;

public Address() {

}
public long getAddressID() {
    return addressID;
}
public void setAddressID(long addressID) {
    this.addressID = addressID;
}
public String getStreet() {
    return street;
}
public void setStreet(String street) {
    this.street = street;
}
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getZip() {
    return zip;
}
public void setZip(String zip) {
    this.zip = zip;
}
public String getState() {
    return state;
}
public void setState(String state) {
    this.state = state;
}
public String getRegion() {
    return region;
}
public void setRegion(String region) {
    this.region = region;
}
public String getCountry() {
    return country;
}
public void setCountry(String country) {
    this.country = country;
}
public User getUser() {
    return user;
}
public void setUser(User user) {
    this.user = user;
}

}

The c3p0 configuration:

<property name="hibernate.c3p0.acquire_increment">1</property> 
<property name="hibernate.c3p0.idle_test_period">1000</property> 
<property name="hibernate.c3p0.max_size">20</property>  
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

The versions used are

hibernate3.jar

c3p0-0.9.1.2.jar

myfaces-api-2.1.4.jar

myfaces-impl-2.1.4.jar

mysql-connector-java-5.1.20-bin.jar

The full stacktrace

org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry 
    (don't flush the Session after an exception occurs)
org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(
                                          DefaultFlushEntityEventListener.java:78)
org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(
                                          DefaultFlushEntityEventListener.java:187)
org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(
                                          DefaultFlushEntityEventListener.java:143)
org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(
                                          AbstractFlushingEventListener.java:219)
org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(
                                          AbstractFlushingEventListener.java:99)
org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(
                                          DefaultAutoFlushEventListener.java:58)
org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:997)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1142)
org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
com.idex.auctions.manager.DatabaseManager.getAllObjects(DatabaseManager.java:464)
com.idex.auctions.ui.NavBean.gotoHome(NavBean.java:40)
sun.reflect.GeneratedMethodAccessor350.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:735)
javax.el.BeanELResolver.invoke(BeanELResolver.java:467)
javax.el.CompositeELResolver.invoke(CompositeELResolver.java:246)
org.apache.el.parser.AstValue.getValue(AstValue.java:159)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.getValue(
                                          ContextAwareTagValueExpression.java:96)
javax.faces.component._DeltaStateHelper.eval(_DeltaStateHelper.java:246)
javax.faces.component.UIOutcomeTarget.getOutcome(UIOutcomeTarget.java:50)
org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils.getOutcomeTargetHref(
                                          HtmlRendererUtils.java:1542)
org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.renderOutcomeLinkStart(
                                          HtmlLinkRendererBase.java:908)
org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.encodeBegin(
                                          HtmlLinkRendererBase.java:143)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:502)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:744)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:758)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:758)
org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(
                                    FaceletViewDeclarationLanguage.java:1900)
org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:285)
com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(
                                    PrettyViewHandler.java:163)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
org.apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(
                                    ResourceViewHandlerWrapper.java:93)
com.idex.auctions.ui.CustomViewHandler.renderView(CustomViewHandler.java:98)
org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:115)
org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:126)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:118)

Solution 1:

The exception:

org.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs)

Tells us that that the session exception has happened before the point where this org.hibernate.AssertionFailure is thrown.

To be exact, the org.hibernate.AssertionFailure is thrown when the session.flush() is happening, not the point where the error ocurred.

The above is a fact, thus a possible conclusion from it is: something could be suppressing the original exception.

So look for other possible points of error: A save() or saveOrUpdate() is possibly trying to persist an entity with a null field where, in the table, the column is NOT NULL?


TIP: To help in the debugging, try adding a session.flush() after every interaction with the Session object (e.g. session.save(obj), session.merge(obj), etc.), this will hopefully cause the org.hibernate.AssertionFailure to happen earlier, closer to where the real problem is taking place. (Of course, after the debugging, remove those session.flush().)


In my case, the real exception was taking place inside a try/catch {} block where the catch suppressed the exception (didn't rethrow or warn me about it).

Solution 2:

I would bet for a concurrency issue but it may occur at different levels:

  • a hibernate session may be shared between different users if the classical "open session in view" pattern is not properly implemented
  • an entity is shared between two user sessions because of improper hibernate cache settings
  • a JDBC connection is shared between two different hibernate session (less likely)

Apart from these potential sources of troubles, I would remove c3p0 (maybe just rumors...) as your stack already provides DataSource with connection pooling integrated with the transaction manager.