Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 336229 - Exception Description: Null or zero primary key encountered in unit of work clone [Tab.Frete Item ELEMTAXALOCAL: + para VARGEM BONITA/MG.], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
Summary: Exception Description: Null or zero primary key encountered in unit of work c...
Status: CLOSED INVALID
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P2 blocker with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-02-03 09:22 EST by Edson Richter CLA
Modified: 2022-06-09 10:08 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Edson Richter CLA 2011-02-03 09:22:48 EST
Build Identifier: 

Eclipselink throw the following error:

"Exception Description: Null or zero primary key encountered in unit of work clone [Tab.Frete Item ELEMTAXALOCAL: + para VARGEM BONITA/MG.], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property."


1) ELEMTAXALOCAL inherits TABELAFRETEITEM

2) DBMS is PostgreSQL 9.0.1

3) TabelaFreteItem declaration:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class TabelaFreteItem implements Serializable {
  private String DTYPE;


3) public field id declaration:

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  public Integer getId() {
    return id;
  }

5) TabelaFreteItemTaxaLocal object declaration:

@Entity
@Table( name = "ELEMTAXALOCAL" )
@DiscriminatorValue( value = "ELEMTAXALOCAL" )
public class TabelaFreteItemTaxaLocalidade extends TabelaFreteItem {

  public TabelaFreteItemTaxaLocalidade() {
    super();
    setDTYPE( "ELEMTAXALOCAL" );
  }

6) Object TabelaFrete has a list of TabelaFreteItem (that includes TabelaFreteItemTaxaLocalidade) like:

  @OneToMany( mappedBy = "tabelaFrete", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  @OrderBy( "criterioPesoDe, criterioValorDe, criterioCubagemDe" )
  public List<TabelaFreteItem> getTabelaFreteItems() {
    return tabelaFreteItems;
  }


6) To store the object, I do

EntityManager em = Util.getEM(); //it just request from EntityManagerFactory
EntityTransacton et = em.getTransation();
et.begin();
em.persist(tabelaFreteObj);
et.commit();
em.close();


7) The EclipseLink saves all the data, except the TabelaFreteItemTaxaLocalidade due the error (and user is loosing information):

"Exception Description: Null or zero primary key encountered in unit of work clone [Tab.Frete Item ELEMTAXALOCAL: + para VARGEM BONITA/MG.], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property."

8) This TabelaFreteItemTaxaLocalidade has special equals and hashCode implementations:
  @Override
  public boolean equals( Object object ) {
    if( object == null || !( object instanceof TabelaFreteItemTaxaLocalidade ) ) {
      return false;
    }
    if( object == this ) {
      return true;
    }

    TabelaFreteItemTaxaLocalidade other = (TabelaFreteItemTaxaLocalidade) object;

    if(other.getId()!=null && this.getId()!=null) {
      return ( other.getId().equals(this.getId()));
    }

    if((other.getId()==null && this.getId()!=null)
            || (other.getId()!=null && this.getId()==null)) {
      return false;
    }
    
    TabelaFrete thisT = getTabelaFrete();
    Localidade thisL = getLocalidade();
    TabelaFrete otherT = other.getTabelaFrete();
    Localidade otherL = other.getLocalidade();

    boolean b1 = (otherT==null && thisT==null) || (otherT == thisT) || (otherT!=null && otherT.equals(thisT));
    boolean b2 = (otherL==null && thisL==null ) || (otherL == thisL) || (otherL!=null && otherL.equals(thisL));
    return b1 && b2 && (sequencia==other.sequencia);
  }

  @Override
  public int hashCode() {
    int hash = 7;
    hash = 89 * hash + (this.localidade != null ? this.localidade.hashCode() : 0);
    hash = 89 * hash + this.sequencia;
    return hash;
  }


9) In persistente.xml I do have:

      <property name="eclipselink.cache.type.default"             value="Weak"/>
      <property name="eclipselink.cache.size.default"             value="50000"/>
      <property name="eclipselink.target-database"                value="PostgreSQL"/>
      <property name="eclipselink.id-validation"                  value="NULL"/>


Please help me to fix. This error occur only with this TabelaFreteItemTaxaLocalidade, all other 

Reproducible: Always

Steps to Reproduce:
Described in the "description" above.
Comment 1 Edson Richter CLA 2011-02-07 21:25:09 EST
I have to increase the importance. The system rollout is in risk if I cant fix the bug.

The problem occurs randomly, and is always related to "unit work clone primary key" of new objects that have inheritance, where primary keys can be zero.

User may loose data, or may duplicate information if suspect that data has not been saved (but it is!).

I really need your help on fixing this.

Regards,

Edson.
Comment 2 Tom Ware CLA 2011-02-08 10:06:50 EST
Can you please provide the full stack trace of the exception?

In the following code:

EntityManager em = Util.getEM(); //it just request from EntityManagerFactory
EntityTransacton et = em.getTransation();
et.begin();
em.persist(tabelaFreteObj);
et.commit();
em.close();

How is tabelaFreteObj created?  Is it new, or read from the DB?  What does it contain?  Are its tabelaFreteItems read from the DB?  Are they new?  How are they added?
Comment 3 Edson Richter CLA 2011-02-08 11:56:29 EST
TabelaFrete is a new object, received through RPC from GWT front end.

TabelaFrete.tabelaFreteItems is a List<TabelaFreteItem> with all new objects of kind ElemTaxaLocal and ElemTaxaColeta.

TabelaFreteItem is abstract class, with dtype defined, and inheritance with class per table. Id is defined here, and is Generated from Identity (actually is a default serial in postgresql table).

ElemTaxaLocal extends TabelaFreteItem, and has attribute ManyToOne with Localidade, plus few more discrete fields. ElemTaxaLocal has null primary key, since it is a new object - and I do expect that this object has a newly generated id from the database as defined in TabelaFreteItem id:

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  public Integer getId() {
    return id;
  }



Localidade is read from database, then transfered via RPC to the client and then received via RPC from the client. It has no generated value, neither zeroed primary key in database (it's varchar): 

  @Id
  @Column( length = 10 )
  public String getId() {
    return id;
  }

I'll try to get the stacktrace.

Seems that, for some reason, the backup and the clone objects are not considered equals... And this is throwing the error.

I suspect that it has something to do with GWT-RPC object transfer between client and server.

This is error is very hard to reproduce when runing on local network.


I'll appreciate your directions.
Comment 4 Edson Richter CLA 2011-02-08 12:49:05 EST
Sorry, TabelaFreteItem is marked with inheritance with JOINED strategy:


@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class TabelaFreteItem implements Serializable {
Comment 5 Tom Ware CLA 2011-02-08 13:14:45 EST
We have seen some issues in the past with serialization related to weaving.

If this is only occuring in a client server environment, you might want to ensure classes are weaved on both sides.  If your server is a JavaEE 5 or better server, weaving should be the default.  Depending on how your client is deployed, it may or may not be weaved by default.  You may need either to use the -javaagent argument, or statically weave your classes.

http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_%28ELUG%29#Using_EclipseLink_JPA_Weaving

Additionally, we have made some improvements to serialization of weaved classes in our 2.2 release which is about to release, so that may also be an option for you.

In any case, if are able to provide the full stacktrace of the exception it would be helpful.
Comment 6 Edson Richter CLA 2011-02-08 13:37:07 EST
Does dynamic weaving works with Apache Tomcat 6?

Regards,

Edson.
Comment 7 Tom Ware CLA 2011-02-08 13:50:09 EST
TomCat is not a Java EE provider, so I suggest using static weaving with it.
Comment 8 Tom Ware CLA 2011-02-08 13:51:57 EST
BTW: What are your deployment environments for the Server and for the Client?  (if neither allows weaving by default, our weaving issue should not affect you, but you might want to consider weaving due to performance benefit)
Comment 9 Edson Richter CLA 2011-02-08 13:59:14 EST
Development:

- Apache Tomcat 6.0.30
- JRockit JDK 1.6.0.20 32 bit for Windows
- Windows 7 64bit

Production:
- Apache Tomcat 6.0.30
- JRockit JDK 1.6.0.20 32 bit for Linux
- Linux Ubuntu 10 LTS 32bit

The error happens with more frequency on Linux than on Windows. I can't guess why.
I don't use Lazy loading (never), since I'll in trouble at GWT side.
All relations that are default LAZY are explicity defined as EAGER.
Comment 10 Tom Ware CLA 2011-02-08 14:26:24 EST
With the configuration above, you are not getting weaving by default on either the client or the server side.

The exception above is thrown when we have calculated a set of changes for an object that has an empty ID and we do not think that object is new.

Is there any chance you are explicitly setting the id to something other than NULL?

Is there any chance your .equals method is returning true for two objects that are not actually equal?  If so, this could result in us thinking an object is not null.
Comment 11 Tom Ware CLA 2011-02-08 14:33:38 EST
correction:

Is there any chance your .equals method is returning true for two objects that
are not actually equal?  If so, this could result in us thinking an object is
not NEW.
Comment 12 Edson Richter CLA 2011-02-08 14:46:40 EST
I just finished to write a method that goes recursively in all method of an object or a collection of objects, then identify my OneToOne and ManyToOne, then replaces for fresh objects obtained with "em.find(Class, pk)".

That seems to have solved the problem. Don't know why. I'll give a day in production, and let you know.

Sorry for not being able to help more on the research, but I'm on pressure since application is in production and users are complaining.

Interestingly, it is very hard to reproduce the problem in development enviroment.

I do believe it's something related to GWT RPC setting something "null" in the serialization/deserialization process (may be an hidden exception!).

Tomorrow I'll provide more information on my evolution.

Thanks,

Edson.
Comment 13 Tom Ware CLA 2011-02-18 10:25:03 EST
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 14 Edson Richter CLA 2011-02-18 11:36:29 EST
Dear all,

I took too long for me to answer your last question.

To make a test, I just completely removed the "equals" and "hashcode" specific implementations (that means, by now I'm using Object.equals and Object.hashcode implementations), and the problem vanished.

Nevertheless, I would like also to warn that this happens only after upgrading from 1.2 to 2.0, so something that would affect my objects happened by that time.
Also, I don't see this behavior on Hibernate and OpenJPA implementations.

Since I do use most advanced Eclipselink cache management specific code in my project, I'm blocked to make Eclipselink as an optional and let users to choose among other implementations.

I do propose to make this an invalid bug report.

I'll keep an eye open on this bug, and if I face it again, then I'll reopen this issue.

Thanks for your effort on helping me with this issue, and sorry for taking your time.

Elicpselink is a great project - I would like to thank your all for your great work.

Kind regards,

Edson Richter
Comment 15 Eclipse Webmaster CLA 2022-06-09 10:08:15 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink