You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Tomi NA <he...@gmail.com> on 2006/05/18 12:54:35 UTC

serialization issue

I'm writing a swing app based on the NetBeans platform. I tried to
serialize a bean containing cayenne generated beans and got the
following result (please excuse the lenght):

Serializable class cayennedata.OrganizationType does not declare
serialVersionUID field. Encountered while storing:
[org.openide.windows.TopComponent$Replacer, advancedsearch.Testing,
java.lang.Integer, java.lang.Number] See also
http://www.netbeans.org/issues/show_bug.cgi?id=19915
Serializable class cayennedata.generated._OrganizationType does not
declare serialVersionUID field. Encountered while storing:
[org.openide.windows.TopComponent$Replacer, advancedsearch.Testing,
java.lang.Integer, java.lang.Number, cayennedata.OrganizationType] See
also http://www.netbeans.org/issues/show_bug.cgi?id=19915
Serializable class org.objectstyle.cayenne.CayenneDataObject does not
declare serialVersionUID field. Encountered while storing:
[org.openide.windows.TopComponent$Replacer, advancedsearch.Testing,
java.lang.Integer, java.lang.Number, cayennedata.OrganizationType,
cayennedata.generated._OrganizationType] See also
http://www.netbeans.org/issues/show_bug.cgi?id=19915
Serializable class org.objectstyle.cayenne.ObjectId does not declare
serialVersionUID field. Encountered while storing:
[org.openide.windows.TopComponent$Replacer, advancedsearch.Testing,
java.lang.Integer, java.lang.Number, cayennedata.OrganizationType,
cayennedata.generated._OrganizationType,
org.objectstyle.cayenne.CayenneDataObject] See also
http://www.netbeans.org/issues/show_bug.cgi?id=19915

I have a couple of questions about this.
First, is there any special reason the templates, the DataObject and
the ObjectId class don't have a serialVersionUID?
Second, is it possible at all to successfuly serialize a class
representing a database entity? Won't the serialization algorithm get
just about the entire database, following the bean getters?

I'd very much appreciate a comment on the topic, as well as a prod in
the right direction concerning cayenne DataObject serialization.
Should I be looking at decode/encodeXML?

t.n.a.

Re: serialization issue

Posted by Tomi NA <he...@gmail.com>.
On 5/18/06, Andrus Adamchik <an...@objectstyle.org> wrote:

> A simple trick would be to use thread-bound DC and create
> "readResolve" method in a custom DO superclass that reattaches itself
> to the thread context (or rather returns a substitute object local to
> the current DC):
>
> private Object readResolve() throws ObjectStreamException {
>     DataContext dc = DataContext.getThreadDataContext();
>     return dc == null ? this : dc.localObject(getObjectId(), this);
> }

This brought me closer to the solution, but I'm not there yet.
Here's what I did.
My dc is in a public static field instead of the current thread - I'm
not sure I can depend on always being in the same thread and I'd like
to use the same dc during the runtime of the app.
I've extended CayenneDataObject along the lines you suggested:

public class SerializableCayenneDataObject extends CayenneDataObject {

    public SerializableCayenneDataObject() {
    }

    private Object readResolve() throws ObjectStreamException {
     DataContext dc = Misc.context;     // not from the current thread
     return dc == null ? this : dc.localObject(getObjectId(), this);
   }
}

I've regenerated the generated superclasses so that they extend the
SerializableCayenneDataObject instead of CayenneDataObject.
Alas, the breakpoint I placed inside the readResolve method never gets
called and I still get an object with null values for all fields
instead of the object I stored.

I tested then if the readResolve code would work anyway and included
it into the readExternal() deserialization method. This is what it
looks like:

    public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
        try {
            MyEntityDataObject medo = (MyEntityDataObject)in.readObject();
            medo = (MyEntityDataObject)
Misc.dataContext.localObject(medo.getObjectId(), medo);
            System.out.println(medo.getName());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject((MyEntityDataObject)MyEntityDataObject.dohvatiPopis(Misc.dataContext).get(0));
    }

Anyway, this works. I get a medo object with the information I stored
using writeExternal. What I really need now is a way to make the
DataContext.localObject call transparent i.e. have it called
internally in my dataObject by extending my custom DataObject. Can
anyone tell me what I did wrong?

Re: serialization issue

Posted by Andrus Adamchik <an...@objectstyle.org>.
On May 18, 2006, at 10:58 AM, Tomi NA wrote:

> Hmm...I'm sorry to hear that. The problem is, I have a panel and a
> bean (presenter, model, if you will) and I bind them using jgoodies
> binding. Some of the bean fields are cayenne DataObjects. I have these
> kinds of panels all over the app, but I need to serialize just a
> couple of them: the point is to save a part of the frame (panel)
> state.

Ok, then serializaing the entire context is indeed inappropriate.  
Just serialize the objects (note that 'objectContext' is a transient  
field, so a serialized object won't drag a DC with it).

> How should I go about serializing/deserializing such objects? All I
> have at my disposal right now is a stream to which I can write to or
> read from, depending on whether I'm serializing or deserializing. I'm
> not clear on what happens when I write an object to such a stream, no
> matter the fact I have a serialized DataContext.

A simple trick would be to use thread-bound DC and create  
"readResolve" method in a custom DO superclass that reattaches itself  
to the thread context (or rather returns a substitute object local to  
the current DC):

private Object readResolve() throws ObjectStreamException {
    DataContext dc = DataContext.getThreadDataContext();
    return dc == null ? this : dc.localObject(getObjectId(), this);
}

Andrus




Re: serialization issue

Posted by Tomi NA <he...@gmail.com>.
On 5/18/06, Andrus Adamchik <an...@objectstyle.org> wrote:
>
> On May 18, 2006, at 6:54 AM, Tomi NA wrote:
>
> > I have a couple of questions about this.
> > First, is there any special reason the templates, the DataObject and
> > the ObjectId class don't have a serialVersionUID?
>
> We should probably add serialVersionUID to all serializable classes
> (and somehow add it to cgen templates) - this may be an improvement
> to the future versions. But the JVM should not throw an exception
> when it is absent either. So are you getting some kind of warning, or
> is this an exception?

It is just a warning, but it seems that the serialization process
fails as I get null values when I deserialize. I thought the missing
UID might be the reason.

> > Second, is it possible at all to successfuly serialize a class
> > representing a database entity?
>
> Absolutely. Serialization of DataObjects worked since Cayenne 1.0.
> The easiest way is to serialize the entire DataContext; if you
> serialize individual objects, you will have to manually reattach them
> to the context on deserialization (e.g. by calling 'localObject').

> > Won't the serialization algorithm get
> > just about the entire database, following the bean getters?

> No, Java serialization does not use getters, it serializes fields
> directly. However IIRC Java bean serialization does - so this can be
> a problem.

Hmm...I'm sorry to hear that. The problem is, I have a panel and a
bean (presenter, model, if you will) and I bind them using jgoodies
binding. Some of the bean fields are cayenne DataObjects. I have these
kinds of panels all over the app, but I need to serialize just a
couple of them: the point is to save a part of the frame (panel)
state.
Now, to the fields-bean properties issue...If I deserialized the
entire context, as you suggest, what would that do for me in terms of
(de)serializing my own bean containing private fields with their
respective public get/set pairs?
How should I go about serializing/deserializing such objects? All I
have at my disposal right now is a stream to which I can write to or
read from, depending on whether I'm serializing or deserializing. I'm
not clear on what happens when I write an object to such a stream, no
matter the fact I have a serialized DataContext.

> > I'd very much appreciate a comment on the topic, as well as a prod in
> > the right direction concerning cayenne DataObject serialization.
> > Should I be looking at decode/encodeXML?
>
> If you don't care about the format, Java binary serialization should
> be more efficient than XML.

I couldn't care less. :)

t.n.a.

Re: serialization issue

Posted by Andrus Adamchik <an...@objectstyle.org>.
On May 18, 2006, at 6:54 AM, Tomi NA wrote:

> I have a couple of questions about this.
> First, is there any special reason the templates, the DataObject and
> the ObjectId class don't have a serialVersionUID?

We should probably add serialVersionUID to all serializable classes  
(and somehow add it to cgen templates) - this may be an improvement  
to the future versions. But the JVM should not throw an exception  
when it is absent either. So are you getting some kind of warning, or  
is this an exception?


> Second, is it possible at all to successfuly serialize a class
> representing a database entity?

Absolutely. Serialization of DataObjects worked since Cayenne 1.0.  
The easiest way is to serialize the entire DataContext; if you  
serialize individual objects, you will have to manually reattach them  
to the context on deserialization (e.g. by calling 'localObject').


> Won't the serialization algorithm get
> just about the entire database, following the bean getters?

No, Java serialization does not use getters, it serializes fields  
directly. However IIRC Java bean serialization does - so this can be  
a problem.

> I'd very much appreciate a comment on the topic, as well as a prod in
> the right direction concerning cayenne DataObject serialization.
> Should I be looking at decode/encodeXML?

If you don't care about the format, Java binary serialization should  
be more efficient than XML.

Andrus