| Summary: | 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. | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | Edson Richter <edsonrichter> |
| Component: | Eclipselink | Assignee: | Project Inbox <eclipselink.orm-inbox> |
| Status: | CLOSED INVALID | QA Contact: | |
| Severity: | blocker | ||
| Priority: | P2 | CC: | tom.ware |
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | |||
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. 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? 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.
Sorry, TabelaFreteItem is marked with inheritance with JOINED strategy:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class TabelaFreteItem implements Serializable {
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. Does dynamic weaving works with Apache Tomcat 6? Regards, Edson. TomCat is not a Java EE provider, so I suggest using static weaving with it. 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) 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. 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. 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. 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. Setting target and priority. See the following page for the meanings of these fields: http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines 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 The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |
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.