Skip to main content

Ejb3 Entity graph serialization problem?

12 replies [Last post]
kjozsa
Offline
Joined: 2007-01-27

These happen on both SJSAS 9.1_02 and Glassfish v2ur2 with the default JPA provider (toplink and toplink essentials I believe):

I have two ejb3 entities, EntityA having a unidirectional ManyToOne relationship to EntityB. My DAO ejb3 slsb loads a list of EntityA-s with a select, and logs out all EntityA.getEntityB().getSomeProperty() which has the correct not-null value. After the log message, I return the List to the caller.

From an other EAR I do a remote EJB call to the DAO mentioned and log the results. All EntityA.getEntityB().getSomeProperty() calls return null now. EntityA.getEntityB() has the class type of EntityB (does not appear to be a proxy), but all properties inside EntityB are null which were correctly set in the DAO as logged right before returning the results.

Trying to narrow down the problem, I replaced the entityManager call loading the list of results with plain object creation (new ArrayList() etc) to get rid of any possible Toplink magic. The problem still exists, appearently serializing a List fails silently with EntityA.getEntityB() being all null inside. Replacing EntityA and EntityB with plain POJOs (not entity beans anymore) make the problem disappear.

What's going on here?

Thanks,
Kristof

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kjozsa
Offline
Joined: 2007-01-27

Anyone?

kjozsa
Offline
Joined: 2007-01-27

I have a completely isolated sandbox-demo of the problem clearly showing a weaved JPA entity losing all its properties upon a remote call serialization.

I'm willing to share the code to anyone interested, but it needs a couple of steps setting it up (including building/deploying with maven and creating a JavaDB pool on glassfish).

kjozsa
Offline
Joined: 2007-01-27

Description of the problem:

When calling from an other EAR on the same appserver, returning an
ejb3 entity bean from a remote ejb call which has a many-to-one lazy
reference makes all the entity's properties be null at the caller
point.

Steps to reproduce:

0. Install Glassfish v2ur2 or Sun Appserver 9.1 (verified on both) and Maven 2
1. prepare the JPA resources:
asadmin create-jdbc-connection-pool \
--datasourceclassname org.apache.derby.jdbc.EmbeddedDataSource \
--property databaseName=\$\{com.sun.aas.instanceRoot\}/databases/eartest:\
connectionAttributes=\;create\\=true \
eartest
asadmin ping-connection-pool eartest
asadmin create-jdbc-resource --connectionpoolid=eartest jdbc/eartest

2. unpack the demo projects hold in eartest-ejb3weaving.tgz
3. do 'mvn install' in all 4 projects in that order: eartest-called,
eartest-called-ear, eartest-called, eartest-caller-ear
4. do 'mvn asadmin:deploy' in eartest-called-ear and eartest-caller-ear
5. do a HTTP GET on http://localhost:8080/eartest-caller
6. check your appserver's server.log file, the entity called
LazyAddress will show its properties being null

Note:

The problem is *not* about an entity's lazy and not fetched property
being null out of the transaction boundaries. The entity's lazy
property is correctly prefetched before returning, but the problem
even exists if the entity is created with the new operator before
returning.

mvatkina
Offline
Joined: 2005-04-04

Can you attache the ear file(s) that you deploy? 'mvn install' called in the first directory downloads too many dependencies, but still fails to resolve 3 artifacts:
Missing:
----------
1) com.sun.jmx:jmxri:jar:1.2.1
2) javax.jms:jms:jar:1.1
3) com.sun.jdmk:jmxtools:jar:1.2.1

-marina

kjozsa
Offline
Joined: 2007-01-27

Please fetch them from these links yourself:
http://ond.vein.hu/~dyn/eartest-called-ear-1.0-SNAPSHOT.ear
http://ond.vein.hu/~dyn/eartest-caller-ear-1.0-SNAPSHOT.ear

They are around 8.5Mb each, I couldn't upload them here.

kjozsa
Offline
Joined: 2007-01-27

Additionally, these does not happen if the same remote call is made from the same EAR. If the caller is packaged in a separate EAR as the called bean, the problem exists.

mvatkina
Offline
Joined: 2005-04-04

Can it be that you have transient modifiers somewhere? Can it be that you have different versions of your entities in 2 EARs?

thanks,
-marina

kjozsa
Offline
Joined: 2007-01-27

I have no transient modifiers in my code, nor different versions of my classes anywhere. I even modified the serialVersionUid in the entity to make sure of this.

chris_delahunt
Offline
Joined: 2005-07-06

Hello,

This problem sounds odd, as entities are really just POJO's. What is stranger is that I would expect that the A->B relationship is null, not that B would be populated with nulls. It is almost like all your data has been marked transient and so is lost during serialization. Can you try sending just the B entity across and see if you still lose your data?

Also, please post the A and B entities (or a subset just so we can get an idea of the mappings and what is going missing).

Best Regards,
Chris

kjozsa
Offline
Joined: 2007-01-27

Good suggestions, Chris. We successfully narrowed the problem: serializing a List containing a single EntityB object fails silently, the List still holds EntityB but all it's properties are null. This only happens if EntityB refers to EntityC with a ManyToOne FetchType.LAZY mapping. (The ejb call was a remote one but the entity was created via new Entity() before the return).

Is that a known serialization problem?

dawebsterup
Offline
Joined: 2008-09-08

With lazy fetching the referential entities only get populated when actually used. If you do not "use" them before returning the list they will be null. You may have to walk your list and call the Set (the nested collection containing the many side of your relationship) with a .size() or such to indicate a "use". Otherwise do not use lazy fetching.

kjozsa
Offline
Joined: 2007-01-27

I'm pretty much familiar with lazy fetching, dynamic proxies, their relation with transaction boundaries and so on. In this case serializing a manually created single entity with a potential lazy relationship which is set to null makes all the entity's other properties become null on the other side of the remote ejb call. This still looks like a user error?