Google

Oct 23, 2013

Drools with Decision tables (Excel spreadsheet) tutorial

This is an extension to Drools tutorial with Maven. This externalize the rules criteria to an Excel spreadsheet license.xls. This means the age condition is supplied in the xls file under src/main/resources/drools/license.xls.

Step 1: Maven pom.xml file dependencies. Add dependencies including the decision tables.


 
<dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-core</artifactId>
 <version>5.5.0.Final</version>
</dependency>
<dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-compiler</artifactId>
 <version>5.5.0.Final</version>
</dependency>
<dependency>
 <groupId>org.drools</groupId>
 <artifactId>drools-decisiontables</artifactId>
 <version>5.5.0.Final</version>
</dependency>

Step 2: The license.xls file where rule name and age criteria are defined.



Step 3: The template file drools/license.drt under src/main/resources

 
template header
rules
age

package com.mycompany.app.drools;

import com.mycompany.app.drools.ApplicantForm;
import com.mycompany.app.drools.Applicant;
import com.mycompany.app.drools.ApplicantDao;
import com.mycompany.app.drools.ApplicantDaoImpl;

global ApplicantDao applicantDao;

template "license-rules"

  
rule "@{rules}_@{row.rowNumber}"
when
   $a : ApplicantForm();
   $applicant: Applicant( age < @{age} ) from applicantDao.findApplicant($a.getApplicantId());
then
   $a.setEligible( false );
end

end template

As you can see, @{age} and @{rules} were determined from the excel spreadsheet. The @{row.rownNumber} is excel spreadsheet row number.
Step 4: The Applicant.java, ApplicationForm.java, ApplicantDao.java, and ApplicantDaoImpl.java are same as before, but moved to a different package com.mycompany.app.drools.

Step 5: Finally, the test class ApplicantLicenseTest class that bootstraps with the xls and drt files.

 
package com.mycompany.app.drools;

import java.io.IOException;
import java.util.Iterator;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.decisiontable.ExternalSpreadsheetCompiler;
import org.drools.io.ResourceFactory;
import org.drools.io.impl.ByteArrayResource;
import org.drools.runtime.StatefulKnowledgeSession;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mvel2.optimizers.OptimizerFactory;

public class ApplicantLicenseTest
{
    
    private KnowledgeBase kbase;
    
    @Before
    public void setup() throws IOException
    {
        OptimizerFactory.setDefaultOptimizer("reflective");
        
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        loadKnowledgeBase("drools/license.xls", "drools/license.drt",
                "license", 2, 1, kbuilder);
        
        kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        
    }
    
    private void loadKnowledgeBase(String aXlsName, String aDrlName,
            String aWorksheetName, int aStartRow, int aStartCol, KnowledgeBuilder aKbuilder) throws IOException
    {
        ExternalSpreadsheetCompiler sc = new ExternalSpreadsheetCompiler();
        
        String drlstr = sc.compile(ResourceFactory.newClassPathResource(aXlsName).getInputStream(),
                aWorksheetName,
                ResourceFactory.newClassPathResource(aDrlName).getInputStream(), aStartRow, aStartCol);
        
        System.out.println(drlstr);
        
        aKbuilder.add(new ByteArrayResource(drlstr.getBytes()), ResourceType.DRL);
        
        Iterator<KnowledgeBuilderError> errors = aKbuilder.getErrors().iterator();
        if (errors.hasNext())
        {
            StringBuilder errorMsg = new StringBuilder("Error compiling rules:");
            while (errors.hasNext())
            {
                errorMsg.append("\t" + errors.next().getMessage());
            }
            
            System.out.println(errorMsg.toString());
        }
    }
    
    @Test
    public void testApplicantLicense()
    {
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.newStatefulKnowledgeSession();
        
        ApplicantForm applicant1 = new ApplicantForm();
        applicant1.setApplicantId(1);
        
        ApplicantForm applicant2 = new ApplicantForm();
        applicant2.setApplicantId(2);
        
        ksession.setGlobal("applicantDao", new ApplicantDaoImpl()); // assign the global dao
        
        ksession.insert(applicant1);
        ksession.insert(applicant2);
        ksession.fireAllRules();
        
        ksession.dispose();
        
        Assert.assertTrue(applicant1.isEligible() == false);//John is not eligible
        Assert.assertTrue(applicant2.isEligible() == true); //Peter is eligible
    }
    
}

Step 6: The output:

 
package com.mycompany.app.drools;
import com.mycompany.app.drools.ApplicantForm;
import com.mycompany.app.drools.Applicant;
import com.mycompany.app.drools.ApplicantDao;
import com.mycompany.app.drools.ApplicantDaoImpl;
global ApplicantDao applicantDao;

rule "License criteria_1"
when
   $a : ApplicantForm();
   $applicant: Applicant( age < 18 ) from applicantDao.findApplicant($a.getApplicantId());
then
   $a.setEligible( false );
end



fetched applicant: name=John, age=16
fetched applicant: name=Peter, age=20



Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home