Commits

Marcin Grzejszczak committed 3d8a2ef

Added the Drools Spring integration project

  • Participants
  • Parent commits fc82f1d

Comments (0)

Files changed (21)

File Drools/Spring integration/pom.xml

+<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">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>pl.grzejszczak.marcin</groupId>
+	<artifactId>drools-spring-integration</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<maven.compiler.source>1.6</maven.compiler.source>
+		<maven.compiler.target>1.6</maven.compiler.target>
+
+		<spring.version>3.1.1.RELEASE</spring.version>
+	</properties>
+	<repositories>
+		<repository>
+			<id>spring-release</id>
+			<url>http://maven.springframework.org/release</url>
+		</repository>
+	</repositories>
+
+	<dependencies>
+		<!-- Spring -->
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-core</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>13.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+		<dependency>
+            <groupId>org.drools</groupId>
+            <artifactId>drools-spring</artifactId>
+            <version>5.4.0.Final</version>
+        </dependency>
+		<dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.6.6</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.10</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+</project>

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/DroolsSpring.java

+package pl.grzejszczak.marcin.drools.springintegration;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import pl.grzejszczak.marcin.drools.springintegration.service.ProductService;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public class DroolsSpring {
+
+    public static void main(String args[]){
+        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
+        ((ProductService)applicationContext.getBean("ProductServiceImpl")).runProductLogic();
+        ((ProductService)applicationContext.getBean("NoRulesProductServiceImpl")).runProductLogic();
+
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/enums/TypeEnum.java

+package pl.grzejszczak.marcin.drools.springintegration.enums;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public enum TypeEnum {
+    MEDICAL("medical", "aaabbbccc"), ELECTRONIC("electronic", "cccbbbaaa");
+
+
+    private final String type;
+    private final String someOutputString;
+
+    private TypeEnum(String type, String someOutputString) {
+        this.type = type;
+        this.someOutputString = someOutputString;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getSomeOutputString() {
+        return someOutputString;
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/factory/ProcessingFactory.java

+package pl.grzejszczak.marcin.drools.springintegration.factory;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public interface ProcessingFactory<T, V> {
+    T createProcessingObject(V inputObject);
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/factory/drools/ProductProcessingFactory.java

+package pl.grzejszczak.marcin.drools.springintegration.factory.drools;
+
+import org.drools.runtime.StatelessKnowledgeSession;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+import pl.grzejszczak.marcin.drools.springintegration.factory.ProcessingFactory;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@Component("ProductProcessingFactory")
+public class ProductProcessingFactory implements ProcessingFactory<StatelessKnowledgeSession, Product> {
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Override
+    public StatelessKnowledgeSession createProcessingObject(Product inputObject) {
+        return (StatelessKnowledgeSession)applicationContext.getBean(inputObject.getTypeEnum().getType() + "KSession");
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/factory/nondrools/NoRulesProcessingFactory.java

+package pl.grzejszczak.marcin.drools.springintegration.factory.nondrools;
+
+import com.google.common.collect.ImmutableMap;
+import org.springframework.stereotype.Component;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.factory.ProcessingFactory;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.service.nondrools.ElectronicProductProcessingService;
+import pl.grzejszczak.marcin.drools.springintegration.service.nondrools.MedicalProductProcessingService;
+import pl.grzejszczak.marcin.drools.springintegration.service.Processor;
+
+import java.util.Map;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@Component("NoRulesProcessingFactory")
+public class NoRulesProcessingFactory  implements ProcessingFactory<Processor, Product> {
+
+    private static final Map<TypeEnum, Processor> PROCESSOR_MAP = new ImmutableMap.Builder<TypeEnum, Processor>().
+            put(TypeEnum.MEDICAL, new MedicalProductProcessingService()).
+            put(TypeEnum.ELECTRONIC, new ElectronicProductProcessingService()).
+            build();
+
+    /**
+     * By using the map we don't have any ifs
+     * @param inputObject
+     * @return
+     */
+    @Override
+    public Processor createProcessingObject(Product inputObject) {
+        return PROCESSOR_MAP.get(inputObject.getTypeEnum());
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/model/Product.java

+package pl.grzejszczak.marcin.drools.springintegration.model;
+
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public class Product {
+    private final TypeEnum typeEnum;
+    private String productName;
+
+    public Product(TypeEnum typeEnum) {
+        this.typeEnum = typeEnum;
+        productName = typeEnum.getSomeOutputString();
+    }
+
+    public TypeEnum getTypeEnum() {
+        return typeEnum;
+    }
+
+    public String getProductName() {
+        return productName;
+    }
+
+    public void setProductName(String productName) {
+        this.productName = productName;
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/Processor.java

+package pl.grzejszczak.marcin.drools.springintegration.service;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public interface Processor<T> {
+    void process(T input);
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/ProductService.java

+package pl.grzejszczak.marcin.drools.springintegration.service;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public interface ProductService {
+    void runProductLogic();
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/drools/ProductServiceImpl.java

+package pl.grzejszczak.marcin.drools.springintegration.service.drools;
+
+import org.drools.runtime.StatelessKnowledgeSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.factory.ProcessingFactory;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.service.ProductService;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@Component("ProductServiceImpl")
+public class ProductServiceImpl implements ProductService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ProductServiceImpl.class);
+
+    @Autowired
+    @Qualifier("ProductProcessingFactory")
+    ProcessingFactory<StatelessKnowledgeSession, Product> processingFactory;
+
+    @Override
+    public void runProductLogic() {
+        LOGGER.debug("Running product logic");
+        Product medicalProduct = new Product(TypeEnum.MEDICAL);
+        Product electronicProduct = new Product(TypeEnum.ELECTRONIC);
+        StatelessKnowledgeSession statelessKnowledgeSession = processingFactory.createProcessingObject(medicalProduct);
+        LOGGER.debug("Running rules for products...");
+        statelessKnowledgeSession.execute(newArrayList(medicalProduct, electronicProduct));
+        LOGGER.debug("...finished running products.");
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/nondrools/ElectronicProductProcessingService.java

+package pl.grzejszczak.marcin.drools.springintegration.service.nondrools;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.service.Processor;
+import pl.grzejszczak.marcin.drools.springintegration.utils.SomeUtil;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public class ElectronicProductProcessingService implements Processor<Product> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ElectronicProductProcessingService.class);
+
+    @Override
+    public void process(Product input) {
+        checkArgument(TypeEnum.ELECTRONIC.equals(input.getTypeEnum()), "This processing service works only for electronic devices");
+        checkArgument(!SomeUtil.replaceAWithB(input.getProductName()).equals(input.getProductName()), "The input has already been processed");
+        LOGGER.debug("Running processing for Electronic Product");
+        input.setProductName(SomeUtil.replaceAWithB(input.getProductName()));
+        LOGGER.debug(format("ELECTRONIC rule applied without Drools, product name is now equal to [%s]", input.getProductName()));
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/nondrools/MedicalProductProcessingService.java

+package pl.grzejszczak.marcin.drools.springintegration.service.nondrools;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.service.Processor;
+import pl.grzejszczak.marcin.drools.springintegration.utils.SomeUtil;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public class MedicalProductProcessingService implements Processor<Product> {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MedicalProductProcessingService.class);
+
+    @Override
+    public void process(Product input) {
+        checkArgument(TypeEnum.MEDICAL.equals(input.getTypeEnum()), "This processing service works only for medical devices");
+        checkArgument(!SomeUtil.replaceAWithB(input.getProductName()).equals(input.getProductName()), "The input has already been processed");
+        LOGGER.debug("Running processing for Medical Product");
+        input.setProductName(SomeUtil.replaceAWithB(input.getProductName()));
+        LOGGER.debug(format("MEDICAL rule applied without Drools, product name is now equal to [%s]", input.getProductName()));
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/nondrools/NoRulesProductServiceImpl.java

+package pl.grzejszczak.marcin.drools.springintegration.service.nondrools;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.service.Processor;
+import pl.grzejszczak.marcin.drools.springintegration.service.ProductService;
+
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@Component("NoRulesProductServiceImpl")
+public class NoRulesProductServiceImpl implements ProductService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(NoRulesProductServiceImpl.class);
+
+    @Autowired
+    @Qualifier("ProductProcessingService")
+    private Processor<List<Product>> productProcessingService;
+
+    @Override
+    public void runProductLogic() {
+        LOGGER.debug("Running product logic without Drools");
+        Product medicalProduct = new Product(TypeEnum.MEDICAL);
+        Product electronicProduct = new Product(TypeEnum.ELECTRONIC);
+        LOGGER.debug("Running rules for products...");
+        productProcessingService.process(newArrayList(medicalProduct, electronicProduct));
+        LOGGER.debug("...finished running products.");
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/service/nondrools/ProductProcessingService.java

+package pl.grzejszczak.marcin.drools.springintegration.service.nondrools;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import pl.grzejszczak.marcin.drools.springintegration.factory.ProcessingFactory;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.service.Processor;
+
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@Component("ProductProcessingService")
+public class ProductProcessingService implements Processor<List<Product>> {
+
+    @Autowired
+    @Qualifier("NoRulesProcessingFactory")
+    private ProcessingFactory<Processor, Product> processingFactory;
+
+    @Override
+    public void process(List<Product> input) {
+        for(Product product : input){
+            Processor<Product> processor = processingFactory.createProcessingObject(product);
+            processor.process(product);
+        }
+    }
+}

File Drools/Spring integration/src/main/java/pl/grzejszczak/marcin/drools/springintegration/utils/SomeUtil.java

+package pl.grzejszczak.marcin.drools.springintegration.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+public final class SomeUtil {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SomeUtil.class);
+
+    private SomeUtil(){
+        throw new UnsupportedOperationException("SomeUtil is a utility class that should not be instantiated");
+    }
+
+    public static String replaceAWithB(String input){
+        LOGGER.debug("Executing some logic");
+        return input.toLowerCase().replaceAll("a", "b");
+    }
+
+}

File Drools/Spring integration/src/main/resources/applicationContext.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
+                           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+    <import resource="classpath:drools-context.xml"/>
+    <!-- Show Spring where to search for the beans (in which packages) -->
+    <context:component-scan base-package="pl.grzejszczak.marcin.drools.springintegration" />
+
+</beans>

File Drools/Spring integration/src/main/resources/drools-context.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:drools="http://drools.org/schema/drools-spring"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+		http://drools.org/schema/drools-spring http://drools.org/schema/drools-spring.xsd">
+
+    <!-- KNOWLEDGE BASE FOR A GIVEN TYPE -->
+    <drools:kbase id="productsKBase">
+        <drools:resources>
+            <drools:resource type="DRL"
+                             source="classpath:rules/products.drl"/>
+        </drools:resources>
+    </drools:kbase>
+
+    <drools:ksession id="productsKSession" name="productsKSession" type="stateless" kbase="productsKBase"/>
+    <alias name="productsKSession" alias="electronicKSession"/>
+    <alias name="productsKSession" alias="medicalKSession"/>
+
+</beans>

File Drools/Spring integration/src/main/resources/log4j.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+	<!-- Appenders -->
+	<appender name="console" class="org.apache.log4j.ConsoleAppender">
+		<param name="Target" value="System.out" />
+		<layout class="org.apache.log4j.PatternLayout">
+			<param name="ConversionPattern" value="%d %-5p [%t] %c:%L %m%n" />
+		</layout>
+	</appender>
+	
+	<!-- Application Loggers -->
+	<logger name="pl.grzejszczak.marcin">
+		<level value="DEBUG" />
+	</logger>
+	
+	<!-- 3rdparty Loggers -->
+	<logger name="org.springframework.core">
+		<level value="INFO" />
+	</logger>
+	
+	<logger name="org.springframework.context">
+		<level value="INFO" />
+	</logger>
+
+
+	<!-- Root Logger -->
+	<root>
+		<priority value="INFO" />
+		<appender-ref ref="console" />
+	</root>
+	
+</log4j:configuration>

File Drools/Spring integration/src/main/resources/rules/products.drl

+package pl.grzejszczak.marcin
+
+import org.slf4j.LoggerFactory
+import pl.grzejszczak.marcin.drools.springintegration.DroolsSpring
+import pl.grzejszczak.marcin.drools.springintegration.model.Product
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum
+
+import function pl.grzejszczak.marcin.drools.springintegration.utils.SomeUtil.replaceAWithB
+import function org.drools.core.util.StringUtils.isEmpty
+
+
+rule "MEDICAL rule"
+	dialect "mvel"
+when
+     $product : Product( typeEnum == TypeEnum.MEDICAL, productName != replaceAWithB($product.typeEnum.someOutputString) )
+then
+     modify ($product) {productName = replaceAWithB($product.typeEnum.someOutputString)}
+     LoggerFactory.getLogger(DroolsSpring.class).debug(String.format("MEDICAL rule applied, product name is now equal to [%s]", $product.productName))
+end
+
+rule "ELECTRONIC rule"
+	dialect "mvel"
+when
+     $product : Product( typeEnum == TypeEnum.ELECTRONIC, productName != replaceAWithB($product.typeEnum.someOutputString) )
+then
+     modify ($product) {productName = replaceAWithB($product.typeEnum.someOutputString)}
+     LoggerFactory.getLogger(DroolsSpring.class).debug(String.format("ELECTRONIC rule applied, product name is now equal to [%s]", $product.productName))
+end

File Drools/Spring integration/src/test/java/pl/grzejszczak/marcin/drools/springintegration/service/NoRulesProductServiceImplTest.java

+package pl.grzejszczak.marcin.drools.springintegration.service;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.utils.SomeUtil;
+
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static java.lang.String.format;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
+public class NoRulesProductServiceImplTest {
+
+    @Autowired
+    @Qualifier("ProductProcessingService")
+    private Processor<List<Product>> productProcessingService;
+
+
+    /**
+     * Test is not run in perfect isolation - the purpose is to show the outcome of processing without Drools
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testRunProductLogic() throws Exception {
+        Product medicalProduct = new Product(TypeEnum.MEDICAL);
+        Product electronicProduct = new Product(TypeEnum.ELECTRONIC);
+        String initialMedicalProductName = medicalProduct.getProductName();
+        String initialElectronicProduct = electronicProduct.getProductName();
+        System.out.println(format("Initial productName for Medical [%s]", medicalProduct.getProductName()));
+        System.out.println(format("Initial productName for Electronic [%s]", electronicProduct.getProductName()));
+
+        productProcessingService.process(newArrayList(medicalProduct, electronicProduct));
+
+        String finalMedicalProduct = medicalProduct.getProductName();
+        String finalElectronicProduct = electronicProduct.getProductName();
+        assertNotSame(finalMedicalProduct, initialMedicalProductName);
+        assertNotSame(finalElectronicProduct, initialElectronicProduct);
+        assertEquals(SomeUtil.replaceAWithB(initialMedicalProductName), finalMedicalProduct);
+        assertEquals(SomeUtil.replaceAWithB(initialElectronicProduct), finalElectronicProduct);
+
+        System.out.println(format("Final productName for Medical [%s]", medicalProduct.getProductName()));
+        System.out.println(format("Final productName for Electronic [%s]", electronicProduct.getProductName()));
+    }
+}

File Drools/Spring integration/src/test/java/pl/grzejszczak/marcin/drools/springintegration/service/ProductServiceImplTest.java

+package pl.grzejszczak.marcin.drools.springintegration.service;
+
+import org.drools.runtime.StatelessKnowledgeSession;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import pl.grzejszczak.marcin.drools.springintegration.enums.TypeEnum;
+import pl.grzejszczak.marcin.drools.springintegration.factory.ProcessingFactory;
+import pl.grzejszczak.marcin.drools.springintegration.model.Product;
+import pl.grzejszczak.marcin.drools.springintegration.utils.SomeUtil;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static java.lang.String.format;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: mgrzejszczak
+ * Date: 14.01.13
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
+public class ProductServiceImplTest {
+
+    @Autowired
+    @Qualifier("ProductProcessingFactory")
+    ProcessingFactory<StatelessKnowledgeSession, Product> processingFactory;
+
+    /**
+     * Test is not run in perfect isolation - the purpose is to show the outcome of processing with Drools
+     * @throws Exception
+     */
+    @Test
+    public void testRunProductLogic() throws Exception {
+        Product medicalProduct = new Product(TypeEnum.MEDICAL);
+        Product electronicProduct = new Product(TypeEnum.ELECTRONIC);
+        String initialMedicalProductName = medicalProduct.getProductName();
+        String initialElectronicProduct = electronicProduct.getProductName();
+        System.out.println(format("Initial productName for Medical [%s]", medicalProduct.getProductName()));
+        System.out.println(format("Initial productName for Electronic [%s]", electronicProduct.getProductName()));
+
+        StatelessKnowledgeSession statelessKnowledgeSessionForMedical = processingFactory.createProcessingObject(medicalProduct);
+        StatelessKnowledgeSession statelessKnowledgeSessionForElectronic = processingFactory.createProcessingObject(electronicProduct);
+        assertTrue(statelessKnowledgeSessionForMedical == statelessKnowledgeSessionForElectronic);
+        System.out.println("References for stateless sessions are the same, executing rules...");
+
+        statelessKnowledgeSessionForMedical.execute(newArrayList(medicalProduct, electronicProduct));
+
+        String finalMedicalProduct = medicalProduct.getProductName();
+        String finalElectronicProduct = electronicProduct.getProductName();
+        assertNotSame(finalMedicalProduct, initialMedicalProductName);
+        assertNotSame(finalElectronicProduct, initialElectronicProduct);
+        assertEquals(SomeUtil.replaceAWithB(initialMedicalProductName), finalMedicalProduct);
+        assertEquals(SomeUtil.replaceAWithB(initialElectronicProduct), finalElectronicProduct);
+
+        System.out.println(format("Final productName for Medical [%s]", medicalProduct.getProductName()));
+        System.out.println(format("Final productName for Electronic [%s]", electronicProduct.getProductName()));
+    }
+}