XStream
  1. XStream
  2. XSTR-77

Support for readResolve() for enum support

    Details

    • Type: New Feature New Feature
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 1.0.1
    • Component/s: Converters
    • Labels:
      None

      Description

      ------- From Chris Kelly ---------

      Normally for serializable enums, then you have a readResolve method so that at you can still use the == operator after deserialization as the local static constant replaces the deserialized one. However when I de-serialize a typesafe enum using XStream then the constants refer to differnt objects thus removing the benefit of using a typesafe constant in the first place. Is this a bug or am I misusing XStream?

      [I enclose a typical typesafe constant with unit tests for normal serialization and serialization using XStream)]

      Thanks for any suggestions in advance.

      public class Status implements Serializable, Comparable {

      private static int nextOrdinal = 0;
      private final int ordinal = nextOrdinal++;

      public static final Status STARTED = new Status("STARTED");

      public static final Status FINISHED = new Status("FINISHED");

      private static final Status[] PRIVATE_VALUES =

      {STARTED, FINISHED}

      ;

      public static final List VALUES = Collections.unmodifiableList(
      Arrays.asList(PRIVATE_VALUES));

      private final String name; // for debug only

      static final long serialVersionUID = 4931026467582637777L;

      private Status(String name)

      { this.name = name; }

      public String toString()

      { return name; }

      public int compareTo(Object o)

      { return ordinal - ((Status) o).ordinal; }

      private Object readResolve() throws ObjectStreamException

      { return PRIVATE_VALUES[ordinal]; //Canonicalize }

      }

      public void testReadResolveWithDefaultSerialization() {
      Status status = Status.STARTED;

      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      try

      { ObjectOutputStream os = new ObjectOutputStream(bout); os.writeObject(status); }

      catch (Exception e)

      { fail("Unable to serialize", e); }

      byte[] bArray = bout.toByteArray();
      Status rStatus = null;
      ObjectInputStream in = null;

      ByteArrayInputStream bin = new ByteArrayInputStream(bArray);

      try

      { in = new ObjectInputStream(bin); rStatus = (Status) in.readObject(); assertNotNull(rStatus); }

      catch (Throwable t)

      { fail("Unable to read de-serialize", t); }

      assertSame(status, rStatus);
      }

      public void testReadResolveWithXStream()

      { Status status = Status.STARTED; XStream xstream = new XStream(); xstream.registerConverter(new EncodedByteArrayConverter()); String xml = xstream.toXML(status); Status rStatus = (Status)xstream.fromXML(xml); assertSame(status, rStatus); }

      ----------- Extra Joe notes --------

      This should be easy to implement. ReflectionConverter can check for the existence of the method and if so, return that instead. Might cause an issue with circular references.

        People

        • Assignee:
          Unassigned
          Reporter:
          Joe Walnes
        • Votes:
          0 Vote for this issue
          Watchers:
          0 Start watching this issue

          Dates

          • Created:
            Updated:
            Resolved: