Storing configuration

Two ways of providing configuration to the rule engine are available:

  • Reading a file (with an absolute path or within the CLASSPATH)
  • Directly providing the XML content. This option is more test oriented.

Great are the chances that the application will store the configuration by other means, such as a database. It’s of course possible and facilitated by utilities. Configuration retrieval from DB will be encapsulated with an implementation of IRuleEngineConfigHolder. The abstract implementation AbstractRuleEngineConfigHolder, performing generic operations, is provided. Simply extend it with your own implementation.

Let’s consider that the rule engine configuration is stored in a DB table, with three columns:

  • A unique code.
  • A last update date.
  • The XML content.

The MyDatabaseXmlConfigHolder class will have to override / implement three methods:

  • init : Holder initialization with the “MyDatabaseXmlConfigHolder.code” parameter, containing the code.
  • getConfigHash : returning a String allowing to identify changes in configuration. Here, last update date is perfect.
  • build : building or retrieving the engine.

Example of implementation, redirecting DB access to the DBService class:

package com.massa.mrules.demos.site;

import java.io.StringReader;
import java.util.Map;

import com.massa.mrules.MRulesMessages;
import com.massa.mrules.builder.AbstractRuleEngineConfigHolder;
import com.massa.mrules.exception.MConfigurationException;
import com.massa.mrules.factory.xml.IRuleExecutionSetXMLFactory;
import com.massa.mrules.factory.xml.XMLMConfigurationException;
import com.massa.mrules.set.IMruleExecutionSet;
import com.massa.util.MessageInfo;
import com.massa.util.StringUtils;

/**
 * Example Config holder for retrieving configuration XML from database.
 * The table storing the XML is supposed to have (at least) these fields:
 *  - A code (unique identifier)
 *  - A last updated date
 *  - The XML content
 *
 *  The configholder must be provided one parameter: the target configuration code.
 */
public class MyDatabaseXmlConfigHolder extends AbstractRuleEngineConfigHolder {

	private String code;

	public MyDatabaseXmlConfigHolder() {
		super();
	}

	/**
	 * Initializes the config holder with the code parameter.
	 */
	@Override
	public void init(final Map<String, String> parameters) throws MConfigurationException {
		super.init(parameters);
		this.code = parameters.get("MyDatabaseXmlConfigHolder.code");
		if (StringUtils.isEmpty(this.code)) {
			throw new MConfigurationException(new MessageInfo(
					MRulesMessages.MRE_NULL_PARAMETER, "MyDatabaseXmlConfigHolder.code"));
		}
	}

	/**
	 * Returns the last updated date from DB.
	 */
	public String getConfigHash() throws XMLMConfigurationException {
		return Long.toString(DBService.getLastUpdateDate(this.code).getTime());
	}

	/**
	 * Builds or retrieves the rule set.
	 */
	public IMruleExecutionSet build() throws MConfigurationException {
		final String xmlContent = DBService.getXmlContent(this.code);
		final IRuleExecutionSetXMLFactory factory = (IRuleExecutionSetXMLFactory) this.getFactory();
		return factory.read(new StringReader(xmlContent));
	}
}

After this, retrieving the engine instance is done in a standard way, for example using injection:

package com.massa.mrules.demos.site;

import javax.inject.Inject;

import com.massa.mrules.inject.InjectProperty;
import com.massa.mrules.inject.MRulesInject;
import com.massa.mrules.set.IMruleExecutionSet;

/**
 * Building new Rule Engine from DB or retrieving it if already existing.
 */
public class InjectBuiltEngineFromDb {
    @Inject
    @MRulesInject(
        uri = "MyDbSessionURI",
        configHolderImpl = "com.massa.mrules.demos.site.MyDatabaseXmlConfigHolder",
        factoryImpl = "com.massa.mrules.factory.xml.RichXMLFactory",
        //allows to define properties to provide to the Rule Engine Builder
        //which are not natively recognized.
        properties = {
        		@InjectProperty(
        			property = "MyDatabaseXmlConfigHolder.code",
        			value = "MY_CODE"
        		)
        }
    )
    private IMruleExecutionSet set;

    //...
}