Spring boot and drools integration

2020-07-17 06:51发布

问题:

I'm trying to run drools 6.2.0.Final with Spring Boot 1.2.2.RELEASE. I configured drools as the documentation says. My kie-context.xml configuration file is where I keep the drools beans and looks like this:

<?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:kie="http://drools.org/schema/kie-spring"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://drools.org/schema/kie-spring http://drools.org/schema/kie-spring.xsd">

<kie:kmodule id="sample_module">
    <kie:kbase name="kbase1" packages="composition-rules">
        <kie:ksession name="ksession1" type="stateless"/>
    </kie:kbase>
</kie:kmodule>

<bean id="kiePostProcessor" class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

as i try to compile the application and run with spring-boot i get the following error:

java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6ab6cc3b: startup date [Wed Apr 15 13:57:02 CEST 2015]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:357)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:877)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.doClose(EmbeddedWebApplicationContext.java:150)
at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:836)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:342)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at skeleton.StorfinoApplication.main(StorfinoApplication.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: Unable to get all ZipFile entries: /home/lukasz/dev/skeleton/application/target/application-1.0-SNAPSHOT.jar!
at org.drools.core.util.IoUtils.indexZipFile(IoUtils.java:133)
at org.drools.compiler.kie.builder.impl.ZipKieModule.<init>(ZipKieModule.java:20)
at org.drools.compiler.kie.builder.impl.ClasspathKieProject.createInternalKieModule(ClasspathKieProject.java:186)
at org.kie.spring.KModuleBeanFactoryPostProcessor.createKieModule(KModuleBeanFactoryPostProcessor.java:189)
at org.kie.spring.KModuleBeanFactoryPostProcessor.addKieModuleToRepo(KModuleBeanFactoryPostProcessor.java:162)
at org.kie.spring.KModuleBeanFactoryPostProcessor.postProcessBeanFactory(KModuleBeanFactoryPostProcessor.java:121)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:177)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at skeleton.StorfinoApplication.main(StorfinoApplication.java:23)
... 6 more
Caused by: java.io.FileNotFoundException: /home/user-name/dev/skeleton/application/target/application-1.0-SNAPSHOT.jar! (No such file or directory)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:220)
at java.util.zip.ZipFile.<init>(ZipFile.java:150)
at java.util.zip.ZipFile.<init>(ZipFile.java:164)
at org.drools.core.util.IoUtils.indexZipFile(IoUtils.java:124)
... 21 more

The command I used for building the project is: mvn clean package and i run it as a jar file (java -jar application/target/application-1.0-SNAPSHOT.jar).

A thing that caught my attention is that the file path (the one which is not found) has an exclamation mark at the end (it is not supposed to be here). The other thing that i observed is that when i run the project in IntelijIdea ide it succeeds to build and works properly.

What could be the reason of such error?

回答1:

I tried the same and ended up building an spring-boot-starter-drools for that, because there was nothing working for me out there. I didn´t use the XML-Configuration, because the latest Spring configuration is all about doing with Java only - i would also recommend that in your case.

Suggestions:

  1. Just use the starter, as decribed in the starter or in the example project
  2. Integrating Drools into your Spring Boot-Project with this working configuration:

    @Configuration
    public class DroolsAutoConfiguration {
    
    private static final String RULES_PATH = "rules/";
    
    @Bean
    public KieFileSystem kieFileSystem() throws IOException {
        KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
        for (Resource file : getRuleFiles()) {
            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
        }        
        return kieFileSystem;
    }
    
    private Resource[] getRuleFiles() throws IOException {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
    }
    
    @Bean
    public KieContainer kieContainer() throws IOException {
        final KieRepository kieRepository = getKieServices().getRepository();
    
        kieRepository.addKieModule(new KieModule() {
            public ReleaseId getReleaseId() {
                return kieRepository.getDefaultReleaseId();
            }
        });
    
        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem()); 
        kieBuilder.buildAll();
    
        return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
    }
    
    private KieServices getKieServices() {
        return KieServices.Factory.get();
    }
    
    @Bean
    public KieBase kieBase() throws IOException {
        return kieContainer().getKieBase();
    }
    
    @Bean
    public KieSession kieSession() throws IOException {
        return kieContainer().newKieSession();
    }
    
    @Bean
    public KModuleBeanFactoryPostProcessor kiePostProcessor() {
        return new KModuleBeanFactoryPostProcessor();
    }
    }
    
  3. There are conflicts of spring-versions, because Spring Boot is based upon Spring 4.x and kie-spring depends on Spring 3.2 - i got the silliest Exceptions, till in the end I excluded all the 3.2-dependecies in my pom.xml:

    <dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>${drools.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
    </exclusions>
    </dependency>