As Mark is hammering on the observer code (thanks, Mark!), I moved over to Interceptors and am mulling over that code. For those that like to follow along, most the code is in InterceptorHandler. Ran into some related Decorator stuff as well.

INTERCEPTOR RELATED

First a small note, in the current code there is one interceptor stack per component, rather than per method. I see how we copy the list on each invoke and filter out the interceptors that do not apply to the method being invoked, but I didn't see if we were maintaining order in that list. Figured I'd just ask where the original list was created so I could take a look -- faster than digging. Pointer is welcome.

A side note on the above, I think we could use some more diversity in the related tests. So far we don't have any components that have more than one interceptable method, so most the above logic is unchallenged. We should definitely add some tests that verify you only get interceptors that were declared in your method and not ones from other methods as well as verifying the order is as declared on the method. The current code shouldn't have a problem with that, but if someone wanted something to do, that'd be a great contribution.

One area not implemented is something barely mentioned in the interceptor spec, but I know is tested in the EJB spec at least, is the concept of "Disable via override." If an @AroundInvoke method is overridden in a subclass without also being annotated @AroundInvoke, then this must dissable the around invoke method and it should not be called. This applies to @AroundInvoke methods in beans and interceptors. It also applies to @PostConstruct and @PreDestroy callbacks.

INTERCEPTORS and DECORATORS

It looks as though the part of the spec that says "Decorators are called after interceptors" was taken differently than intended. Currently, the interceptor stack wraps the target bean and the decorator "stack" more or less just gets a notification of the invocation as a separate after thought. As well Decorators were implemented as a list that is iterated over, rather than as a stack where one decorator calls the next in the chain.

Interceptors and Decorators are completely identical and part of the same overall invocation stack. They both wrap an object and delegate to it. They both can manipulate the method parameters and both can manipulate the return value (or exception). The only difference is Interceptors are very reflection-like and Decorators are strongly typed.

So what "Decorators are called after interceptors" means is that one stack is created and in that stack interceptors are invoked first, decorators are invoked second, and the target bean method is invoked last. The wording is unfortunate as it also means that the opposite is true on the way out: the bean returns and that value propagates back up the stack to the decorators, then the interceptors. So Interceptors and Decorators all wrap each other like one big onion. Interceptors are the outer most layers of the onion, the decorator layers follow, and finally the bean itself is the center.

From an implementation standpoint what it means is that the last interceptor in the interceptor part of the stack is actually going to invoke the first decorator in that part of the stack and the invocation will continue. Code wise there's no real way for that last interceptor to know if its invoking the bean or a decorator that implements the same interface and method as the bean. It just calls what it was given. So we just need to make an actual stack out of the decorators and pass that into the interceptor stack in place of where we pass the bean now.

If someone has time that's another good area for contribution.


-David


Reply via email to