views:

52

answers:

2

Hello,

I'll try and explain my problem as concisely and clearly as possible. I feel that what I'm trying might inherently be wrong, but somehow I believe it should work. So please feel free to treat this post as a mere clarification about the Serialization mechanism.

So, I have an Interface implemented by a class [it's implied they exist in separate files].

// ----- SomeInterface.java
public interface SomeInterface extends Serializable
{
    public void setMsg(String msg);
    public void printMsg();
}

// ----- SomeImpl.java
public class SomeImpl implements SomeInterface
{
    private String msg;
    public void setMsg(String msg)
    {
        this.msg = msg;
    }


    public void printMsg()
    {
        System.out.println("Msg is: " +msg);
    }

}

Now I serialize an instance of [tt]SomeImpl[/tt]class:

...
    public void SomeMethInSomeClass()
    { 
        FileOutputStream fos = new FileOutputStream(new File("c:/test.ser"));
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        SomeInterface si = new SomeImpl();

        si.setMsg("blah blah");
        oos.writeObject(test);

        oos.close();
        fos.close();
        System.out.println("------ done -------");
    }

Now in a separate project, I have a JAR of the application above which contains the interface SomeInterface, but not the implementation class SomeImpl. In this application if I try to do the following:

....
....
    public void deserialiserMethod() throws Exception
    {
        FileInputStream fis = new FileInputStream(new File("c:/test.ser"));
        ObjectInputStream ois = new ObjectInputStream(fis);
        SomeInterface si = null;

        System.out.println("------ reading ----------");
        si = (SomeInterface) ois.readObject();
        si.printMsg();
        System.out.println("------- done ----------");
        ois.close();
        fis.close();
    }
....

... I get a ClassNotFoundException [for SomeImpl]. Now I know that my other project does NOT have the SomeImpl class in its classpath. But shouldn't casting into a reference of the parent interface take care of that dependency?

thanks for your inputs!

+1  A: 

This isn't a question of casting, this is a question of the class type of the serialized object. It doesn't matter if your code never refers directly to the SomeImpl class, the fact remains that the serialized object is still of that type.

Consider this - what class would the deserialized object be an instance of, if not SomeImpl? The fields have to be defined somewhere, and if not in SomeImpl, then where?

Even if you were to deserialize the object and cast it to java.lang.Object, you'd have to the same problem of what the actual representation and runtime type of the object is.

skaffman
A: 

If the deserialising process doesn't have access to the class, you can't have an instance of it.

If the class is not loaded by the "latest" class loader used by the default ObjectInputStream implementation, you can supply a different class loaded elsewhere. Override ObjectInputStream.resolveClass to supply the class. Like RMI does, you can "annotate" the stream by overriding ObjectOutputStream.annotateClass to indicate where the class should be found.

Tom Hawtin - tackline
`resolveClass` and `annotateClass` look promising. i'll look into them. Thanks Tom!
anirvan