We saw in detail how instances can be built. It would however be counterproductive to build the instance each time it is needed, both in terms of resource consumption (configuration reading, memory usage) and of developments.
To overcome these drawbacks, a centralized system for building, caching and accessing the instances is provided.
The Builder
The MRulesBuilder class is the crossover point of the centralized access to the rule engine instances.
It provides methods to get the instance, by providing a limited number of input parameters. The input parameters natively recognized in the library are listed in the Java enum CustomProperties.
Builder expects minimum parameter ruleengine.uri
: It may be sufficient if it is known that the instance already exists and has been positioned.
Otherwise, the configholder.impl
parameter becomes mandatory for methods which do not directly provide the data to read. It provides the implementation to use for the IRuleEngineConfigHolder interface.
The other parameters in CustomProperties are used to configure more precisely the Builder, or are used by Config Holders.
Config Holders
Config Holders are used by the builder to instanciate the Tule Engine Factory, retrieve configuration parameters and build the instance.
Depending on settings, it’s also possible to identify the obsolescence of an instance if its configuration has been modify and to rebuild it.
The configholder.factoryimpl
parameter is mandatory and gives the Factory to use. The configholder.compilation.level
parameter is optional and allows to change compilation level (STANDARD by defaut).
A Config Holder is specified by the IRuleEngineConfigHolder interface. Two implementations are available by defaut :
- GenericRuleEngineConfigHolder : Specific implementation only allowing to instanciate the Factory and solely dedicated to Builder methods providing the data to read.
- XmlRuleEngineConfigHolder : Implementation dedicated to XML configurations. XML content can be red from a file or directly provided as a parameter. For any other data source (Db for instance), it’s possible to simply override this Class.
Base implementation imposes to provide one of thexmlconfigholder.xmlfile
orxmlconfigholder.xmlcontent
parameters to define XML content source.
JNDI access
When using MRules with an application server or a Web container, it is possible de define an access as a JNDI resource, like JDBC resources.
The JNDI factory is entirely based on the Builder and thus accepts the same parameters. It’s implemented by the MRulesFactory class.
Example of a rule engine instance declaration in Tomcat JNDI context:
<?xml version='1.0' encoding='utf-8'?> <Context> <Resource <!-- JNDI Name --> name="rules/test" <!-- Object type --> type="javax.rules.RuleSession" <!-- Optional description --> description="Test rule" <!-- Unique URI --> ruleengine.uri="rules/test" <!-- Mandatory if a Rule Session is required. If omitted a RuleSet is provided. --> ruleengine.session.type="STATELESS" <!-- MRules JNDI Factory --> factory="com.massa.mrules.jndi.MRulesFactory" <!-- Config Holder to use --> configholder.impl="com.massa.mrules.builder.XmlRuleEngineConfigHolder" <!-- Configuration parser to use --> configholder.factoryimpl="com.massa.mrules.factory.xml.RichXMLFactory" <!-- XML File where configuration is stored. Starts with "file:///" if its an absolute path. Otherwise is searched for in CLASSPATH --> xmlconfigholder.xmlfile="file:////var/rules/my_ruleset.xml" <!-- Optional: Check for configuration changes (false if omitted)? --> ruleenginebuilder.checkhash="true" <!-- Optional: protect cached instance by cloning it when requested (false if omitted)? --> ruleenginebuilder.clone="false" <!-- Optional: Compilation level: STANDARD (default if omitted) or LIGHT --> configholder.compilation.level="STANDARD" /> </Context>
Dependency injection
Since version 1.3.0, MRules integrates support for CDI (Context and Dependencies Injection) specified by Java EE 6. This functionnality is not available for the version compiled with JDK 1.5.
The @MRulesInject
annotation allows to directly inject a Rule Engine instance or a Rule Session (stateful or stateless) into a Field. The Field type determines the type of the Object to inject.
Depending on the parameters provided, the annotation will:
- Retrieve a rule engine instance / a session in the JNDI context.
- Retrieve a rule engine instance / a session from its URI (unique identifier), knowing it’s already been built.
- Build a rule engine instance / a session if needed or reuse it if already existing..
Examples :
package com.massa.mrules.demos.site; import javax.inject.Inject; import com.massa.mrules.inject.MRulesInject; import com.massa.mrules.set.IMruleExecutionSet; /** * Retrieving Rule Engine Instance from JNDI Context. */ public class InjectFromJndi { @Inject @MRulesInject( jndiName = "java:/comp/env/rules/TestRuleSet" ) private IMruleExecutionSet set; //... }
package com.massa.mrules.demos.site; import javax.inject.Inject; import javax.rules.StatelessRuleSession; import com.massa.mrules.inject.MRulesInject; import com.massa.mrules.set.IMruleExecutionSet; /** * Retrieving Rule Session from known existing URI. */ public class InjectFromUri { @Inject @MRulesInject( uri = "MySessionURI" ) private StatelessRuleSession set; //... }
package com.massa.mrules.demos.site; import javax.rules.RuleRuntime; import javax.rules.RuleSession; import com.massa.mrules.inject.MRulesInject; /** * Building new Rule Session or retrieving it if already existing. */ public class InjectBuiltSession { @Inject @MRulesInject( uri = "MySessionURI", sessionType = RuleRuntime.STATEFUL_SESSION_TYPE, configHolderImpl = "com.massa.mrules.builder.XmlRuleEngineConfigHolder", factoryImpl = "com.massa.mrules.factory.xml.RichXMLFactory", xmlFile = "com/massa/mrules/demos/site/configuration.xml" ) private RuleSession set; //... }
JSR 94 API
API specified by JSR 94 are also implemented.
MRulesBuilder implements RuleExecutionSetProvider and LocalRuleExecutionSetProvider.
MRuleAdministrator implements RuleAdministrator, MRuleRuntime implements RuleRuntime. They are accessible via the MRuleServiceProvider Class.