Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / February 2006

Tip: Looking for answers? Try searching our database.

Final field & custom serialized format

Thread view: 
Ian Pilcher - 13 Feb 2006 04:55 GMT
I have a class which has a single field:

   private final File nameFile;

When serializing it, I want to save it as a String, rather than a File.
This will allow me to better check for platform incompatibilities during
deserialization.

I can serialize it like so:

   private transient final File nameFile;

   private void writeObject(ObjectOutputStream out) throws IOException
   {
    out.defaultWriteObject();
       out.writeObject(nameFile.getPath());
   }

A straightforward approach to deserialization won't work, however, for
the obvious reason that I won't be able to set nameFile to the File I
construct from my deserialized String.

I can't be the first person to run into this.  What have others done in
this situation?

Thanks!

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

Ian Pilcher - 13 Feb 2006 06:30 GMT
> A straightforward approach to deserialization won't work, however, for
> the obvious reason that I won't be able to set nameFile to the File I
> construct from my deserialized String.

Talking to myself again.  One answer seems to be the use of writeReplace
and readResolve, although they come with a lot of caveats.

(Can anyone think of a reason why readResolve should have an access
modifier other than private?)

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

Chris Uppal - 13 Feb 2006 13:34 GMT
> (Can anyone think of a reason why readResolve should have an access
> modifier other than private?)

In case a subclass wants to say:
   if (...)
       return super.readResolve();
perhaps ?  Or so that you can write tests for your objects' implementations of
the serialisation protocol independently of the complexities of the real
serialisation code ?

   -- chris
Thomas Hawtin - 13 Feb 2006 14:08 GMT
>>A straightforward approach to deserialization won't work, however, for
>>the obvious reason that I won't be able to set nameFile to the File I
>>construct from my deserialized String.
>
> Talking to myself again.  One answer seems to be the use of writeReplace
> and readResolve, although they come with a lot of caveats.

That seems to be the answer from the JMM list.

http://www.cs.umd.edu/~pugh/java/memoryModel/archive/1636.html

> (Can anyone think of a reason why readResolve should have an access
> modifier other than private?)

pre-1.5 type-safe enums. If you subclass for certain constants, then you
probably don't want to repeat the readResolve method. Much the same goes
for anywhere where the base class is peers with a fixed set of
subclasses. I suppose where creation is done through a static creation
method.

If you are coding for both J2ME and J2SE, then you can't put
serialisation code in J2ME classes. Subclassing every class is not on.
What you can do is insert serialisation base classes on different
sourcepaths for J2ME and J2SE.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Chris Uppal - 13 Feb 2006 13:22 GMT
> I have a class which has a single field:
>
>     private final File nameFile;
>
> When serializing it, I want to save it as a String, ...

Perhaps a simple solution would be adequate for you

class XXX
{
   private final String fileName;
   private transient File namedFile;
   //...
}

and rebuild namedFile lazily, or in a custom de-serialisation step, according
to your taste.

Or -- even simpler -- don't make namedFile final.  After all, your design calls
for changing it !

   -- chris
Ian Pilcher - 13 Feb 2006 15:05 GMT
> Perhaps a simple solution would be adequate for you
>
[quoted text clipped - 4 lines]
>     //...
> }

Yeah.  Actually playing with writeReplace and readResolve for a while, I
slapped myself and did the following:

   private final File nameFile;

   private void writeObject(ObjectOutputStream out) throws IOException
   {
       out.defaultWriteObject();
       out.writeObject(nameFile.getPath());
   }

   private void readObject(ObjectInputStream in)
           throws IOException, ClassNotFoundException
   {
       in.defaultReadObject();
       String savedPath = (String)in.readObject();

       if (!savedPath.equals(nameFile.getPath()) ||
               nameFile.getParent() != null)
       {
           throw new InvalidObjectException(savedPath +
                   ": not compatible with this platform");
       }
   }

nameFile contains a single element of a pathname, either a "prefix" or a
name.  It is properly final, since a single element is immutable.  I use
a File, rather than a String, so that I can compare element names and
let the File class worry about the rules of the platform on which I'm
running.

By saving it's original name, I can check that the File serialization/
deserialization doesn't change it's name (\ --> / for example).  I also
check that the name doesn't contain anything that's interpreted as a
directory separator on the current platform.  Linux allows backslashes
in file names, for example.

Signature

========================================================================
Ian Pilcher                                        i.pilcher@comcast.net
========================================================================

P.Hill - 14 Feb 2006 05:28 GMT
>>Perhaps a simple solution would be adequate for you
>>
[quoted text clipped - 6 lines]
>
> Yeah.  Actually playing with writeReplace and readResolve for a while, I
[...]
> slapped myself and did the following:
[...]
>     private void readObject(ObjectInputStream in)
>             throws IOException, ClassNotFoundException
[quoted text clipped - 5 lines]
>                 nameFile.getParent() != null)
>         {

Hmm, nameFile is null at this point is it not? Thus
I'm not sure this is a general solution.  You weren't reading
from a serialization from before changing the definition to
transient where you?

But if you find you miss created something and you could recover
by creating some new version of an XXX, you can create a new class XXX
by using a private constructor within readObject().

HTH,
-Paul
tom fredriksen - 13 Feb 2006 13:56 GMT
> I can't be the first person to run into this.  What have others done in
> this situation?

You could try the library xstream, which de-/serialises from/into xml.
The result would be a bit larger than pure a string or binary version,
but it would be very portable and for-/backwards compatible.

/tom
Roedy Green - 13 Feb 2006 15:52 GMT
On Sun, 12 Feb 2006 22:55:22 -0600, Ian Pilcher
<i.pilcher@comcast.net> wrote, quoted or indirectly quoted someone who
said :

>A straightforward approach to deserialization won't work, however, for
>the obvious reason that I won't be able to set nameFile to the File I
>construct from my deserialized String.

It is not obvious why.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.