[ 
https://issues.apache.org/jira/browse/OPENJPA-2613?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

DORE updated OPENJPA-2613:
--------------------------
    Issue Type: Question  (was: Bug)

> findByPrimaryKey error on EJB CMP with composite primary key
> ------------------------------------------------------------
>
>                 Key: OPENJPA-2613
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-2613
>             Project: OpenJPA
>          Issue Type: Question
>          Components: jpa, kernel
>    Affects Versions: 2.4.0
>         Environment: apache-tomee-plus-1.7.2
>            Reporter: DORE
>
> Hello Openjpa community,
> I'm trying to get working a cmp ejb entity with a composite primary key.
> I know I can get this sample running with a simple Integer type as primary 
> key, but some of cmp ejb have composite pk, so I want to test it. (not just 
> for fun, I have some ejb oin this case !)
> create, findAll, customer finders are ok, but I encounter problem on 
> findByPrimaryKey:
> {code}
> java.rmi.RemoteException: The bean encountered a non-application exception; 
> nested exception is: 
>       <openjpa-2.4.0-r422266:1674604 nonfatal user error> 
> org.apache.openjpa.persistence.ArgumentException: The given value 
> "fr.chronopost.ejb.esd.customer.interfaces.CustomerPK@1" cannot be converted 
> into an identity for "class 
> openejb.fr.chronopost.ejb.esd.customer.server.CUSTOMER".  The value is the 
> wrong type (fr.chronopost.ejb.esd.customer.interfaces.CustomerPK).
>       at 
> org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException(EjbTransactionUtil.java:155)
>       at 
> org.apache.openejb.core.cmp.CmpContainer.findByPrimaryKey(CmpContainer.java:702)
>       at 
> org.apache.openejb.core.cmp.CmpContainer.invoke(CmpContainer.java:269)
>       at 
> org.apache.openejb.server.ejbd.EjbRequestHandler.doEjbHome_FIND(EjbRequestHandler.java:445)
>       at 
> org.apache.openejb.server.ejbd.EjbRequestHandler.processRequest(EjbRequestHandler.java:198)
>       at 
> org.apache.openejb.server.ejbd.EjbDaemon.processEjbRequest(EjbDaemon.java:344)
>       at org.apache.openejb.server.ejbd.EjbDaemon.service(EjbDaemon.java:240)
>       at org.apache.openejb.server.ejbd.EjbServer.service(EjbServer.java:86)
>       at 
> org.apache.openejb.server.httpd.ServerServlet.service(ServerServlet.java:58)
>       at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
>       at 
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
>       at 
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
>       at 
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
>       at 
> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
>       at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
>       at 
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
>       at 
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
>       at 
> org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
>       at 
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
>       at 
> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
>       at 
> org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
>       at 
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
>       at 
> org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
>       at 
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
>       at java.lang.Thread.run(Thread.java:662)
> Caused by: <openjpa-2.4.0-r422266:1674604 nonfatal user error> 
> org.apache.openjpa.persistence.ArgumentException: The given value 
> "fr.chronopost.ejb.esd.customer.interfaces.CustomerPK@1" cannot be converted 
> into an identity for "class 
> openejb.fr.chronopost.ejb.esd.customer.server.CUSTOMER".  The value is the 
> wrong type (fr.chronopost.ejb.esd.customer.interfaces.CustomerPK).
>       at 
> org.apache.openjpa.kernel.BrokerImpl.newObjectId(BrokerImpl.java:1311)
>       at 
> org.apache.openjpa.kernel.DelegatingBroker.newObjectId(DelegatingBroker.java:315)
>       at 
> org.apache.openjpa.persistence.EntityManagerImpl.find(EntityManagerImpl.java:485)
>       at 
> org.apache.openejb.persistence.JtaEntityManager.find(JtaEntityManager.java:180)
>       at 
> org.apache.openejb.core.cmp.jpa.JpaCmpEngine.loadBean(JpaCmpEngine.java:163)
>       at 
> org.apache.openejb.core.cmp.CmpContainer.findByPrimaryKey(CmpContainer.java:688)
>       ... 25 more
> Caused by: java.lang.Exception: java.lang.ClassCastException: 
> fr.chronopost.ejb.esd.customer.interfaces.CustomerPK cannot be cast to 
> java.lang.Number
>       at 
> org.apache.openjpa.util.Exceptions.replaceNestedThrowables(Exceptions.java:254)
>       at 
> org.apache.openjpa.persistence.ArgumentException.writeObject(ArgumentException.java:106)
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>       at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>       at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>       at java.lang.reflect.Method.invoke(Method.java:597)
>       at 
> java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:940)
>       at 
> java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1469)
>       at 
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
>       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
>       at 
> java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
>       at 
> java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
>       at 
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
>       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
>       at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
>       at 
> org.apache.openejb.client.ThrowableArtifact.writeExternal(ThrowableArtifact.java:57)
>       at 
> java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1429)
>       at 
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1398)
>       at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
>       at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
>       at 
> org.apache.openejb.client.EJBResponse.writeExternal(EJBResponse.java:186)
>       at 
> org.apache.openejb.server.ejbd.EjbRequestHandler.processResponse(EjbRequestHandler.java:303)
>       at 
> org.apache.openejb.server.ejbd.EjbDaemon.processEjbResponse(EjbDaemon.java:356)
>       at org.apache.openejb.server.ejbd.EjbDaemon.service(EjbDaemon.java:269)
>       ... 20 more
> {code}
> {code:title=ejb-jar.xml|borderStyle=solid}
> <enterprise-beans>
>       <entity>
>               <description>
>                       This bean represents customer
>               </description>
>               <ejb-name>CustomerEJB</ejb-name>
>               
> <home>fr.chronopost.ejb.esd.customer.interfaces.CustomerHome</home>
>               
> <remote>fr.chronopost.ejb.esd.customer.interfaces.CustomerRemote</remote>
>               
> <ejb-class>fr.chronopost.ejb.esd.customer.server.CustomerBean</ejb-class>
>               <persistence-type>Container</persistence-type>
>               
> <prim-key-class>fr.chronopost.ejb.esd.customer.interfaces.CustomerPK</prim-key-class>
>               <reentrant>false</reentrant>
>               <cmp-version>2.x</cmp-version>
>               <abstract-schema-name>CUSTOMER</abstract-schema-name>
>               <cmp-field>
>                       <field-name>id</field-name>
>               </cmp-field>
>               <cmp-field>
>                       <field-name>name</field-name>
>               </cmp-field>
>               <cmp-field>
>                       <field-name>birthdate</field-name>
>               </cmp-field>
>               <cmp-field>
>                       <field-name>sssNo</field-name>
>               </cmp-field>
>               <cmp-field>
>                       <field-name>address</field-name>
>               </cmp-field>
>               <cmp-field>
>                       <field-name>annualSalary</field-name>
>               </cmp-field>
>               <cmp-field>
>                       <field-name>loanAmount</field-name>
>               </cmp-field>
>               <primkey-field>id</primkey-field> 
>               <query>
>                       <query-method>
>                               <method-name>findBySssNo</method-name>
>                               <method-params>
>                                       
> <method-param>java.lang.String</method-param>
>                               </method-params>
>                       </query-method>
>                       <ejb-ql>select distinct object(o) from CUSTOMER o where 
> o.sssNo = ?1</ejb-ql>
>               </query>
>               <query>
>                       <query-method>
>                               <method-name>findAll</method-name>
>                               <method-params />
>                       </query-method>
>                       <ejb-ql>select distinct object(o) from CUSTOMER 
> o</ejb-ql>
>               </query>
>       </entity>
> </enterprise-beans>
> </ejb-jar>
> {code}
> {code:title=openejb-jar.xml|borderStyle=solid}
> <?xml version="1.0" encoding="UTF-8"?>
> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1";
>       xmlns:nam="http://geronimo.apache.org/xml/ns/naming-1.1"; 
> xmlns:pkgen="http//www.openejb.org/xml/ns/pkgen-2.0"
>       xmlns:sec="http://geronimo.apache.org/xml/ns/security-1.1"; 
> xmlns:sys="http://geronimo.apache.org/xml/ns/deployment-1.1";>
>       <cmp-connection-factory>
>               <resource-link>ejbPool_esd</resource-link>
>       </cmp-connection-factory>
>       <enterprise-beans>
>               <entity>
>                       <ejb-name>CustomerEJB</ejb-name>
>          
>                       <table-name>CUSTOMER</table-name>
>                       <cmp-field-mapping>
>                               <cmp-field-name>id</cmp-field-name>
>                               <table-column>id</table-column>
>                       </cmp-field-mapping>
>                       <cmp-field-mapping>
>                               <cmp-field-name>name</cmp-field-name>
>                               <table-column>name</table-column>
>                       </cmp-field-mapping>
>                       <cmp-field-mapping>
>                               <cmp-field-name>birthdate</cmp-field-name>
>                               <table-column>birthdate</table-column>
>                       </cmp-field-mapping>
>                       <cmp-field-mapping>
>                               <cmp-field-name>sssNo</cmp-field-name>
>                               <table-column>sss_no</table-column>
>                       </cmp-field-mapping>
>                       <cmp-field-mapping>
>                               <cmp-field-name>address</cmp-field-name>
>                               <table-column>address</table-column>
>                       </cmp-field-mapping>
>                       <cmp-field-mapping>
>                               <cmp-field-name>annualSalary</cmp-field-name>
>                               <table-column>annual_salary</table-column>
>                       </cmp-field-mapping>
>                       <cmp-field-mapping>
>                               <cmp-field-name>loanAmount</cmp-field-name>
>                               <table-column>loan_amount</table-column>
>                       </cmp-field-mapping>
>                       <query>
>                               <query-method>
>                                       <method-name>findBySssNo</method-name>
>                                       <method-params>
>                                               
> <method-param>java.lang.String</method-param>
>                                       </method-params>                        
>                 
>                               </query-method>
>                               <ejb-ql>SELECT OBJECT(c) FROM CUSTOMER as c 
> where c.sssNo = ?1</ejb-ql>
>                       </query>
>                       <query>
>                               <query-method>
>                                       <method-name>findAll</method-name>
>                                       <method-params />
>                               </query-method>
>                               <ejb-ql>SELECT OBJECT(c) FROM CUSTOMER as 
> c</ejb-ql>
>                       </query>
>               </entity>
>       </enterprise-beans>
> </openejb-jar>
> {code}
> {code:title=CustomerPK.java|borderStyle=solid}
> public class CustomerPK implements java.io.Serializable, Comparable {
>       public Integer id;  
>       
>       public CustomerPK() {
>       }
>       public CustomerPK(Integer id) {
>                this.id = id;
>       }
>        
>       public boolean equals(Object obj) {
>               boolean ret = false;
>               if (obj == null || !(obj instanceof CustomerPK))
>                       ret = false;
>               else if (obj == this)
>                       ret = true;
>               else if ((((CustomerPK) obj).id).compareTo(id) == 0)
>                       ret = true;
>               return ret;
>       }
>       public int hashCode() {
>               return id.hashCode();
>       }
>       public int compareTo(Object obj) {
>               return ((CustomerPK) obj).id.compareTo(id);
>       }
> }
> {code}
> {code:title=CustomerRemote.java|borderStyle=solid}
> public interface CustomerRemote extends EJBObject {
>       
>       public void setName(String name) throws RemoteException;
>       public String getName() throws RemoteException;
>       
>       public void setSssNo(String sssNo) throws RemoteException;
>       public String getSssNo() throws RemoteException;
>       
>       public void setAddress(String address) throws RemoteException;
>       public String getAddress() throws RemoteException;
>       
>       public void setBirthdate(Date birthdate) throws RemoteException;
>       public Date getBirthdate() throws RemoteException;
>       
>       public void setAnnualSalary(Double annualSalary) throws RemoteException;
>       public Double getAnnualSalary() throws RemoteException;
>       
>       public void setLoanAmount(Double loanAmount) throws RemoteException;
>       public Double getLoanAmount() throws RemoteException;
> }
> {code}
> {code:title=CustomerRemote.java|borderStyle=solid}
> public interface CustomerHome extends EJBHome {
>       public CustomerRemote create(Integer id,String name,Date 
> birthdate,String sssNo,String address, Double annualSalary,Double loanAmount) 
> throws CreateException,RemoteException;
>       
>       public CustomerRemote create(CustomerPK primaryKey)throws 
> CreateException,RemoteException;
>       public CustomerRemote findByPrimaryKey(CustomerPK pk) throws 
> FinderException, RemoteException;
>       public Collection findAll() throws FinderException, RemoteException;
>       public CustomerRemote findBySssNo(String sssNo) throws FinderException, 
> RemoteException;
> }
> {code}
> {code:title=...and here the test sample|borderStyle=solid}
> ...
> CustomerHome home = ...
> ...
> // create is OK
> home.create(new java.lang.Integer(11), "name", new java.util.Date(), "123", 
> "address", new Double(2.0), new Double(2.0));                     
> // findAll is OK
> Collection col = home.findAll(); 
> System.out.println("col.size=" + col.size());
> for (Iterator iterator = col.iterator(); iterator.hasNext();) {
>       Object object = (Object) iterator.next();
>       CustomerRemote remote = (CustomerRemote) object;
>       System.out.println(remote.getPrimaryKey() + " // " +  remote.getName() 
> + " / " + remote.getAddress());
>                       }
> // customer finder is OK too
> CustomerRemote cr =  home.findBySssNo("123");
> System.out.println(cr.getPrimaryKey() + " // " + cr.getName() + " / " + 
> cr.getAddress());
> // but findByPrimaryKey throws an exception !! (see stacktrace)
> CustomerPK pk0 = new CustomerPK();
> pk0.id = new Integer(11);
> CustomerRemote remote =  home.findByPrimaryKey(pk0);
> System.out.println(remote.getPrimaryKey() + " // " + remote.getName() + " / " 
> + remote.getAddress());
> ...
> {code}
> EDIT: ok, I found the problem: firstable, I have to remove in ejb-jar.xml:
>       <primkey-field>id</primkey-field> 
> And, in my primary key class, when I create an entity, container throws a 
> NullPointerExc.
> So, what is a correct implementation for hashCodeMethod ?
> I thought this one was a classic way:
> {code}        
> public int hashCode() {
>       return id.hashCode();
> }
> {code}
> But throws NPException, so the version below bypasses the problem:
> {code}        
> public int hashCode() {
>       if (id == null) {
>               id = new Integer(0);
>       }
>       return id.hashCode();
> }
> {code}
> What do you think of this implementation? 
> Is it a correct analysis ? 



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to