Dave,

I've sent you some unit tests offlist that I was using for testing
serialization when I had problems with it.

Note that testSerializationOfDataContextWithNewObject does not pass.
The other two may or may not pass for you -- I have defined my own
equality method for DataObjects.

However, this should give you a good starting point for trying to test
serialization separately from everything else.

Here's what I use for equality in my base DataObject superclass.

   protected static boolean safeEquals(Object A, Object B) {
       return (A == null) ? (B == null) : A.equals(B);
   }

   public boolean equals(Object obj)
   {
       if (obj != null && (obj.getClass().equals(this.getClass())))
       {
        BaseDataObjectImpl other = (BaseDataObjectImpl)obj;
        
        if (false == safeEquals(objectId, other.getObjectId()))
                return false;
        
        return true;
       }

       return false;
   }

        public int hashCode ()
   {
       // This meets requirements (1) and (2).  You always return the
       // same value for each object because you always return the
       // same value for all objects.  You also return identical
       // hashCode values when two objects test as equals because
       // you always return identical hashCode values.  There is no
       // requirement to return different hashCode values when
       // two objects test as not equal.
       //
       // The only real problem with this implementation is that it
       // is an almost totally useless implementation of hashCode.
       // It can turn a Hashtable lookup into a linear search.
       //
       // With JDK 1.1 you can't return 'x', because it can change
       // and the requirements for hashCode are that the same value
       // must be returned each time hashCode is called on the same object.
       //
       // Java 2 (formerly JDK 1.2) allows 'return x'; because Java 2
allows the hashCode
       // value to change if the underlying data changes.  This is more
       // friendly, but still allows data to be lost in hashtables
       // if the underlying hashCode value changes.
       //
       return 0;
   }

Here's some other serialization stuff.  Dont' know if it'll be helpful
for you.  I mark my temporary data context with the "temporary" user
property.  A lot of this code isn't really used anymore, though.

   ////// Serialization

   private void writeObject(java.io.ObjectOutputStream out)
        throws IOException
   {
        Logger logger = Logger.getLogger("serialization");
        if (null == this.getDataContext())
        {
        logger.info("writeObject: " + this.getClass().getName() + "
[" + String.valueOf(this.hashCode()) + "] has no DC.");
        logger.info("writeObject: " + this);
        Thread.dumpStack();
        }
       out.writeBoolean(Boolean.TRUE ==
this.getDataContext().getUserProperty("temporary"));
       out.defaultWriteObject();

        if (Boolean.TRUE == this.getDataContext().getUserProperty("temporary"))
        {
        logger.info("writeObject: " + this.getClass().getName() + "
[" + String.valueOf(this.hashCode()) + "] has DC [" +
String.valueOf(this.getDataContext().hashCode()) + "] and is marked
temporary.");
        }
        else
        {
        logger.info("writeObject: " + this.getClass().getName() + "
[" + String.valueOf(this.hashCode()) + "] has DC [" +
String.valueOf(this.getDataContext().hashCode()) + "] and is not
marked temporary.");
        }
   }

   private void readObject(java.io.ObjectInputStream in)
        throws IOException, ClassNotFoundException
   {
       boolean isInTemporaryDataContext = in.readBoolean();
       in.defaultReadObject();
       this.isInTemporaryDataContext = isInTemporaryDataContext;

       Logger logger = Logger.getLogger("serialization");
        if (null != this.getDataContext())
        {
        if (isInTemporaryDataContext)
        {
                logger.info("readObject: " + this.getClass().getName() +
" [" + String.valueOf(this.hashCode()) + "] has DC [" +
String.valueOf(this.getDataContext().hashCode()) + "] and is marked
temporary.");
        }
        else
        {
                logger.info("readObject: " + this.getClass().getName() +
" [" + String.valueOf(this.hashCode()) + "] has DC [" +
String.valueOf(this.getDataContext().hashCode()) + "] and is not
marked temporary.");
        }
        }
        else
        {
        if (isInTemporaryDataContext)
        {
                logger.info("readObject: " + this.getClass().getName() +
" [" + String.valueOf(this.hashCode()) + "] has no DC and is marked
temporary.");
        }
        else
        {
                logger.info("readObject: " + this.getClass().getName() +
" [" + String.valueOf(this.hashCode()) + "] has no DC and is not
marked temporary.");
        }
        }
  }
   /**
    * Substitute self with an object registered in thread
    * DataContext with the same ID.
    */
   protected Object readResolve() throws ObjectStreamException
   {
       if (null == getDataContext())
       {
           if (isInTemporaryDataContext)
           {
                Logger logger = Logger.getLogger("serialization");
                logger.info("readResolve: " + this.getClass().getName() +
" [" + String.valueOf(this.hashCode()) + "] has no DC and is marked
temporary.");
                
                return this;
           }
           else
           {
                Logger logger = Logger.getLogger("serialization");
                logger.info("readResolve: " + this.getClass().getName() +
" [" + String.valueOf(this.hashCode()) + "] has no DC and is not
marked temporary.");

                DataContext context;

               try {
                   context = DataContext.getThreadDataContext();
               }
               catch (IllegalStateException e) {
                   throw new NotActiveException("Can't deserialize
object for id '"
                           + getObjectId()
                           + "' - no DataContext bound to thread.");
               }

               // return context.registeredObject(getObjectId());
               return context.localObject(getObjectId(), null);
           }
       }
       else
       {
        Logger logger = Logger.getLogger("serialization");
        logger.info("readResolve: " + this.getClass().getName() + "
[" + String.valueOf(this.hashCode()) + "] has DC [" +
String.valueOf(this.getDataContext().hashCode()) + "].");
           return this;
       }
   }


On 9/11/06, Mike Kienenberger <[EMAIL PROTECTED]> wrote:
No, I wouldn't try changing the transient nature.

It does seem kinda odd, though.  I know that I'm saving serialized
objects two different ways -- by individual DataObject for one
read-only context, and by DataContext for a modified set of objects.
I don't think I have seen this particular problem.

Are you serializing the DataContext directly?


On 9/11/06, Dave Dombrosky <[EMAIL PROTECTED]> wrote:
> I downloaded the 1.2.1 source and added some code to figure out what
> is going on.  It appears that context.getChannel() from
> ObjectStore.java line 945 is returning null.  I am guessing that this
> is because of DataContext line 182 which declares the channel to be
> transient.  Transient properties are not serialized, which is how
> tomcat saves the session, so it is reverting back to it's default
> value (null).
>
> I tried removing the "transient" part of the variable declaration, but
> then Tomcat complains on a different piece of code.  I'm not even sure
> if that's the best way to fix it so I don't think I'll explore that
> any further yet.  Is this issue something that I should add to JIRA?
>
> -Dave
>
> On 9/11/06, Mike Kienenberger <[EMAIL PROTECTED]> wrote:
> > My suggestion would be to look at the 1.2.1 source and see what's
> > going on at ObjectStore.java, line 945.
> >
> > On 9/11/06, Dave Dombrosky <[EMAIL PROTECTED]> wrote:
> > > Problem still occurs on 1.2.1
> > >
> > > On 9/11/06, Mike Kienenberger <[EMAIL PROTECTED]> wrote:
> > > > Maybe http://issues.apache.org/cayenne/browse/CAY-614 ?
> > > >
> > > > This was fixed for 1.2.1.   It might be related.
> > > >
> > > > On 9/11/06, Dave Dombrosky <[EMAIL PROTECTED]> wrote:
> > > > > I am currently having problems when trying to use Cayenne 1.2 along
> > > > > with Tomcat's (v5.0.28) session restore capability.  That is to say,
> > > > > if I deploy new code and restart tomcat, it saves the session data
> > > > > instead of starting with all new sessions when it starts up.
> > > > >
> > > > > My problem is that I used to be able to restart and stay logged in
> > > > > using version 1.1.  Version 1.2 seems to have problems with trying to
> > > > > look up data after I have restarted Tomcat, and I get this stack trace
> > > > > caused by a NullPointerException:
> > > > >
> > > > > 
org.objectstyle.cayenne.access.ObjectStore.resolveHollow(ObjectStore.java:945)
> > > > > 
org.objectstyle.cayenne.access.DataContext.prepareForAccess(DataContext.java:1842)
> > > > > 
org.objectstyle.cayenne.CayenneDataObject.readProperty(CayenneDataObject.java:238)
> > > > >
> > > > > I couldn't find anyone else with this problem, so I assume I am doing
> > > > > something wrong and it's not a bug.  Any ideas?
> > > > >
> > > > > -Dave
> > > > >
> > > >
> > >
> >
>

Reply via email to