users@glassfish.java.net

Glassfish, stubs and portability

From: <glassfish_at_javadesktop.org>
Date: Fri, 06 Jun 2008 17:26:13 PDT

A couple years back I asked a question about whether or not it is guaranteed that a stateless session bean's stub (the container-generated implementation of the remote business interface) is serializable and may be shipped between tiers. The answer was yes.

So that means among other things that you could if you were inclined include a remote reference to an SLSB in, for example, a data transfer object or an Entity that gets shipped to your application client. That's what I'm doing.

I somewhat dubiously took it one step further, and not surprisingly things went bang. What I did was to annotate the @Entity field storing that reference such that it would be stored in the database as a blob. So when the entity in question is stored into the database, the stub (the remote reference to the SLSB) is serialized and stored as well.

This works fine.

What does not work is when this entity is loaded via EntityManager#find(). I get a CORBA exception like this (the reference to my SLSB is at line five or so in the stack below):
[code]
org.omg.CORBA.BAD_OPERATION: The delegate has not been set! vmcid: 0x0 minor code: 0 completed: No
        at org.omg.CORBA.portable.ObjectImpl._get_delegate(ObjectImpl.java:53)
        at com.sun.corba.ee.spi.presentation.rmi.StubAdapter.getDelegate(StubAdapter.java:174)
        at com.sun.corba.ee.impl.presentation.rmi.bcel.BCELStubBase.selfAsBaseClass(BCELStubBase.java:214)
        at bricks.business.query.ntier.api.__QueryLogicDelegate_Remote_DynamicStub.writeReplace(bricks/business/query/ntier/api/__QueryLogicDelegate_Remote_DynamicStub.java)
        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.invokeWriteReplace(ObjectStreamClass.java:1032)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1107)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at com.sun.ejb.containers.RemoteBusinessWrapperBase.writeObject(RemoteBusinessWrapperBase.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:945)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1461)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
        at oracle.toplink.essentials.mappings.converters.SerializedObjectConverter.convertObjectValueToDataValue(SerializedObjectConverter.java:110)
        at oracle.toplink.essentials.mappings.foundation.AbstractDirectMapping.getFieldValue(AbstractDirectMapping.java:462)
        at oracle.toplink.essentials.mappings.foundation.AbstractDirectMapping.buildCloneValue(AbstractDirectMapping.java:172)
        at oracle.toplink.essentials.mappings.foundation.AbstractDirectMapping.buildClone(AbstractDirectMapping.java:160)
        at oracle.toplink.essentials.mappings.foundation.AbstractDirectMapping.buildBackupClone(AbstractDirectMapping.java:152)
        at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildBackupClone(ObjectBuilder.java:317)
        at oracle.toplink.essentials.descriptors.changetracking.DeferredChangeDetectionPolicy.buildBackupClone(DeferredChangeDetectionPolicy.java:178)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.populateAndRegisterObject(UnitOfWorkImpl.java:2866)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:687)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:167)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:105)
        at oracle.toplink.essentials.internal.queryframework.ExpressionQueryMechanism.checkCacheForObject(ExpressionQueryMechanism.java:682)
        at oracle.toplink.essentials.queryframework.ReadObjectQuery.checkEarlyReturnImpl(ReadObjectQuery.java:224)
        at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.checkEarlyReturn(ObjectLevelReadQuery.java:444)
        at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:575)
        at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:692)
        at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:746)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2248)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.findInternal(EntityManagerImpl.java:354)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.findInternal(EntityManagerImpl.java:330)
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerImpl.find(EntityManagerImpl.java:148)
        at com.sun.enterprise.util.EntityManagerWrapper.find(EntityManagerWrapper.java:546)
[/code]

It looks like not all the state of whatever the stub consists of is serialized (I'm guessing that something (the "delegate") is transient).

Is this a Glassfish bug, or something that I simply cannot rely on?

I tried to dig up the old post in this forum where ksaks, I believe, laid out the things that can and cannot be relied upon when speaking of remote business interface references to stateless session beans, but could not find it. A refresher would be most welcome since the specification does not spell any of them out.

Best,
Laird
[Message sent by forum member 'ljnelson' (ljnelson)]

http://forums.java.net/jive/thread.jspa?messageID=278922