The idea started from an endless debate regarding Drool vs. jBPM. :-)
Thinking about the JIRA issue of being able to create your own dependency
+ listening to MarkP here @ Farnborough, I hacked the next stuff over the weekends + some
details now during the visit.
The basic idea is to define a set of rules for certain bean.
And than add dependency items based on those rules.
There is a RuleDependencyMapper - aop-lifecycle bean - that matches the beans and applies
the
dependency item created from the DependencyItemFactory.
The rules are held in a Drools StatefulSession (WorkingMemory - WM), and I applied
JBossAOP interceptors
for all CRUD methods (insert, update, retract) on the WM instance, so that
WM.fireAllRules() method is
transperently invoked. Basically meaning any change to WM can lead to some rules
dependencies being resolved.
Here I still need to find a way to transperently push forward contexts that have been
resolved by this WM invocation.
I also added a few ways to aviod fireAllRules for any CRUD. You can set an
@DisableFireAllRules on a method, and a ThreadLocal
flag will be set which will prevent FireAllRulesAdvice to fire.
Or you can set @FireAllRulesAfter, in which case all invocation of fireAllRules method
will be ignored, and the interceptor will
issue the execution at the end of the method.
I've also added a couple of deployers that know how to handle Drools .drl, .dsl, .xsl,
.csv files.
All this stuff is pushed into new MC module called reliance (since dependency already
exists, I went to webster thesaurus for the name).
When I find some time - and it looks it won't be any time soon :-) - I have a similar
idea for jBPM.
I'll wait with commiting this stuff after Scott releases MC beta4.
I still have to write some tests, but this will be done with jBPM idea - after the JBAS5
dust settles.
The concept test case is here:
| <deployment xmlns="urn:jboss:bean-deployer:2.0">
|
| <!-- aspects -->
|
| <bean name="AspectManager"
class="org.jboss.aop.AspectManager">
| <constructor factoryClass="org.jboss.aop.AspectManager"
factoryMethod="instance"/>
| </bean>
|
| <!-- intercepts any StatefulSession creation from our RuleBase bean -->
| <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
| name="WrapStatefulSessionAdvice"
|
class="org.jboss.reliance.drools.core.aspects.StatefulSessionCreationInterceptor"
| pointcut="execution(*
org.jboss.reliance.drools.core.RuleBaseBean->newStatefulSession(..))"/>
|
| <!-- invokes fireAllRules after any CRUD method invocation on WorkingMemory
instance -->
| <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
| name="FireAllRulesCheckAdvice"
|
class="org.jboss.reliance.drools.core.aspects.CRUDAwareAspect"
| pointcut="execution(*
$instanceof{org.drools.StatefulSession}->$implements{org.drools.WorkingMemory}(..))"
/>
|
| <!-- disables fireAllRules if @DisableFireAllRules is present -->
| <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
| name="DisableFireAllRulesAdvice"
|
class="org.jboss.reliance.drools.core.aspects.DisableFireAllRulesInterceptor"
| pointcut="execution(*
@org.jboss.reliance.drools.core.aspects.DisableFireAllRules->*(..)) OR execution(*
*->@org.jboss.reliance.drools.core.aspects.DisableFireAllRulesAllRules(..))"
/>
|
| <!-- only invokes fireAllRules at the end of invocation -->
| <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
| name="FireAllRulesAfterInvocationAdvice"
|
class="org.jboss.reliance.drools.core.aspects.FireAllRulesAfterInvocationInterceptor"
| pointcut="execution(*
@org.jboss.reliance.drools.core.aspects.FireAllRulesAfter->*(..)) OR execution(*
*->@org.jboss.reliance.drools.core.aspects.FireAllRulesAfterlesAfter(..))">
| <constructor>
| <parameter><inject bean="WorkingMemory"
property="statefulSession"/></parameter>
| </constructor>
| </aop:aspect>
|
| <!-- applies RuleBasedDependencyItem to all @RulesAware beans -->
| <aop:lifecycle-describe xmlns:aop="urn:jboss:aop-beans:1.0"
| name="RulesMapper"
|
class="org.jboss.reliance.drools.dependency.RuleDependencyMapper"
|
classes="(a)org.jboss.reliance.drools.dependency.RulesAware">
| <property name="factory"><inject
bean="RuleBasedDependencyFactory"/></property>
| </aop:lifecycle-describe>
|
| <bean name="RuleBasedDependencyFactory"
class="org.jboss.reliance.drools.dependency.RuleBasedDependencyItemFactory">
| <property name="whenRequired">Create</property>
| </bean>
|
| <!-- drools beans -->
|
| <bean name="WorkingMemory"
class="org.jboss.reliance.drools.core.ManagedWorkingMemory">
| <constructor>
| <parameter><inject bean="RuleBase"/></parameter>
| <parameter><inject
bean="jboss.kernel:service=KernelController"/></parameter>
| </constructor>
| <incallback method="addEventListener"
signature="org.drools.event.AgendaEventListener"/>
| <incallback method="addEventListener"
signature="org.drools.event.WorkingMemoryEventListener"/>
| <uncallback method="removeEventListener"
signature="org.drools.event.AgendaEventListener"/>
| <uncallback method="removeEventListener"
signature="org.drools.event.WorkingMemoryEventListener"/>
| </bean>
|
| <bean name="debugAgendaEventListener"
class="org.drools.event.DebugAgendaEventListener"/>
| <bean name="debugWorkingMemoryEventListener"
class="org.drools.event.DebugWorkingMemoryEventListener"/>
|
| <bean name="RuleBase"
class="org.jboss.reliance.drools.core.RuleBaseBean">
| <demand>packageGenerator</demand>
| </bean>
|
| <bean name="packageGenerator"
class="org.jboss.reliance.drools.core.PackageGenerator">
| <property name="fromDRL">
| <value>
| package SimplePermissions;
|
| import org.jboss.reliance.drools.core.security.PermissionCheck;
| import org.jboss.reliance.drools.core.security.RoleTracker;
| import org.jboss.reliance.drools.core.security.Role;
| import org.jboss.reliance.drools.core.rules.Flag;
|
| global org.jboss.dependency.spi.Controller controller;
|
| rule TesterCanBeCreated
| when
| c: PermissionCheck(name == "tester", action ==
"Create")
| Role(name == "admin")
| then
| c.grant();
| end;
|
| rule RoleTrackerAddition
| salience 10
| when
| Role(name == "admin")
| then
| insert( new Flag("admin_flag") );
| insertLogical( new RoleTracker("admin") );
| end;
|
| rule RoleTrackerRemovalTrigger
| when
| f : Flag(name == "admin_flag")
| not( RoleTracker(name == "admin") )
| then
| retract( f );
| RoleTracker.change(controller, "tester",
"Configured");
| end;
| </value>
| </property>
| </bean>
|
| <bean name="configuration"
class="org.jboss.reliance.identity.Configuration"/>
|
| <bean name="identity"
class="org.jboss.reliance.drools.core.security.RoleBasedIdentity">
| <property name="securityContext"><inject
bean="WorkingMemory" property="statefulSession"/></property>
| <property name="configuration"><inject
bean="configuration"/></property>
| </bean>
|
| <!-- user beans -->
|
| <bean name="roles"
class="org.jboss.test.reliance.drools.support.RolesAdapter">
| <constructor>
| <parameter><inject bean="identity"/></parameter>
| </constructor>
| <property name="username">alesj</property>
| <property name="password">qwert</property>
| <property name="roles">
| <set elementClass="java.lang.String">
| <value>guest</value>
| </set>
| </property>
| </bean>
|
| <bean name="tester"
class="org.jboss.test.reliance.drools.support.Tester">
|
<annotation>(a)org.jboss.reliance.drools.dependency.RulesAware</annotation>
| <demand state="PreInstall">roles</demand>
| </bean>
|
| </deployment>
|
and the matching JUnit code
| public void testRulesConcept() throws Throwable
| {
| // only in Configured state, since there is no admin role present
| KernelControllerContext testerContext = getControllerContext("tester",
ControllerState.CONFIGURED);
| assertEquals(ControllerState.CONFIGURED, testerContext.getState());
|
| RolesAdapter rolesAdapter = (RolesAdapter)getBean("roles");
| rolesAdapter.addRole("admin");
|
| // should be Installed now, since admin role is present
| change(testerContext, ControllerState.INSTALLED);
| assertEquals(ControllerState.INSTALLED, testerContext.getState());
|
| rolesAdapter.removeRole("admin");
| // should be unwinded to Configured, since the admin role was removed
| assertEquals(ControllerState.CONFIGURED, testerContext.getState());
|
| KernelControllerContext identityContext =
getControllerContext("identity");
| change(identityContext, ControllerState.NOT_INSTALLED);
|
| // should be uninstalled as well, since it relies on identity
| assertEquals(ControllerState.NOT_INSTALLED, testerContext.getState());
| }
|
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4080123#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...