db-jdo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig Russell <Craig.Russ...@Sun.COM>
Subject Detachment contract
Date Wed, 13 Jul 2005 00:50:14 GMT
Javadogs,

Here's a summary of what I'm thinking for the detachment contract.  
I'll have a formal proposal as a spec update shortly.

Please comment if you have objections to the basic ideas.

There is a difference between Detachable and non-detachable classes.  
Detachable classes are not serialization-compatible with their un- 
enhanced original classes. This is a good thing, as it disallows  
confusion. Non-binary-compatible implementations need to have their  
own strategy for doing detachment.

Serialization creates detached instances. The jdoPreSerialize method  
makes the instance suitable to be detached. The actual detachment  
happens "automatically" when the serialized instance loses its  
jdoStateManager and jdoFlags fields because they are transient.  
DetachCopy also creates detached  instances. Implementations can use  
the same algorithm for detachCopy as for serialization and then just  
copy the fields (except for jdoStateManager and jdoDetachedState) to  
the detached instance.

DetachAll updates the version information, flushes the cache, creates  
detached instances or transient instances for every managed instance  
in the cache, and clears the cache. No changes made to the objects  
after the DetachAll method are reflected in the current transaction.  
DetachAll is mostly useful in the beforeCompletion callback because  
of this behavior.

Serializing or detachCopy-ing a non-Detachable PC instance creates a  
transient instance in the output, just like JDO 1. This leads to  
predictable results in case the PC instance is the value of a  
persistent field in a detached instance and the detached instance is  
attached. But I think that this should be allowed since we know if  
the field has been changed while detached, and it might be what the  
user expects.

Allowing detached instances to have a non-null jdoStateManager field  
would change the JDO1 serialization contract, so we should not allow  
it. This does constrain an implementation to require recognizing the  
detached state without having a state manager.

This is the algorithm:

jdoIsDetached() {
return jdoStateManager == null && jdoDetachedState != null;

Since there is never a state manager for a detached instance we don't  
need to delegate to the state manager for the answer. And we don't  
need sm.isDetached(PersistenceCapable).

The jdoDetachedState is an Object[ ] that consists of:

{
Object objectId,
Object version,
BitSet loadedFields,
BitSet modifiedFields
}

The enhancer implements

Object jdoGetVersion() {
   if (jdoStateManager != null) return jdoStateManager.getVersion(this);
   try {
     return (jdoDetachedState == null)?null:jdoDetachedState[1];
   } catch (Exception ex) {
     throw new JDOFatalInternalException(msg.msg 
("EXC_IllegalDetachedState", ex);
   }
}

Object jdoGetObjectId() {
   if (jdoStateManager != null) return jdoStateManager.getObjectId 
(this);
   try {
     return (jdoDetachedState == null)?null:jdoDetachedState[0];
   } catch (Exception ex) {
     throw new JDOFatalInternalException(msg.msg 
("EXC_IllegalDetachedState", ex);
   }
}

PersistenceManager flags determine the behavior for detachment,  
regardless of whether the detachment is due to serialization or  
explicit detachCopy.

get/setDetachmentOptions(int flags). The standard values are:
public final static DETACH_LOAD_FIELDS
public final static DETACH_UNLOAD_FIELDS

The LOAD_FIELDS flag specifies that the fetch plan in effect at the  
time the object is detached determines the fields that must be loaded  
(fetched from the datastore and marked as loaded) in the detached  
instances. If this flag is not set, then the fields in the fetch plan  
might be loaded or not depending on when the instances were fetched.

The UNLOAD_FIELDS flag specifies that the fetch plan in effect at the  
time the object is detached determines the fields that must be  
unloaded (set to their Java default values and marked as not loaded)  
in the detached instances. If this flag is not set, then the fields  
not in the fetch plan might be loaded or not depending on when the  
instances were fetched.

Detachable classes that implement writeObject and readObject pose a  
problem. The JVM standard serialization will include the  
jdoDetachedState field because it is known to the VM. If the  
writeObject delegates to the standard, this is fine. If not, the  
jdoDetachedState field will not be written. So the enhancer checks  
that the user's writeObject delegates to the out.defaultWriteObject()  
and if it does not, inserts a call to write the jdoDetachedState  
instance ahead of the rest of the object in the output stream. The  
readObject method is similarly changed to read the state of the  
jdoDetachedState field.

Similarly, if the class implements Externalizable, the enhancer adds  
the code to the readExternal and writeExternal methods to handle the  
jdoDetachedState field.

The jdoFlags value DETACHED is not used and will be removed from the  
interface.

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Mime
View raw message