We're trying to finish up an application and we're taking a hammering
from Java null pointers and database NULL.
The trick with our application is that we need to be bug-by-bug
database compatible with an old .asp + vbscript application until such
time that we can delete the old application, so are hands are pretty
tied w.r.t. solving problems at a database/application design level.
Handling null pointers in a more robust and universal fashion, is one
of my hobby horses.
http://www.objectstyle.org/cayenne/lists/cayenne-user/2006/08/0010.html.
While I'm on the soapbox: a Java null pointer is a VERY different
beast from a database NULL and trying to simulate one with the other,
while at first it sounds like a good idea, turns out to be hairy to
say the least. I wish Cayenne would stop using Java null pointers
pretty much across the board to represent anything but unitialized
member variables. Uninitialized member variables should never be read
by correctly written code per my personal definition. I'll step down
from my soapboax now.
One of the exceptions we're looking into are below. I'm trying to see
where things go haywire, but here are some of the clues that I've
managed to find:
- readProperty() for a property that returns a CayenneDataObject will
either return a Java null pointer or a CayenneDataObject. "instanceof"
will always return false for a Java null pointer.
- I don't believe there is such a thing as an ObjectId for a Java null
pointer returned by readProperty()(which in this case represents a
database NULL).
- writeProperty(null) is legal and is Cayenne speak for asking the
underlying engine to write a database NULL.
- DataContext.localObject() does not allow null pointer's for an
ObjectId. There is no way to distinguish between two Java null
pointers that "belong" to two different CayenneDataContext's, so some
conditional code on the outside of localObject() can be used/is
required in *all places* where a database null might appear. The net
result is the need for a raft of if() statements to somehow handle the
null pointer case in each instance localObject() is invoked.
- Here is an ArcOperation. I'm not sure what this *should* have looked
like in the writeProproty(null) case, given that there is no such
thing as an ObjectId representing database null.
[1]= ObjectDiff$ArcOperation (id=7192)
arcId= "toTreatCustomspec"
delete= false
diffId= 2
nodeId= ObjectId (id=7221)
targetNodeId= null
Caused by: java.lang.IllegalArgumentException: Null ObjectId
at org.objectstyle.cayenne.access.DataContext.localObject(DataContext.java:1903)
at org.objectstyle.cayenne.access.DataContextMergeHandler.arcCreated(DataContextMergeHandler.java:203)
at org.objectstyle.cayenne.access.ObjectDiff$ArcOperation.apply(ObjectDiff.java:408)
at org.objectstyle.cayenne.graph.CompoundDiff.apply(CompoundDiff.java:133)
at org.objectstyle.cayenne.access.ObjectStoreGraphDiff.apply(ObjectStoreGraphDiff.java:155)
at org.objectstyle.cayenne.access.DataContextMergeHandler.graphChanged(DataContextMergeHandler.java:135)
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 org.objectstyle.cayenne.util.Invocation.fire(Invocation.java:240)
at org.objectstyle.cayenne.event.EventManager$Dispatch.fire(EventManager.java:433)
at org.objectstyle.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:182)
at org.objectstyle.cayenne.event.DispatchQueue.dispatchEvent(DispatchQueue.java:94)
at org.objectstyle.cayenne.event.EventManager.dispatchEvent(EventManager.java:372)
at org.objectstyle.cayenne.event.EventManager.postEvent(EventManager.java:343)
at org.objectstyle.cayenne.access.DataContext.fireDataChannelChanged(DataContext.java:1731)
at org.objectstyle.cayenne.access.DataContext.onContextFlush(DataContext.java:1216)
at org.objectstyle.cayenne.access.DataContext.onSync(DataContext.java:1194)
at org.objectstyle.cayenne.access.DataContext.flushToParent(DataContext.java:1261)
at org.objectstyle.cayenne.access.DataContext.commitChanges(DataContext.java:1165)
-- Øyvind Harboe http://www.zylin.com
This archive was generated by hypermail 2.0.0 : Mon Oct 23 2006 - 14:12:17 EDT