I've used Cayenne in a couple of JSF applications.
Up to this point, my best solution was to use a servlet filter to save
and restore the primary DataContext in the session. This is a
read-only (or write-request-only) context, and I explicitly check at
the end of every request to insure it's in a non-dirty state. Thus,
if necessary, I can create a completely-new DataContext on the next
request -- storing this DataContext in the session is simply a
performance enhancer.
I then also have a set of modified DataObjects in a temporary
DataContext that I saveState into the client-side save state. I
don't save the DataContext; I only save the objects.
My DataObject superclass has these serialization methods. There's a
lot of extra logging in here from when I was debugging it -- not every
path is taken.
////// 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 4/2/07, Marc Gabriel-Willem
<marc.gabriel-wille..ide-international.com> wrote:
> Yes, it seems to have a problem with the 'awakeFromDeserialization'
> function. Not sure to understand what you mean by 'code called before
> cayenne is loaded' but for your information the code that crash is
> called by a jsf action method.
>
> Moreover, the problem seems to come from 'relationship objects' (in my
> case: m_editableGroup.getGroupContentArray()).
>
> To summarize:
>
> 1) In a backing bean, I create a child data context and store it as a
> member variable.
> 2) I link entity objects to that child data context.
> 3) I modify those entity objects
> 4) I shut down the tomcat server
> 5) I restart the the tomcat server
> 6) I call a jsf action method (in my business, a save) and then the
> crash appear :|
>
> Thank you for your help.
>
> Marc
>
> -----Original Message-----
> From: Andrus Adamchik [mailto:andru..bjectstyle.org]
> Sent: Sunday, April 01, 2007 3:25 PM
> To: use..ayenne.apache.org
> Subject: Re: Cayenne -- Apache automatic deploy problem
>
> This likely means that 'awakeFromDeserialization' [1] failed to
> attach DataContext to Cayenne stack. Is it possible that the code in
> question called before Cayenne stack is loaded? Where is it called
> anyways?
>
> Andrus
>
>
> [1] http://svn.apache.org/repos/asf/cayenne/main/branches/STABLE-2.0/
> cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/
> DataContext.java
>
> On Mar 30, 2007, at 10:55 AM, Marc Gabriel-Willem wrote:
>
> > Hello,
> >
> > I checked the entity resolver value.
> > Indeed, in this situation the value is 'null'.
> >
> > Marc
> >
> > -----Original Message-----
> > From: Andrus Adamchik [mailto:andru..bjectstyle.org]
> > Sent: Friday, March 30, 2007 4:16 PM
> > To: use..ayenne.apache.org
> > Subject: Re: Cayenne -- Apache automatic deploy problem
> >
> > I can't reproduce this error in a test case. I am out of ideas what
> > might have caused it. Can you possibly debug this condition to figure
> > out why the 'metadata' field in DataContextQueryAction is null? First
> > thing to check:
> >
> > m_editableGroup.getObjectContext().getEntityResolver() != null
> >
> >
> > Andrus
> >
> >
> > On Mar 30, 2007, at 5:24 PM, Marc Gabriel-Willem wrote:
> >
> >> Hello,
> >>
> >> Sorry, it is the first time I'm using a list like this one. So, I'm
> >> doing some crazy error with it :) For example, I hope my "reply
> >> all" is
> >> a correct action to do in this case.
> >>
> >> I saw your first reply.
> >>
> >> I have exactly the same error when I stop and restart properly the
> >> Tomcat server. In fact, stoping and restarting the server simulate
> >> the
> >> serialization / deserialization operation that an application
> >> server can
> >> do at any time it wants (isn't it ?)
> >>
> >> Marc
> >>
> >> -----Original Message-----
> >> From: Andrus Adamchik [mailto:andru..bjectstyle.org]
> >> Sent: Friday, March 30, 2007 3:09 PM
> >> To: use..ayenne.apache.org
> >> Cc: Marc Gabriel-Willem
> >> Subject: Re: Cayenne -- Apache automatic deploy problem
> >>
> >> Hi, See my original reply asking for more information here:
> >>
> >> http://objectstyle.org/cayenne/lists/cayenne-user/2007/03/0101.html
> >>
> >> BTW, it would be much easier to communicate if you subscribe to the
> >> list :-)
> >>
> >> Andrus
> >>
> >>
> >> On Mar 30, 2007, at 4:46 PM, Marc Gabriel-Willem wrote:
> >>
> >>> Hi,
> >>>
> >>>
> >>>
> >>> Sorry to repost that question, but I was not properly register to
> >>> the
> >>> mailing list, so I was unable to reply properly.
> >>>
> >>>
> >>>
> >>> I'm using Cayenne (2.0.2) with the apache web server (5.5.20) and
> >>> I'm
> >>> facing to the following problem.
> >>>
> >>>
> >>>
> >>> When apache does an automatic deploy, all objects are serialized /
> >>> deserialized without any error.
> >>>
> >>> But after that, when the code accesses a cayenne persistent object
> >>> (member variable of a jsf backing bean), the following problem
> >>> occurs:
> >>>
> >>>
> >>>
> >>> Caused by: java.lang.NullPointerException
> >>>
> >>> at
> >>> org.apache.cayenne.access.DataContextQueryAction.interceptPaginatedQ
>
> >>> u
> >
> >>> e
> >>
> >>> ry
> >>> (DataContextQueryAction.java:91)
> >>>
> >>> at
> >>> org.apache.cayenne.access.DataContextQueryAction.execute
> >>> (DataContextQuer
> >>> yAction.java:50)
> >>>
> >>> at
> >>> org.apache.cayenne.access.DataContext.onQuery(DataContext.java:1387)
> >>>
> >>> at
> >>> org.apache.cayenne.access.DataContext.performQuery(DataContext.java:
> >>> 1376
> >>> )
> >>>
> >>> at
> >>> org.apache.cayenne.access.ToManyList.resolvedObjectList
> >>> (ToManyList.java:
> >>> 307)
> >>>
> >>> at
> >>> org.apache.cayenne.access.ToManyList.size(ToManyList.java:260)
> >>>
> >>> at
> >>> com.sideinternational.web.profiling.group.GroupEditor.save
> >>> (GroupEditor.j
> >>> ava:246)
> >>>
> >>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
> >>> Method)
> >>>
> >>> at
> >>> sun.reflect.NativeMethodAccessorImpl.invoke
> >>> (NativeMethodAccessorImpl.jav
> >>> a:39)
> >>>
> >>> at
> >>> sun.reflect.DelegatingMethodAccessorImpl.invoke
> >>> (DelegatingMethodAccessor
> >>> Impl.java:25)
> >>>
> >>> at java.lang.reflect.Method.invoke(Method.java:585)
> >>>
> >>> at
> >>> org.apache.myfaces.el.MethodBindingImpl.invoke
> >>> (MethodBindingImpl.java:13
> >>> 2)
> >>>
> >>>
> >>>
> >>> For information, the following code throws that exception (the
> >>> call to
> >>> the size() method) :
> >>>
> >>> List itemsToRemove = m_editableGroup.getGroupContentArray();
> >>>
> >>> for (int i=0; i < itemsToRemove.size(); i)
> >>>
> >>> ...
> >>>
> >>> Note: Child data context and ObjectEntities are stored in a
> >>> serializable
> >>> jsf backing bean.
> >>>
> >>>
> >>>
> >>> Thank you for your help.
> >>>
> >>>
> >>>
> >>> Marc Gabriel
> >>>
> >>>
> >>>
> >>>
> >>>
> >>
> >>
> >>
> >
> >
> >
>
>
>
This archive was generated by hypermail 2.0.0 : Mon Apr 02 2007 - 10:33:04 EDT