Return-Path: Delivered-To: apmail-db-jdo-dev-archive@www.apache.org Received: (qmail 99665 invoked from network); 13 Jul 2005 00:50:16 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 13 Jul 2005 00:50:16 -0000 Received: (qmail 84611 invoked by uid 500); 13 Jul 2005 00:50:14 -0000 Mailing-List: contact jdo-dev-help@db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jdo-dev@db.apache.org Delivered-To: mailing list jdo-dev@db.apache.org Received: (qmail 84552 invoked by uid 99); 13 Jul 2005 00:50:13 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Jul 2005 17:50:13 -0700 X-ASF-Spam-Status: No, hits=0.1 required=10.0 tests=HTML_30_40,HTML_MESSAGE X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [192.18.98.34] (HELO brmea-mail-3.sun.com) (192.18.98.34) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 12 Jul 2005 17:50:10 -0700 Received: from fe2.sun.com ([192.18.108.79]) by brmea-mail-3.sun.com (8.12.10/8.12.9) with ESMTP id j6D0oA8t019788 for ; Tue, 12 Jul 2005 18:50:10 -0600 (MDT) Received: from conversion-daemon.fe2.sun.com by fe2.sun.com (Sun Java System Messaging Server 6.1 HotFix 0.02 (built Aug 25 2004)) id <0IJJ00801J2XQ700@fe2.sun.com> (original mail from Craig.Russell@Sun.COM) for jdo-dev@db.apache.org; Tue, 12 Jul 2005 18:50:10 -0600 (MDT) Received: from [192.168.0.10] ([24.6.172.77]) by fe2.sun.com (Sun Java System Messaging Server 6.1 HotFix 0.02 (built Aug 25 2004)) with ESMTPSA id <0IJJ00GIMJNLPYSC@fe2.sun.com> for jdo-dev@db.apache.org; Tue, 12 Jul 2005 18:50:10 -0600 (MDT) Date: Tue, 12 Jul 2005 17:50:14 -0700 From: Craig Russell Subject: Detachment contract To: JDO Expert Group Cc: jdo-tck-ext@Sun.COM, jdo-dev@db.apache.org Message-id: MIME-version: 1.0 X-Mailer: Apple Mail (2.730) Content-type: multipart/signed; protocol="application/pkcs7-signature"; boundary=Apple-Mail-63--972789449; micalg=sha1 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N --Apple-Mail-63--972789449 Content-Type: multipart/alternative; boundary=Apple-Mail-62--972790231 --Apple-Mail-62--972790231 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed 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! --Apple-Mail-62--972790231 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=ISO-8859-1 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=A0 = 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.=A0

DetachAll updates the = version information,=A0flushes 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.=A0DetachAll is mostly useful in = the beforeCompletion callback because of this behavior.=A0

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 =3D=3D null && = jdoDetachedState !=3D 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).=A0

The jdoDetachedState is an = Object[ ] that consists of:

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

The enhancer = implements

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

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

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.=A0If = 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!


= --Apple-Mail-62--972790231-- --Apple-Mail-63--972789449 Content-Transfer-Encoding: base64 Content-Type: application/pkcs7-signature; name=smime.p7s Content-Disposition: attachment; filename=smime.p7s MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGHjCCAtcw ggJAoAMCAQICAw3FWTANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt YWlsIElzc3VpbmcgQ0EwHhcNMDUwMTEwMDA0MTA5WhcNMDYwMTEwMDA0MTA5WjBHMR8wHQYDVQQD ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMSQwIgYJKoZIhvcNAQkBFhVDcmFpZy5SdXNzZWxsQFN1 bi5DT00wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDti7ZE4rO6oXKbLM02AG9WY55t udmBVL53fb3V3X5S1kvcJOk1NEMIYT/T7Ww+/hE955zvHT29+mIoNe8AW/yj1WUH8uGG2HxhwCHI UQTHmN/ioVJgjwUaYbtNMKbL/NRpnL0QWewdMJS+6IFzFyX7ADFW5cJ+UWNLvNeWAQtN0mtLildn vdOgh50i8YPvACNkCHoomGjXx0azcXbe1X3c5AgRI6e2CZe5k2lRFQFUMqkjdoMtQPoNqJ1BxH9l i4cnabl8mcTwHHl44hrvb8ThqwRf2pfJh2vVuwmgK6z4IWjOk4RQM+0ODsRdq67mBdimJYmPMK1p RMBHzrUsfKxNAgMBAAGjMjAwMCAGA1UdEQQZMBeBFUNyYWlnLlJ1c3NlbGxAU3VuLkNPTTAMBgNV HRMBAf8EAjAAMA0GCSqGSIb3DQEBBAUAA4GBAIj86LzxCHedStDLMEeqHLy+UFG7zIRHfChSIV42 +MvXicydXEBh8v0Ry1V2d/lY4jS78G5yW5R9fKt1U5nlRBCOVzdhomvSolnNRIT71wPVVDrAIVlA YpXKxSmVBq7+4hV+3ZLHDeq3qZnNmiJR0sTEUD16xZX1RJs9dRYPCHoRMIIDPzCCAqigAwIBAgIB DTANBgkqhkiG9w0BAQUFADCB0TELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTES MBAGA1UEBxMJQ2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMf Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFs IEZyZWVtYWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUuY29t MB4XDTAzMDcxNzAwMDAwMFoXDTEzMDcxNjIzNTk1OVowYjELMAkGA1UEBhMCWkExJTAjBgNVBAoT HFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25hbCBG cmVlbWFpbCBJc3N1aW5nIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEpjxVc1X7TrnK mVoeaMB1BHCd3+n/ox7svc31W/Iadr1/DDph8r9RzgHU5VAKMNcCY1osiRVwjt3J8CuFWqo/cVbL rzwLB+fxH5E2JCoTzyvV84J3PQO+K/67GD4Hv0CAAmTXp6a7n2XRxSpUhQ9IBH+nttE8YQRAHmQZ cmC3+wIDAQABo4GUMIGRMBIGA1UdEwEB/wQIMAYBAf8CAQAwQwYDVR0fBDwwOjA4oDagNIYyaHR0 cDovL2NybC50aGF3dGUuY29tL1RoYXd0ZVBlcnNvbmFsRnJlZW1haWxDQS5jcmwwCwYDVR0PBAQD AgEGMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFQcml2YXRlTGFiZWwyLTEzODANBgkqhkiG9w0B AQUFAAOBgQBIjNFQg+oLLswNo2asZw9/r6y+whehQ5aUnX9MIbj4Nh+qLZ82L8D0HFAgk3A8/a3h YWLD2ToZfoSxmRsAxRoLgnSeJVCUYsfbJ3FXJY3dqZw5jowgT2Vfldr394fWxghOrvbqNOUQGls1 TXfjViF4gtwhGTXeJLHTHUb/XV9lTzGCAucwggLjAgEBMGkwYjELMAkGA1UEBhMCWkExJTAjBgNV BAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25h bCBGcmVlbWFpbCBJc3N1aW5nIENBAgMNxVkwCQYFKw4DAhoFAKCCAVMwGAYJKoZIhvcNAQkDMQsG CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDUwNzEzMDA1MDE0WjAjBgkqhkiG9w0BCQQxFgQU dFMgMXyk7cVZ64fea5c1rMH3hzcweAYJKwYBBAGCNxAEMWswaTBiMQswCQYDVQQGEwJaQTElMCMG A1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNv bmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECAw3FWTB6BgsqhkiG9w0BCRACCzFroGkwYjELMAkGA1UE BhMCWkExJTAjBgNVBAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1Ro YXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBJc3N1aW5nIENBAgMNxVkwDQYJKoZIhvcNAQEBBQAEggEA p5kxJcBzqtjtz5aAjd/VnIJDCct45VjtmjDE3z92d+j+AaGnNg2Fu00FKOLrz2MQFREC0eHiKFNU cHXSAx+AxBJb5jEdlk/eJmWPzHjF/gKySSCn10JdB4gSjKRVjhCgrHb9fTSuvhbfuCI9/1aibOa6 lkWIo0epEUEIpMQ++htlEeTkM3DBekFyH67We9BegUnMIlBEfbBkmGe6G3sfAIkRFiABD+jfq8RY uxgoHsoiuVbafxn72KuZ66nh6rG44IDyCknNS10jMQ6yGOx36y6rprzk/ILMJ5NS4RM3jJR81vlj 0yM7OsFlgZ4i/9CVXW/51Vcc+ck+JgFp42DnygAAAAAAAA== --Apple-Mail-63--972789449--