Do you know all the available rules ahead of time, even if you don't necessarily want to pre-register them?
Perhaps we could have a lazy rule provider that registers all its tokens ahead of time, but doesn't compile the rules until they're actually requested? -Darius On Thu, Sep 1, 2011 at 11:50 AM, McKee, Steven Jay <[email protected]>wrote: > The pre-registration of rules is what we’re currently trying to get away > from. We basically want our rules to be found and loaded as needed. The > problem is the rules are executed at the OpenMRS level (created by the Arden > translator). We can’t directly register rules to our provider from there > since the provider is down in a module. We need something to call before we > call eval on a rule to make sure it’s loaded (or it won’t be found): **** > > ** ** > > Rule 1:**** > > > /////////////////////////////////////////////////////////////////////////////////////// > **** > > Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”, > parameters);**** > > > /////////////////////////////////////////////////////////////////////////////////////// > **** > > ** ** > > Rule 1 is calling the “ChicaAgeRule” from within it. We need some > mechanism to ensure the “ChicaAgeRule” is loaded (and load it if it’s not) > before we call eval. Since we’re trying to avoid pre-registering all the > rules, there isn’t a good way to get them loaded.**** > > ** ** > > One possibility is to have the “getRule” method in a rule provider be dual > purpose. It can load and possibly register the rule if it’s not currently > registered. The rule provider would then have to be passed in parameters of > the eval method. The Arden translator could create something like this:** > ** > > ** ** > > Rule 1:**** > > > /////////////////////////////////////////////////////////////////////////////////////// > **** > > RuleProvider ruleProvider = (RuleProvider)parameters.get(“ruleProvider”);* > *** > > If (ruleProvider != null) {**** > > ruleProvider.getRule(“ChicaAgeRule”);**** > > }**** > > Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”, > parameters);**** > > > /////////////////////////////////////////////////////////////////////////////////////// > **** > > ** ** > > This doesn’t seem the best way to do it, but I’m not sure of another way > since we’re trying to avoid pre-registration. This is basically why we were > proposing to add a new “loadRule” method to the logicService interface so we > could AOP around it and load our rules: **** > > ** ** > > Rule 1:**** > > > /////////////////////////////////////////////////////////////////////////////////////// > **** > > logService.loadRule(“ChicaAgeRule”, false);**** > > Result result = context.eval(patient.getPatientId(), “ChicaAgeRule”, > parameters);**** > > > /////////////////////////////////////////////////////////////////////////////////////// > **** > > ** ** > > ** ** > > Thanks,**** > > Steve**** > > ** ** > > ** ** > > *From:* Darius Jazayeri [mailto:[email protected]] > *Sent:* Thursday, September 01, 2011 10:22 AM > *To:* McKee, Steven Jay > *Cc:* dev; Dugan, Tammy Marie > > *Subject:* Re: New LogicService method**** > > ** ** > > Yes, you could register your static rules in the afterStartup method on a > RuleProvider. (That's exactly what that method is for.)**** > > ** ** > > E.g. the handler in the logic module that handles dynamically-defined rules > in groovy or java does:**** > > /** > * @see org.openmrs.logic.rule.provider.AbstractRuleProvider#afterStartup() > */ > @Override > public void afterStartup() { > TokenService tokenService = Context.getService(TokenService.class); > RuleDefinitionService service = > Context.getService(RuleDefinitionService.class); > for (RuleDefinition rd : service.getAllRuleDefinitions()) { > tokenService.registerToken(rd.getName(), this, > rd.getId().toString()); > } > }**** > > Also, do make sure you extend AbstractRuleProvider rather than just > implementing RuleProvider, in case that interface ends up getting methods > added later.**** > > ** ** > > -Darius**** > > ** ** > > On Thu, Sep 1, 2011 at 8:15 AM, McKee, Steven Jay <[email protected]> > wrote:**** > > I can see this approach working well for our dynamic class loading:**** > > **** > > 1. The class loader task looks for new classes.**** > > 2. Once found, the rules get registered to our DSS rule provider.*** > * > > 3. The DSS rule provider would use our compiling classloader to > locate the file in the “getRule” method.**** > > **** > > We still, however, have the issue of our static rules in some of our > modules. We want to be able to use these on the fly, so how would be > initially get these rules registered? Would be have to write some sort of > task to do this on startup? Is there anything in logic that provides us a > way of doing this? I noticed there’s an “afterStartup” method in the > RuleProvider interface. What exactly is this used for?**** > > **** > > Thanks,**** > > Steve**** > > **** > > **** > > *From:* Darius Jazayeri [mailto:[email protected]] > *Sent:* Wednesday, August 31, 2011 5:34 PM > *To:* McKee, Steven Jay; dev**** > > > *Cc:* Dugan, Tammy Marie > *Subject:* Re: New LogicService method**** > > **** > > Moving this to the developers list.**** > > **** > > The way this is supposed to work is that if you have a rule (YourRule.java) > and you want it to be accessible as the token "Your Rule", then you need to > do something like this:**** > > TokenService.registerToken("Your Rule", chicaRuleProvider, > "InternalUniqueIdOfYourRule");**** > > **** > > Then when LogicService.getRule("Your Rule") is called, that will delegate > to:**** > > chicaRuleProvider.getRule("InternalUniqueIdOfYourRule");**** > > **** > > Presumably you have a RuleProvider in your module already? (Even if you're > bypassing LanguageHandler, I think RuleProvider is necessary...)**** > > **** > > The logic infrastructure will cache these rules (since they may be > expensive to compile) so if you want it to forget a cached value, you'd do: > **** > > TokenService.notifyRuleDefinitionChanged("Your Rule");**** > > **** > > It seems like these methods should be sufficient for what you're trying to > do.**** > > **** > > (Adding a method to LogicService is pretty significant to do, because > that's a change to the core api, which requires simultaneous releases of new > versions of 1.6.x, 1.7.x, and 1.8.x, to support the new logic module. It's > possible that we end up doing this, but it can't happen quickly.)**** > > **** > > -Darius**** > > **** > > On Tue, Aug 30, 2011 at 2:42 PM, McKee, Steven Jay <[email protected]> > wrote:**** > > We are currently bypassing the dynamic rule code and language handlers. We > need the ability to load rules on the fly instead of pre-loading them. It > just gives us a lot of flexibility and the benefit of not loading rules we > may not use.**** > > **** > > Thanks, Darius.**** > > **** > > Steve**** > > **** > > *From:* Darius Jazayeri [mailto:[email protected]] > *Sent:* Tuesday, August 30, 2011 2:04 PM > *To:* McKee, Steven Jay > *Cc:* Dugan, Tammy Marie > *Subject:* Re: New LogicService method**** > > **** > > Hi steve**** > > I'm out and about at the moment, but will try to reply on the dev list > today out tomorrow.**** > > Isn't there already a workflow so your rule provider can update loaded > rules though? Or have you ended up bypassing the dynamic rule code and > language handlers I put in?**** > > -Darius (by phone)**** > > On Aug 30, 2011 1:17 PM, "McKee, Steven Jay" <[email protected]> wrote:*** > * > > Darius,**** > > **** > > CHICA is very close to finishing the upgrade to OpenMRS 1.7.x, but we’re > needing an additional method added to the LogicService interface:**** > > **** > > /****** > > * Loads a rule into memory so it can be used. It will also update the > rule *metadata* if**** > > * required.**** > > * **** > > * *@param* token the lookup key ("token") for the rule to be > loaded.**** > > * *@param* updateRule Whether or not the rule *metadata* needs to be > updated once loaded.**** > > * *@throws* LogicException if an error occurs loading a rule.**** > > */**** > > *public* *void* loadRule(String token, boolean updateRule) > *throws*LogicException; > **** > > **** > > CHICA currently has the same method in its DSS module which looks in > various places to load a rule into memory. We currently have hardcoded > places in our code to load specific rules before any other rules are > executed. We want to be able to remove the hardcoded loading of the rules > so we can be more dynamic about it. **** > > **** > > Here’s what we are proposing to do:**** > > 1. Add the new LogicService method.**** > > 2. Update the Arden parser to create Java calls that execute the > loadRule method on an inner rule before calling “eval”.**** > > logicService.loadRule("LocationAttributeLookup", false);**** > > Result result = context.eval(patient.getPatientId(), > "LocationAttributeLookup",parameters);**** > > 3. For the time being the implementation of the loadRule method in > the logic module will do nothing.**** > > 4. We will set up an AOP call for the method in our DSS module so we > can call our own loadRule to get the correct rule into memory.**** > > 5. The AOP call is a temporary fix until we can eventually get some > of our DSS code moved into logic in the future. But we’re very close to our > upgrade deadline at the moment.**** > > **** > > The “updateRule” parameter for the method is used to tell the code whether > or not the metadata about the rule should be updated. Most of the time in > normal operating conditions this will be false. The case where we would > supply true is when are class loading scheduled task is looking for new > rules. Once it finds a new rule, we want the newest metadata (and > registration) for it.**** > > **** > > Thanks,**** > > **** > > Steve McKee**** > > Children’s Health Services Research**** > > Indiana University School of Medicine**** > > Phone: 317-278-9660**** > > Email: [email protected]**** > > **** > > **** > > ** ** > _________________________________________ To unsubscribe from OpenMRS Developers' mailing list, send an e-mail to [email protected] with "SIGNOFF openmrs-devel-l" in the body (not the subject) of your e-mail. [mailto:[email protected]?body=SIGNOFF%20openmrs-devel-l]

