Question

I am using JBoss Drools. I have a business requirement as defined below. and I want to convert it into JBoss Drools DRL format.

The Business requirement : I have two sets of location. One is, locations which are visited by user previoulsy. Let's call it as X. This information is obtained at runtime. And I will have some set of locations with me and let's call it as Y. This locations: Y are predefined in the rule that means Y is static. I must have a rule such that if any of the location in X matches with any of the location in Y then it has to invoke some java code.

In algorithmic view

rule "Check if Locations X matches with Locations Y"

      When
         X: It Contains locations visted by user previosuly (obtained at runtime)
         Y: It contains some predefined locations
         Check if any location in x matches with any location in Y
     then
         call some java code here to process this.

end;

So now, how can I express the above rule in a JBoss-Drools DRL fashion? Any help on this regard is really appreciated.

Was it helpful?

Solution

Okay, I'm ready to give it a try based on your explanations. If this is not quite what you were looking for, we can work towards a more suitable solution. Also, please excuse my limited command of geography ;).

First, I'll define our data model. We have the following fact class that models locations:

package de.jannik.locationrules;

public class VisitedLocation {

    private String name;

    public VisitedLocation(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Then, we have a class that models users. We only need this for the method which you want to invoke:

package de.jannik.locationrules;

public class User {
    public void handleVisitedContinent(String continentName) {
        System.out.println("User has been to " + continentName + ".");
    }
}

Now we can describe the business requirements in terms of these model classes:

package de.jannik.drltest

import de.jannik.locationrules.VisitedLocation;
import de.jannik.locationrules.User;

global User user;

rule "User has been to Europe"

    when
        exists VisitedLocation(name in ("Berlin", "Paris", "London", "Rome"))
    then
        user.handleVisitedContinent("Europe");
end

rule "User has been to Australia"

    when
        exists VisitedLocation(name in ("Melbourne", "Sydney"))
    then
        user.handleVisitedContinent("Australia");
end

rule "User has been to America"

    when
        exists VisitedLocation(name in ("San Francisco", "New York", "Buenos Aires"))
    then
        user.handleVisitedContinent("America");
end

Here, I have formulated a number of rules that call the User.handleVisitedContent(String) method with different arguments depending on which VisitedLocations exist in the working memory. Please note that the user is not modeled explicitly in the facts. Instead, we assume that a new session is created everytime a user needs to be modified. Depending on your business requirements and performance considerations, you may want to change this to use only a single session for all users.

Here is the code I use to execute the rules I have defined:

...
@Test
public void testLocationRules() {
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource("locations.drl"), ResourceType.DRL);
    if (kbuilder.hasErrors()) {
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        System.out.println(errors.toString());
        throw new RuntimeException(errors.toString());
    }
    KnowledgeBase knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase();
    knowledgeBase.addKnowledgePackages(kbuilder.getKnowledgePackages());
    StatelessKnowledgeSession session = knowledgeBase.newStatelessKnowledgeSession();
    session.setGlobal("user", new User());
    List<VisitedLocation> facts = new ArrayList<VisitedLocation>();
    facts.add(new VisitedLocation("Berlin"));
    facts.add(new VisitedLocation("Paris"));
    facts.add(new VisitedLocation("San Francisco"));
    facts.add(new VisitedLocation("Saigon"));
    session.execute(facts);
}
...

This results in the following output:

User has been to America.
User has been to Europe.

Please let me know if this is not what you were looking for or if you need further clarification. Also, you may want to consult the Drools Expert User Guide for more explanations of Drools concepts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top