The first thing you need to understand is that the Java object you get from IDfSession.getObject or IDfSession.newObject is not the actual persistent object – it is a proxy object (google Java dynamic proxies for more info). It looks like a regular old persistent object to you, but it isn’t.
Whenever you attach (or detach) an aspect you might end up changing the prototype of the persistent object. This would be the case if an aspect implemented an orthogonal interface. DFC will actually rebuild the class files (yes, the byte code) that relates to the type [+aspects] in question. This is an expensive operation and there are optimizations to minimize the number of times this is done.
Of course, your existing persistent object is already loaded from the old class definition and this can’t change, so you end up with a “stale” persistent object reference.
So, after attaching or detaching an aspect you must refetch the object immediately. The refetched object will implement any new interfaces and will not implement any removed interfaces. Any unsaved changes you made will be preserved. The sequence should be something like this …
if (obj instanceof IDfAspects) {
(IDfAspects) obj).attachAspect(“foo”, null);
obj = session.getObject(obj.getObjectId());
((IFoo) obj).foo();
}
The above code fragment is suitable when you are a regular client (eg. application code). However, if you are executing in the context of a TBO or aspect method on obj itself when you try to attach or detach the aspect, then you are executing on the “old” object that is about to become stale, and the new object has not been built yet, so getObject just returns the same old disappointing Java object. You then have to use callbacks. Callbacks are invoked just before the original entry point to the outermost TBO or aspect method invocation returns and have a kind of implicit getObject associated with them. You can think of them as delayed client code. Do not do getObject within a callback – the object reference your callback is given is the new, beautiful, predictable Java object. The code sequence would then look something like this …
this.attach/detachAspect(“foo”, myCallback); // myCallback invokes foo()
// You cannot use foo here – the Java object is not ready. Refetch won’t help either.
The callback implementation would look something like this …
void doPostAttach/Detach(IDfPersistentObject obj) {
((IFoo) obj).foo(); // ok, obj is fully cooked here
}
Also note that not all objects can have aspects attached. All sysobjects and its subclasses can, but most non-sysobjects don’t support aspects. Any object that does, however, will implement the IDfAspects interface (DFC sees to this automatically). A non-sysobject type would only support aspects if it were created with the DQL syntax …
alter type ... allow aspects