Dynamically Attaching Interceptors to any (X)MBean
dimitris Dec 5, 2004 7:21 PMI scratched my head quite a few times trying to figure out:
http://www.jboss.org/index.html?module=bb&op=viewtopic&t=56668
The main issue here was that we want to attach an intereptor-like chain to existing deployers (e.g. EJBDeployer) so that related deployers (e.g. WebService) can not only react to notifications but be able also to fail the whole thing if something is wrong on their side.
XMBeans can have interceptors but the problem is those are defined statically at deployment time. If we could dynamically add/remove interceptors that would solve a big part of the problem.
So I created the internal hooks to allow any (X)MBean to become "Interceptable". To expose the Interceptable interface you just have to specify in the xmbean descriptor the DynamicInterceptor, and expose some predefined operations:
<mbean> ... <descriptors> <interceptors> <interceptor code="org.jboss.mx.interceptor.DynamicInterceptor"/> </interceptors> </descriptors> ... &interceptable;
Using the addOperationInterceptor()/removeOperationInterceptor() methods, you can attach/detach at runtime new interceptors to the running MBean.
I've included a helper base class that extends ServiceMBeanSupport, called InterceptorServiceMBeanSupport that lets you quickly write Services that upon start-up attach themselves as interceptors to an Interceptable target (X)MBean, and detach themselves upon stop.
You simply override an invoke(Invocation) method to do whatever you want, and configure a dependency on the Interceptable MBean, e.g.:
<mbean code="org.jboss.test.jmx.interceptors.AdderInterceptorService" name="jboss.test:service=adderinterceptor"> <depends optional-attribute-name="Interceptable" proxy-type="attribute"> jboss.test:service=interceptable </depends> </mbean>
This example MBean dynamically attaches itself to another XMBean, then monitors calls to method add(int a, int b) and just increments the result by one, so 1+1 gives 3.
As it is now, it let's you intercept operations (I could do it for attribute get/sets, too, but I don't know who would use that), and also puts every new dynamic interceptors first in the chain, so it's really in your invoke() code to decide whether to do your stuff then forward the call, or the other way round.
I can imagine this can have many other usages apart from deployer chaining.
The next step would be to re-write either the Portal or WebService deployers based on this, and see how it goes.