Great info! Some form of all this could make for great javadoc at the top of the InterceptorHandler class. At minimum a few "@see" pointers to the code mentioned.

On Oct 15, 2009, at 5:45 AM, Gurkan Erdogdu wrote:

Currently interceptors and decorators are supported for  the "Managed
Beans".  OWB delegates calling of "EJB Beans" interceptors to the EJB
container. It does not provide built-in interceptor and decorator support
for EJB beans.

This would be great code for the OpenWebBeansEjbInterceptor. Essentially it would have an @AroundInvoke method and be placed last in the EJB interceptor stack. In its @AroundInvoke method it would call the "web beans" Interceptors, call all the Decorators, and then finally call invocationContext.proceed() which effectively hands control back to the ejb container who then invokes the EJB bean instance's target method. I left out a lot of tricky details, but that's how it could work at a high level.

Current implementation supports configuration of the
interceptors on the "Managed Beans" with 2 different scenarios, i.e. it supports "EJB related interceptors ( defined by EJB specification)" and
"JSR-299 related interceptors (defined by interceptor bindings)".

Spec note that @InterceptorBinding is moving into the javax.interceptor package and will be part of the EJB Interceptor spec. The actual definition of it now will still remain in 299 and EJB 3.1 containers won't be required to support it, but in the future they likely will.

So in the future the line between "EJB" Interceptor and "WebBeans" interceptor will get pretty blurry -- more so than it already is. There'll be pretty much no line :) Hopefully Decorators will be added to EJB.next as well (I wanted them in EJB 3.1, but there just wasn't enough bandwidth to address it), in which case the overlap between EJB and WebBeans will get even bigger. Might be an opportunity for code reuse between OpenEJB and OpenWebBeans down the line.

"EJBInterceptorConfig" class is responsible for finding all interceptors for given managed bean class according to the EJB Specification. (But as you
said, it may not include @AroundInvoke/@PostConstruct etc. disablement
scenario!).

No worries there, it's an obscure requirement even we (OpenEJB) didn't find till we started running the TCK. We (OWB) can add it easily later without much change to the way the code is written.

3* Invocation of Interceptors and Decorators

Invocation is handled by the "InterceptorHandler" class [...] After that it filters interceptor stack for calling method (Current design of filtering may not be
optimal!).

I gave that chunk of code a good long mental scrubbing and even started to write some notes on changing it, but I like it more and more. Checking equals on a small number of objects is pretty quick, usually faster than an array copy. There usually aren't a large number of interceptors and if there are they are typically defined at the class level or more generallly -- at the method level is less common. Any scenario involving starting with an empty array (ArrayList) and adding items to it could involve growing that ArrayList. If we start with the full list, copy it, then yank out the values that don't apply, we guarantee that the first array created is the right size. So the logic involves no hash lookups and exactly one array copy. The filtering is mostly boolean comparisons until we reach the entries that apply to specific methods and start calling .equals().

The only other way for it to be faster is to go the exact opposite approach and build a full stack for each method in advance, so the entire stack is one hashmap lookup away and the method is the key. Building one stack per method can be bad. I've found that doing that kind of processing in advance can significantly raise the deployment cost. Doing special processing for every method can really drag startup as the number of beans and methods increase. This way, there's no actual growing cost when beans/methods increase, just when the number of interceptors increase and that's almost always going to be a smaller number.

I'm very tempted to go back and rewrite the related OpenEJB code.

A small note is that InterceptorHandler actually doesn't do the list copy in they way I describe -- it copies one item at a time which could grow the original array in the new ArrayList -- but that's a one line change. Can just pass the read-only array into the ArrayList constructor when creating the temp list. Then what I mention is true.

Good small focused change if someone wants to throw that in real quick.

The correct way may be that after executing last interceptor instance, it looks for the decorator stack. If decorator stack is not empty, it exhausts all decorators before calling actual method. (I1 --> I2 --> D1 --> Actual Method). This issue can be resolved easily by updating *InterceptorHandle*
code.

Right, exactly.

-David

Reply via email to