[ https://issues.apache.org/jira/browse/LUCENE-1473?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Michael Busch updated LUCENE-1473: ---------------------------------- Attachment: custom-externalizable-reader.patch I really wouldn't want to add another backwards-compatibility requirement to Lucene, as the others already stated. Often in the past was ensuring backwards-compatibility the part of writing patches that took the longest and involved the most discussions. But maybe we can come up with a fair compromise here. What if we change the classes that currently implement Serializable, so that they implement Externalizable and add a suid as Jason suggests. But we make clear in the javadocs that we don't support backwards-compatiblity here, so e.g. a Term externalized with Lucene 2.9 can't be read with 3.0, only with 2.9. Then we add a new class CustomExternalizableReader to util: {code:java} public abstract class CustomExternalizableReader { public abstract void readExternal(Object obj, ObjectInput in) throws IOException, ClassNotFoundException; } {code} add a package-private, static variable of this type to a class that implements Externalizable and implement the deserialization code in a default instance of such a reader. This could look like this: {code:java} public class SomeClass implements Externalizable { private int one; private int two; ... static CustomExternalizableReader extReader = new CustomExternalizableReader() { public void readExternal(Object obj, ObjectInput in) throws IOException, ClassNotFoundException { SomeClass s = (SomeClass) obj; long uid = in.readLong(); if (uid != serialVersionUID) { throw new IOException("Wrong serialVerionUID: " + uid); } int one = in.readInt(); int two = in.readInt(); s.init(one, two); } }; // initialization method for readExternal void init(int one, int two) { this.one = one; this.two = two; } {code} Note that I also specified an init() method. Since both init() and extReader are both package-private, they are not protected by our backwards-compatibility policy and we can change them in any release. Now if in the next version of this class we add a new variable 'three' we have to change init() and the reader: {code:java} public class SomeClassNewVersion implements Externalizable { private int one; private int two; private int three; static final long serialVersionUID = 2L; public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { extReader.readExternal(this, in); } public void writeExternal(ObjectOutput out) throws IOException { out.writeLong(serialVersionUID); out.writeInt(one); out.writeInt(two); out.writeInt(three); } /** * This reader can only read the externalized format created with the same * version of this class. If backwards-compatibility is desired, a custom * reader has to be implemented. */ static CustomExternalizableReader extReader = new CustomExternalizableReader() { public void readExternal(Object obj, ObjectInput in) throws IOException, ClassNotFoundException { SomeClassNewVersion s = (SomeClassNewVersion) obj; long uid = in.readLong(); if (uid != serialVersionUID) { throw new IOException("Wrong serialVerionUID: " + uid); } int one = in.readInt(); int two = in.readInt(); int three = in.readInt(); s.init(one, two, three); } }; void init(int one, int two, int three) { this.one = one; this.two = two; this.three = three; } {code} Now if someone tries to deserialize an object that was written with an old Lucene version, an exception will be thrown. But the user can simply implement an own, backwards-compatible reader: {code:java} // Now the user implements their own backwards compatible reader SomeClassNewVersion.extReader = new CustomExternalizableReader() { public void readExternal(Object obj, ObjectInput in) throws IOException, ClassNotFoundException { SomeClassNewVersion c_new = (SomeClassNewVersion) obj; long uid = in.readLong(); int one = in.readInt(); int two = in.readInt(); int three; if (uid == 1) { // old version - initialze with default value three = -3; } else { // new version three = in.readInt(); } c_new.init(one, two, three); } }; {code} With this approach we have to clearly document in the javadocs the externalization format. Also if externalizable classes contain private inner classes that need to be serialized, then those inner classes have to be made package-private. The nice thing here is that we allow backwards-compatibility, but push the burden of maintaining it to the user. I coded this all up as an example that I'm attaching here. Let me know what you think, please. The patch file contains a Demo.java with a main method that demonstrates what I'm proposing here. > Implement standard Serialization across Lucene versions > ------------------------------------------------------- > > Key: LUCENE-1473 > URL: https://issues.apache.org/jira/browse/LUCENE-1473 > Project: Lucene - Java > Issue Type: Bug > Components: Search > Affects Versions: 2.4 > Reporter: Jason Rutherglen > Priority: Minor > Attachments: custom-externalizable-reader.patch, LUCENE-1473.patch, > LUCENE-1473.patch, LUCENE-1473.patch, LUCENE-1473.patch > > Original Estimate: 8h > Remaining Estimate: 8h > > To maintain serialization compatibility between Lucene versions, > serialVersionUID needs to be added to classes that implement > java.io.Serializable. java.io.Externalizable may be implemented in classes > for faster performance. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]