persistence@glassfish.java.net

Re: jpa TopLink java.lang.NoSuchMethodError: _toplink_get when OneToOne is Lazy

From: christopher delahunt <christopher.delahunt_at_oracle.com>
Date: Tue, 19 Aug 2008 08:59:05 -0400

Could you be hitting bug 2546?
  https://glassfish.dev.java.net/issues/show_bug.cgi?id=2546

if so, the workarounds are to move the annotations to the properties, or
to mark the Tbl1ID ManyToOne in Tbl2 as lazy.

Best Regards,
Chris

tiberiu wrote:
> Hi All,
> I found a bug in Oracle TopLink used with Glassfish. JPA Model is destroyed
> when using OneToOne Lazy Connections.
>
> Soft:
> Netbeans 6.1, Glassfish-v2ur2 (came together with Netbeans)
> Database:mysql
>
> Here is Db Model:
>
> create table tbl1 (
> ID INTEGER AUTO_INCREMENT NOT NULL primary key
> );
>
> create table tbl2 (
> ID INTEGER AUTO_INCREMENT NOT NULL primary key,
> tbl1ID INTEGER not null
> );
>
> create table tbl3 (
> ID INTEGER AUTO_INCREMENT NOT NULL primary key,
> tbl2ID INTEGER not null,
> UNIQUE KEY `uk_tbl2ID` (`tbl2ID`)
> );
>
> alter table tbl2 add constraint fk_tbl1_tbl2 foreign key (tbl1ID) references
> tbl1(ID);
> alter table tbl3 add constraint fk_tbl2_tbl3 foreign key (tbl2ID) references
> tbl2(ID);
>
> insert into tbl1 values(null);
> insert into tbl2 values(null,1);
> insert into tbl3 values(null,1);
>
> I create an Ejb Project, the Annotated Entities look like that (see package
> db in uploaded File):
> Tbl1:
> @OneToMany(fetch=FetchType.LAZY, mappedBy = "tbl1ID")
> private Collection<Tbl2> tbl2Collection;
> Tbl2:
> @OneToOne(mappedBy = "tbl2ID", fetch=FetchType.LAZY)
> private Tbl3 tbl3;
> @JoinColumn(name = "tbl1ID", referencedColumnName = "ID")
> @ManyToOne
> private Tbl1 tbl1ID;
> Tbl3:
> @JoinColumn(name = "tbl2ID", referencedColumnName = "ID", unique=true,
> nullable=false, updatable = false)
> @OneToOne
> private Tbl2 tbl2ID;
>
> So, Tbl2 said has a one2one Connection with Tbl3, loading it lazily.
>
> Now here is the Business Logic of the Ejb (package dummy in zip):
> public void dummy() {
> Logger log = Logger.getLogger(DummyBean.class.getName());
>
> log.info("Sp1");
> Tbl1 tbl1 = em.find(Tbl1.class, 1);
> log.info("Sp1 after read");
> for(Tbl2 tbl2 : tbl1.getTbl2Collection()) {
> log.info("Sp2 tbl2.id=" + tbl2.getId());
> log.info("Sp3:" + tbl2.getTbl3());
> log.info("Sp4:" + tbl2.getTbl1ID());
> }
> log.info("Sp End");
> }
>
>
> I am calling the Ejb Remote.
> The Result is the following:
>
>
> Sp1
> db.Tbl2 actually got transformed
> TopLink, version: Oracle TopLink Essentials - 2.0.1 (Build b04-fcs
> (04/11/2008))
> Server: unknown
> Detected Vendor platform:
> oracle.toplink.essentials.platform.database.MySQL4Platform
> connecting(DatabaseLogin(
> platform=>DatabasePlatform
> user name=> ""
> connector=>JNDIConnector datasource name=>null
> ))
> Connected:
> jdbc:mysql://localhost:3306/tib?zeroDateTimeBehavior=convertToNull
> User: root_at_localhost
> Database: MySQL Version: 5.0.45-community-nt-log
> Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.5 (
> Revision: ${svn.Revision} )
> connecting(DatabaseLogin(
> platform=>MySQL4Platform
> user name=> ""
> connector=>JNDIConnector datasource name=>null
> ))
> Connected: .......
> SELECT ID FROM tbl1 WHERE (ID = ?)
> bind => [1]
> Sp1 after read
> SELECT ID, tbl1ID FROM tbl2 WHERE (tbl1ID = ?)
> bind => [1]
> Sp2 tbl2.id=1
> SELECT ID, tbl2ID FROM tbl3 WHERE (tbl2ID = ?)
> bind => [1]
> Sp3:null
> EJB5018: An exception was thrown during an ejb invocation on [DummyBean]
> javax.ejb.EJBException
> at
> com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:3869)
> at
> com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3769)
> at
> com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3571)
> at
> com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1354)
> at
> com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1316)
> at
> com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:210)
> at
> com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:117)
> at $Proxy140.dummy(Unknown Source)
> 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
> com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:154)
> at
> com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:687)
> at
> com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:227)
> at
> com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1846)
> at
> com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1706)
> at
> com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1088)
> at
> com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:223)
> at
> com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:806)
> at
> com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:563)
> at
> com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2567)
> at
> com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
> Caused by: java.lang.NoSuchMethodError:
> db.Tbl2._toplink_gettbl1ID()Ldb/Tbl1;
> at db.Tbl2.getTbl1ID(Tbl2.java:62)
> at dummy.DummyBean.dummy(DummyBean.java:33)
> 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
> com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1067)
> at
> com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:176)
> at
> com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2895)
> at
> com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:3986)
> at
> com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:203)
> ... 17 more
>
> So it says "Caused by: java.lang.NoSuchMethodError:
> db.Tbl2._toplink_gettbl1ID()Ldb/Tbl1;" that means Tbl2 hasn't a Link to its
> Parent Tbl1.
> I tried to run an Ejb Client also with
> -javaagent:/..../glassfish-v2ur2/lib/toplink-essentials-agent.jar but I got
> the same result.
>
> If I delete the "fetch=FetchType.LAZY" in Tbl2 the Code it works:
> Sp1
> TopLink, version: Oracle TopLink Essentials - 2.0.1 (Build b04-fcs
> (04/11/2008))
> Server: unknown
> Detected Vendor platform:
> oracle.toplink.essentials.platform.database.MySQL4Platform
> connecting(DatabaseLogin(
> platform=>DatabasePlatform
> user name=> ""
> connector=>JNDIConnector datasource name=>null
> ))
> Connected:
> jdbc:mysql://localhost:3306/tib?zeroDateTimeBehavior=convertToNull
> User: root_at_localhost
> Database: MySQL Version: 5.0.45-community-nt-log
> Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.5 (
> Revision: ${svn.Revision} )
> connecting(DatabaseLogin(
> platform=>MySQL4Platform
> user name=> ""
> connector=>JNDIConnector datasource name=>null
> ))
> Connected: ....................
> SELECT ID FROM tbl1 WHERE (ID = ?)
> bind => [1]
> Sp1 after read
> SELECT ID, tbl1ID FROM tbl2 WHERE (tbl1ID = ?)
> bind => [1]
> SELECT ID, tbl2ID FROM tbl3 WHERE (tbl2ID = ?)
> bind => [1]
> Sp2 tbl2.id=1
> Sp3:null
> Sp4:db.Tbl1[id=1]
> Sp End
>
> I hope it will be a fix... it is quite important Lazy Loading :)
>
> http://www.nabble.com/file/p19048060/toplink_one2one_bug_java.zip
> toplink_one2one_bug_java.zip
>