title: ClassCastException when Appending Object OutputStream
body: <p>I have been trying to do a little project that needs an appendable ObjectOutputStream.
  I have gone through a couple of solutions and i found <a href="https://stackoverflow.com/questions/1194656/appending-to-an-objectoutputstream">this</a> It seemed to solve my problem at first. But on further development of my project i started getting unexpected exceptions.
  The following are my classes.</p>
  
  <pre><code>public class PPAccount implements Serializable
  {
      private Profile profile;
      private String email;
      private float accountBal;
      private boolean isActivated;
      private String activationCode;
      private ArrayList&lt;Transaction&gt; transactions;
  
      //a few functions   
  }
  public class PPRestrictedAccount extends PPAccount {
      private String parentEmail;
      private float withdrawLimit;
  
          //a few functions
  }
  public class PPBusinessAccount extends PPAccount {
      private ArrayList &lt;PPRestrictedAccount&gt; accountOperators;
  
          //a few functions
  }
  public class PPStudentAccount extends PPAccount {
      private String parentEmail;
  
          //a few functions
  }
  </code></pre>
  
  <p>What i have observed is, using the <a href="https://stackoverflow.com/questions/1194656/appending-to-an-objectoutputstream">this</a> i have overridden the ObjectOutputStream and used it while i am appending the objects to the file. But what happens is if i write:</p>
  
  <p><code>PPBusinessAccount</code> first, repeat any number of times... then write <code>PPAccount</code> all is well.
  <code>PPAccount</code> first, repeat.... then write <code>PPBusinessAccount</code> then write <code>PPAccount</code>, it writes well but while reading i get a <code>ClassCastException</code>.</p>
  
  <p>I am tried reading the Objects and storing them directly in an instance of <code>Object</code> class to avoid the class cast but still <code>readObject()</code> throws <code>ClassCastException</code>.</p>
  
  <p>I tried best to describe my scenario, tell if you don't get anything. Why is this happening?? has it got something to do with the header that it is writing for this first time?? Along the lines of Base class header cannot support child class?? What's the turn around?</p>
  
  <p>I am doing the cast like this:</p>
  
  <pre><code>Object o = ois.readObject();        //Surprisingly exception is raised here (line:50 in DataStore)
  PPAccount ppa = (PPAccount)o;
  </code></pre>
  
  <p>The stack trace</p>
  
  <pre><code>java.lang.ClassCastException: java.lang.String cannot be cast to java.io.ObjectStreamClass
      at java.io.ObjectInputStream.readClassDesc(Unknown Source)
      at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
      at java.io.ObjectInputStream.readClassDesc(Unknown Source)
      at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
      at java.io.ObjectInputStream.readObject0(Unknown Source)
      at java.io.ObjectInputStream.readObject(Unknown Source)
      at java.util.ArrayList.readObject(Unknown Source)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at java.io.ObjectStreamClass.invokeReadObject(Unknown Source)
      at java.io.ObjectInputStream.readSerialData(Unknown Source)
      at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
      at java.io.ObjectInputStream.readObject0(Unknown Source)
      at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
      at java.io.ObjectInputStream.readSerialData(Unknown Source)
      at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
      at java.io.ObjectInputStream.readObject0(Unknown Source)
      at java.io.ObjectInputStream.readObject(Unknown Source)
      at in.msitprogram.iiit.paypal.persistance.DataStore.lookupAccount(DataStore.java:50)
      at in.msitprogram.iiit.paypal.persistance.DataStore.writeAccount(DataStore.java:131)
      at in.msitprogram.iiit.paypal.console.PPNewAccountScreen.show(PPNewAccountScreen.java:78)
      at in.msitprogram.iiit.paypal.console.MainMenu.show(MainMenu.java:42)
      at in.msitprogram.iiit.paypal.PPSystem.main(PPSystem.java:17)
  Exception in thread "main" java.lang.NullPointerException
      at in.msitprogram.iiit.paypal.persistance.DataStore.lookupAccount(DataStore.java:66)
      at in.msitprogram.iiit.paypal.persistance.DataStore.writeAccount(DataStore.java:131)
      at in.msitprogram.iiit.paypal.console.PPNewAccountScreen.show(PPNewAccountScreen.java:78)
      at in.msitprogram.iiit.paypal.console.MainMenu.show(MainMenu.java:42)
      at in.msitprogram.iiit.paypal.PPSystem.main(PPSystem.java:17)
  </code></pre>
  
  <p>The <code>lookUpAccount</code> reads from the stream while <code>writeAccount</code> writes to the stream, here is the code:</p>
  
  <pre><code>public static PPAccount lookupAccount(String email) throws IOException, ClassNotFoundException 
      {
          PPAccount account = null; //initialize it after reading from file
          // write code to open the files, read
          PPAccount foundAccount=null;
          ObjectInputStream ois=null;
          FileInputStream fis=null;
          File ff = new File(PPConstants.AllAccountDetails);
          if(!ff.exists())
          {
              //System.out.println("Required file not found");
              return null;
          }
          try
          {
              fis=new FileInputStream(PPConstants.AllAccountDetails);
              ois = new ObjectInputStream(fis);
              while(fis.available()&gt;0 &amp;&amp; foundAccount==null)
              {
                  //Object o=null;
                  PPAccount ppa=null;
                  try
                  {
                      ppa = (PPAccount)ois.readObject();
                      if(ppa==null)
                          return null;
                      System.out.println(ppa);
                  }
  
                  catch(ClassCastException cce)
                  {
                      System.out.println("Class cast exception "+cce.getCause());
                      cce.printStackTrace();  
                  }
                  if(email.equals(ppa.getEmail()))
                  {
                      foundAccount=ppa;
                      break;
                  }
                  if(ppa instanceof PPBusinessAccount)
                  {
                      PPBusinessAccount ppba = (PPBusinessAccount)ppa;
                      ArrayList&lt;PPRestrictedAccount&gt; alist=ppba.getAccountOperators();
                      if(alist==null)
                          continue;
                      Iterator&lt;PPRestrictedAccount&gt; it = alist.iterator();
                      while(it.hasNext())
                      {
                          PPRestrictedAccount ppr=(PPRestrictedAccount) it.next();
                          System.out.println(ppr);
                          if(email.equals(ppr.getEmail()))
                          {
                              foundAccount = ppr;
                              break;
                          }
                      }//iterators while loop
                  }//if it is a businessAccount
              }//outer while  
          }//try
          finally
          {
              if(ois!=null)
                  ois.close();
              if(fis!=null)
                  fis.close();
          }   
          return foundAccount;
      }
      public static void writeAccount(PPAccount account,Boolean append) throws IOException, ClassNotFoundException, DuplicateAccountException
      {
          ObjectOutputStream oos=null;
          FileOutputStream fos=null;
          try
          {
              if(!append)
              {
                  fos= new FileOutputStream(PPConstants.AllAccountDetails);
                  oos = new ObjectOutputStream(fos);
                  //System.out.println("Not Appending");
                  oos.writeObject(account);
              }
              else
              {
                  File ff = new File(PPConstants.AllAccountDetails);
                  if(!ff.exists())
                  {
                      System.out.println("Required file not found");
                      return;
                  }
                  PPAccount aa=lookupAccount(account.getEmail());
                  if(aa!=null)
                      throw new DuplicateAccountException("An Account already exits with this email-ID");
                  oos = new AppendingObjectOutputStream(new FileOutputStream(PPConstants.AllAccountDetails,append));
                  oos.writeObject(account);
              }
          }
          finally
          {
              if(oos!=null)
                  oos.close();
              if(fos!=null)
                  fos.close();
          }
  
      }
  </code></pre>