Accéder aux instances

Nous avons vu en détail comment les instances peuvent être construites. Il serait cependant contre productif de construire l’instance à chaque fois qu’elle doit être utilisée, autant en termes de consommation de ressources (lecture de la configuration, utilisation mémoire) que de développements.

Pour palier à ces inconvénients, un système centralisé de construction, mise en cache et accès aux instances est fourni.

Le Builder

La classe MRulesBuilder est le point d’articulation de l’accès centralisé aux instances de moteurs de règles.

Il fournit des méthodes permettant d’obtenir l’instance, en lui fournissant un nombre limité de paramètres d’entrée. Les paramètres d’entrée connus nativement dans la librairie sont listés dans l’enum Java CustomProperties.

Le Builder attend à minima le paramètre ruleengine.uri : Il peut être suffisant si l’on sait que l’instance existe déjà et a été positionnée.

Sinon, le paramètre configholder.impl devient obligatoire pour les méthodes ne fournissant pas directement les données à lire. Il donne l’implémentation à utiliser de l’interface IRuleEngineConfigHolder.

Les autres paramètres présents dans CustomProperties permettent soit de configurer plus finement le Builder, soit sont utilisés par les Config Holders.

Les Config Holders

Les Config Holders sont utilisés par le builder pour instancier la Fabrique de moteur de règles, récupérer les données de configuration et pour construire l’instance.

Selon le paramétrage, ils permettent aussi d’identifier l’obsolescence d’une instance si sa configuration a été modifiée et de la reconstruire.

Le paramètre configholder.factoryimpl est obligatoire et donne la Fabrique à utiliser. Le paramètre configholder.compilation.level est facultatif et permet de changer le niveau de compilation (STANDARD par défaut).

Un Config Holder doit implémenter l’interface IRuleEngineConfigHolder. Deux implémentations sont fournies par défaut :

  • GenericRuleEngineConfigHolder : Implémentation spécifique ne permettant que d’instancier la Fabrique désirée et destinée uniquement aux méthodes du Builder fournissant directement les données à lire.
  • XmlRuleEngineConfigHolder : Implémentation dédiée aux configurations XML. Le contenu XML peut être soit lu depuis un fichier soit transmis directement en paramètre. Pour toute autre source de données (BDD par exemple), il est possible de surcharger simplement cette classe.
    L’implémentation de base impose de fournir soit le paramètre xmlconfigholder.xmlfile soit xmlconfigholder.xmlcontent pour définir la source du contenu XML.

L’accès JNDI

En cas d’utilisation de MRules sur un serveur d’application ou sur un conteneur Web, il est possible de définir un accès en tant que ressource JNDI, à l’instar des ressources JDBC.

La Fabrique JNDI se base intégralement sur le Builder et accepte donc les mêmes paramètres. Il s’agit de la classe MRulesFactory.

Exemple de déclaration d’une instance de moteur de règles dans le contexte JNDI pour Tomcat :

<?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> 

 

L’injection de dépendances

MRules intègre depuis la version 1.3.0 le support de CDI (Context and Dependencies Injection) spécifié par Java EE 6. Cette fonctionnalité n’est pas disponible pour la version compilée par le JDK 1.5.

L’annotation @MRulesInject permet d’injecter directement dans une variable soit une instance du moteur de règles, soit une session (stateful ou stateless). Le type de la variable permet de déterminer le type d’objet à injecter.

Selon les paramètres transmis à l’annotation, elle permet de:

  • Récupérer une instance de moteur de règle / une session dans le contexte JNDI.
  • Récupérer une de moteur de règle / une session par son URI (identifiant unique) sachant qu’elle a été construite auparavant.
  • Construire si besoin une de moteur de règle / une session ou la réutiliser si déjà existante.

Exemples :

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;

    //...
}

 

Les API JSR 94

Les API définies par la JSR sont intégralement implémentées.

MRulesBuilder implémente RuleExecutionSetProvider et LocalRuleExecutionSetProvider.

MRuleAdministrator implémente RuleAdministrator, MRuleRuntime implémente RuleRuntime. Ils peuvent être accédés par la classe MRuleServiceProvider.