0

On my first day to learn drools.I got this weird problem.

rule "Hello World" in drl cannot run in Controller,but working well in Junit test case. rule "Another rule" always run on both Controller and Junit test.

the code in controller and junit test are same totally.

Anyone who have idea is welcome. thanks .


Sample.drl:

package com.happylifeplat.checkin

import com.happylifeplat.checkin.managerorder.beans.RaBean1;

rule "Hello World"
   when
       $h : RaBean1( id == 1)
   then
       $h.setContent("from drl content");
       System.out.println("-----Hello World rule called  id == 1");
end

rule "Another rule"
   when
   then
       System.out.println("-----Another rule called");
end

kmodule.xml:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="ksession-rules"/>
    </kbase>
</kmodule>

RaBean1.java:

package com.happylifeplat.checkin.managerorder.beans;

public class RaBean1 {
    private int id;
    private String content;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

HelloController.java:

@RestController
@RequestMapping("/hello")
public class HelloController {

    private static KieContainer kieContainer;
    private KieSession sessionStatefull = null;

    @RequestMapping(value = "/helloworld", method = RequestMethod.GET)
    @ApiOperation(value = "hello")
    public Result metadata() {
        try {
            if (kieContainer == null) {
                kieContainer = KnowledgeSessionHelper.createRuleBase();
            }
            sessionStatefull = KnowledgeSessionHelper.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksession-rules");
            RaBean1 bean1 = new RaBean1();
            bean1.setId(1);
            bean1.setContent("default content");
            sessionStatefull.insert(bean1);
            sessionStatefull.fireAllRules();
            return new Result(CommonCode.sussess, bean1.getContent());
        } catch (Exception e) {
            return new Result(CommonCode.fail, null);
        }
    }
}

HelloControllerTest.java:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ImportResource({"classpath:spring/applicationContext.xml"})
@IntegrationTest("server.port=0")
@WebAppConfiguration
public class HelloControllerTest {
    private static final Logger log = LoggerFactory.getLogger(HelloControllerTest.class);
    private MockMvc mockMvc;
    private static KieContainer kieContainer;
    private KieSession sessionStatefull = null;

    @Before
    public void setUp() throws Exception {
//        mockMvc = MockMvcBuilders.standaloneSetup(managerOrderController).build();
    }

    @Test
    public void helloTest() throws Exception {
        if (kieContainer == null) {
            kieContainer = KnowledgeSessionHelper.createRuleBase();
        }
        sessionStatefull = KnowledgeSessionHelper.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksession-rules");
        RaBean1 bean1 = new RaBean1();
        bean1.setId(1);
        bean1.setContent("default content");
        sessionStatefull.insert(bean1);
        sessionStatefull.fireAllRules();
        System.out.println("rabean.getContent---->"+bean1.getContent());
    }
}
Rabbit
  • 480
  • 5
  • 13
  • I doubt that HelloController's method `metadata' is executed. Add a println to ascertain that the insert is executed. Also, put some code into the consequence of "Another rule" to count the facts in WM and add that number to the message. – laune Mar 15 '17 at 05:38
  • The log shows that "insert" has bean executed. – Rabbit Mar 15 '17 at 07:07
  • Add a more detail here: When I code "sessionStatefull.setGlobal(..." ,it report an error:java.lang.RuntimeException: Illegal class for global. Expected [com.happylifeplat.checkin.utils.DroolsOutputUtil], found [com.happylifeplat.checkin.utils.DroolsOutputUtil]. Looks like that the object in the project are not in drools system's space. Any operations to put beans in drl file will fail. – Rabbit Mar 15 '17 at 07:12
  • Here is another important point: When i "mvn package " the project,then use "java -jar" to run this jar file,and send http request , Everything is alright. the "Hello World" Rule run! I think it is because of my Intellj Idea.(jboss's doc recommended eclipse) – Rabbit Mar 15 '17 at 08:26
  • Use code in the consequence of the rule that does fire to list the class names of all facts in working memory. – laune Mar 15 '17 at 10:34
  • @laune how to do the "list all facts",can you show me please? – Rabbit Mar 16 '17 at 01:36
  • Iterate `kcontext.getKieRuntime().getObjects()`. – laune Mar 16 '17 at 05:24
  • Possible duplicate of [Drools doesn't work with spring-boot-devtools](https://stackoverflow.com/questions/55373809/drools-doesnt-work-with-spring-boot-devtools) – Fabio Bonfante May 13 '19 at 16:30

4 Answers4

6

Finally a friend helped me. It is because the "hot deployment". close it ,then problem solved.

It is in pom.xml:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
Rabbit
  • 480
  • 5
  • 13
  • This saved my day. Apart from mismatch in setGlobal(), even switching to stateless session did not help as classObjectType was skipping rules execution since isAssignableFrom() would fail despite source and target being the same class object. Thanks a ton for documenting this. – angel_007 Jan 09 '18 at 20:02
1

I also faced the same issue. The reason in my case was a conflict due to the dev-tools dependency. After removing the conflicted dependency, it started working for me.

Mohit Kanwar
  • 2,962
  • 7
  • 39
  • 59
Lalchand Mali
  • 211
  • 1
  • 2
  • 11
1

We can still use dev-tools by adding this linerestart.include.dools=/(drools|kie)\-.*\.jar in META-INF/spring-devtools.properties file in resources folder.

0

I removed this dependency its working

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>