javaspringspring-bootdroolsdrools-guvnor

Add new rules to singleton KieContainer by preserving existing rules


I am trying to add new rules to a singleton KieContainer having session persistence, in a Spring Boot project. I have implemented the programmatic approach for addition of new rules to the KieContainer but the existing rules are getting replaced everytime I update the ReleaseID of the KieContainer. What I want is to preserve the existing rules that is present in the Drools Session and add new rules to that. The updateContainer() function from my utility class is how I am making changes to the KieContainer. Any suggestions mostly welcomed. My implementation is as follows:

Configuration class:

@Configuration
public class DynamicDroolsConfig {

    private KieServices kieServices;

    @Autowired
    private IPersistentSessionService iPersistentSessionService;

    @PostConstruct
    private void init() {
        this.initDataSource();
        this.kieServices = KieServices.Factory.get();
    }

    @Bean
    public KieSession getPersistentKieSession() {
        List<SessioninfoEntity> sessioninfoEntities = iPersistentSessionService.getStoredSessionDetails();

        if (sessioninfoEntities.size() == 0) {
            return newSession();
        } else if (sessioninfoEntities.size() == 1) {
            return persistedSession(sessioninfoEntities.get(0));
        } else {
            // todo other things
            return null;
        }
    }

    @Bean
    public KieServices getKieServices() {
        return this.kieServices;
    }

    @Bean
    public KieContainer getKieContainer() {
        getFileSystem();
        KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
        KieBuilder kb = kieServices.newKieBuilder(getFileSystem()).buildAll();
        KieModule kieModule = kb.getKieModule();
        return kieServices.newKieContainer(kieModule.getReleaseId());
    }

    @Bean
    public KieFileSystem getFileSystem() {
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        return kieFileSystem;
    }

    public Environment getEnv() {
        Environment env = kieServices.newEnvironment();
        env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, Persistence.createEntityManagerFactory("org.drools.persistence.jpa"));
        env.set(EnvironmentName.TRANSACTION_MANAGER, TransactionManagerServices.getTransactionManager());
        return env;
    }

    private void initDataSource() {
        PoolingDataSource ds = new PoolingDataSource();
        ds.setUniqueName("jdbc/BitronixJTADataSource");
        ds.setClassName("com.mysql.cj.jdbc.MysqlXADataSource");
        ds.setMaxPoolSize(3);
        ds.setAllowLocalTransactions(true);
        ds.getDriverProperties().put("user", "root");
        ds.getDriverProperties().put("password", "1234");
        ds.getDriverProperties().put("URL", "jdbc:mysql://localhost:3306/drool_demo");
        ds.init();
    }

    private KieSession newSession() {
        return kieServices.getStoreServices().newKieSession(getKieContainer().getKieBase(), null, getEnv());
    }

    private KieSession persistedSession(SessioninfoEntity sessioninfoEntity) {
        return kieServices.getStoreServices().loadKieSession(sessioninfoEntity.getId(), getKieContainer().getKieBase(), null, getEnv());
    }
}

Container releaseId updation method:

@Service
public class DroolsUtilityImpl implements IDroolsUtility {

    @Autowired
    private KieFileSystem fileSystem;
    @Autowired
    private KieServices services;
    @Autowired
    private KieContainer container;

    @Override
    public void updateContainer(String rules) {

//        System.out.println("drl:\n" + rules);
        fileSystem.write("src/main/resources/rules/rule.drl", rules);
        KieBuilder kb = services.newKieBuilder(fileSystem).buildAll();
        KieModule kieModule = kb.getKieModule();
        container.updateToVersion(kieModule.getReleaseId());
    }

    @Override
    public void viewContainerRules() {

        KieBase kieBase = container.getKieBase();
        for (KiePackage kp : kieBase.getKiePackages()) {
            for (Rule rule : kp.getRules()) {
                System.out.println(rule.getName());
            }
        }
    }
}

Solution

  • I would try to regenerate the pom and increase release Id. A bit like in this example :

      KieServices ks = KieServices.Factory.get();
      ReleaseId releaseId = ks.newReleaseId("org.kie", "hello-world", "1.0");
      KieFileSystem kfs = ks.newKieFileSystem()
          .generateAndWritePomXML( releaseId )
          .write( "src/main/resources/KBase1/org/pkg1/r1.drl", createDrl( "R1" ) )
          .write( "src/main/resources/KBase1/org/pkg2/r2.drl", createDrl( "R2" ) )
          .writeKModuleXML( createKieProjectWithPackages( ks, "org.pkg1" ).toXML() );
      ks.newKieBuilder( kfs ).buildAll();
    

    taken from https://www.codota.com/web/assistant/code/rs/5c65b1cf1095a5000171b19f#L199