How-To #3: Spring Integration

Introduction

This article will show you how to integrate MRules in a project based on Spring. More precisely, we will see here how to use dependency injection with MRules and Spring.

Dependency injection

Dependency injection is a mechanism allowing to implement inversion of control. Programs using dependency injection are loosely coupled, as dependencies between software components are resolved dynamically at runtime instead of being hard coded and static.

MRules supports native CDI specified by Java EE 6 since version 1.3.0. But the Spring implementation is more powerful and can be used with JDK 1.5.

So the version 1.9.0 of MRules is shipped with a brand new extension, providing support for Spring dependency injection. See below how to use it.

Add extension to you project

The extension is shipped as a Maven dependency. A transitive dependency allows to retrieve the library core. Only one dependency declaration is necessary.

POM example for Maven :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <dependencies>
        <!-- Adding dependency -->
        <dependency>
            <groupId>com.massa.mrules.extensions</groupId>
            <artifactId>spring</artifactId>
            <version>1.9.0</version>
        </dependency>
    </dependencies>
</project>

Annotation Configuration

If you are using on your project the new annotation-oriented way to configure Spring (which is in my opinion far more elegant than the old fashioned XML files) then you will have two solutions available to integrate MRules :

With the factory

In the Spring configuration class, you will have to declare a Bean returning an instance of the MRules factory. You can extend the factory class in order to read configuration from external configuration file, database, or any other way. Then Spring will automatically use the factory instance to instanciate the rule engine.
Example :

package com.massa.mrules.demos.spring;

public class MRulesSpringConfig {
    /**
    * Creates a rule engine, managed by Spring via the MRules Factory Bean.
    */
    @Bean
    public MRulesFactoryBean getRuleEngine() throws MConfigurationException {
        final MRulesFactoryBean fact = new MRulesFactoryBean();
        fact.setUri("TEST_SPRING");
        fact.setFactoryImpl(RichXMLFactory.class.getName());
        fact.setConfigHolderImpl(XmlRuleEngineConfigHolder.class.getName());
        fact.setXmlFile("rules.xml");
        return fact;
    }
}

Then, just use your rule engine in your module !

package com.massa.mrules.demos.spring;
public class MRulesSpring {
/**
* Spring will inject your rule engine instance in this field at runtime.
*/
@Autowired
protected IMruleExecutionSet ruleEngine;

// Use the rule engine ...
}

Without the factory

It’s almost the same as the factory way, but you instanciate your rule engine directly in the Spring config class instead of delegating this operation to the factory. And you use you rule engine instance the same way.

It’s a little less flexible, but may be enough depending on the context.

package com.massa.mrules.demos.spring;

public class MRulesSpringConfig {
    /**
    * Creates a rule engine, managed by Spring via the MRules Factory Bean.
    */
    @Bean
    public IMruleExecutionSet getRuleEngine() throws MConfigurationException {
        final InputStream xml = ResourceLoader.getResourceAsStream("rules.xml");
        final RichXMLFactory factory = new RichXMLFactory();
        return factory.read(xml);
    }
}

XML Configuration

If your Spring project is configured using XML, you will have no difficulties to integrate MRules. Just declare a bean in your Spring context configuration, as follow :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- Configures rule engine, for Spring XML Demo -->
    <bean id="ruleEngine" class="com.massa.mrules.extensions.spring.MRulesFactoryBean">
        <property name="uri" value="spring test" />
        <property name="configHolderImpl" value="com.massa.mrules.builder.XmlRuleEngineConfigHolder" />
           <property name="factoryImpl" value="com.massa.mrules.factory.xml.RichXMLFactory" />
        <property name="xmlFile" value="rules.xml" />
        <property name="compilationLevel" value="LIGHT" />
    </bean>
</beans>

Then, just use your rule engine in your module, with the @Autowired annotation, or with the XML IOC configuration.

Demo

A demo, which can be found in the download page, illustrates all the examples above.