Search code examples
springspring-bootdrools

Can I store drools .drl files in bitbucket repository and access them during runtime using spring boot


I would like to store drools .drl files in bitbucket (instead of keeping them inside the application classpath) and access them during using spring boot. In this way if there are any changes in rules I do not need to repackage the application and redeploy.


Solution

  • Beans by default are singleton, so they're only created once and that's it. I haven't worked with Drools personally, but making HTTP requests just to get a file could potentially by costly/slow.

    So my suggestion would be to try and utilize Spring Cloud Config somehow and store the rules in your there in application.yml

    So for example, you would define the below in your Git Spring config repo:

    drools:
      myRule: >
        package com.baeldung.drools.rules;
    
        import com.baeldung.drools.model.Applicant;
    
        global com.baeldung.drools.model.SuggestedRole suggestedRole;
    
        dialect  "mvel"
    
        rule "Suggest Manager Role"
            when
                Applicant(experienceInYears > 10)
                Applicant(currentSalary > 1000000 && currentSalary <= 
                2500000)
            then
                suggestedRole.setRole("Manager");
        end
    

    You would then define a ConfigurationProperties bean like:

    @Configuration
    @ConfigurationProperties("drools")
    public class ConfigProperties {
        private String myRule;
    
        // getters/setters ...
    }
    

    Since we're going to utilize Spring Cloud Config, you'll want to add @RefreshScope

    @Configuration
    @ConfigurationProperties("drools")
    @RefreshScope
    public class ConfigProperties {
        private String myRule;
    
        // getters/setters ...
    }
    

    So now whenever you make changes in your config repo, it should get reflected in your application without having to re-deploy with updated files.

    I don't know how you're constructing your Drool bean, but my assumption is you're likely passing in an InputStream so simple convert the String to an InputStream:

    @Configuration
    public class MyDroolConfig {
        private final ConfigProperties properties;
    
        ConfigProperties(ConfigProperties properties) {
            this.properties = properties;
        }
    
        @Bean
        public MyRuleObject myRuleObject() {
            try (InputStream in = new ByteArrayInputStream(properties.getMyRule().getBytes())) {
                // do something with the rule
            }
        }
    }