Currently I am quite happy.
This was easier as expected. When I first took a look at the JBoss Drools
Website I just got the impression, that this could be something cool, but I did
not get the point where to start? But as I said this is not the first time I am
using Drools. So I have been there and after some internet research I found
multiple examples to get some small examples running.
Enough gibberish let's start to check out other things about rules. So what I did not like about the previous rule and test was that we have to set the limit value in the test as well as in the rule. Normally such a value should be configurable, so it has to be set. Therefore, we can use global variables in Drools. Taking a look at the documentation at http://docs.jboss.org/drools/release/5.5.0.Final/drools-expert-docs/html/ch04.html#d0e4569 you get the idea behind global variabless and also some possibilities to misuse them :-).
global Double ALERTVALUE
rule "Critical value"
when
$v : SensorValue ( value > ALERTVALUE)
then
System.err.println("Critical sensor value");
end
No we can inject the value of alertValue into the rule, by using the setGlobal method of our session.
ksession.setGlobal("ALERTVALUE", 50.0);
When testing this rule, I also tried double and int as data types, as for example suggested by Jeremy, other books and some blogs. For me it did not work. I do not know why, but I got a parsing exception (unknown class).
Another thing is that we can bind variables:
rule "Critical value"
when
SensorValue ($id : sensorId)
$v : SensorValue ( value >50.0 )
then
System.err.println("Critical sensor value in " + $id);
end
As you can see, it is possible to bind the sensor id to the variable §id and use it in the consequence. This rule shows another interesting thing about rules. When firing rules, the number of fired rules is returned as result of the method call. When using this rule, I got 10000 fired rules, but I only inserted 100 sensor values. The reason for this behavior is the cross product which is the result of the join. So instead of writing rules this way, the size of the cross product should be minimized.
global Double alertValue
rule "Critical value"
when
$v : SensorValue ( value > alertValue, $id : sensorId )
then
System.err.println("Critical sensor value in " + $id);
end
Another possibility is to use the getter of the bound object.
System.err.println("Critical sensor value in " +
$v.getSensorId());
Well, there is so much more about rules and their configuration. I will extend this post in the future, but there are other things to explore, for example decision tables.
Posts mit dem Label Rule werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Rule werden angezeigt. Alle Posts anzeigen
Donnerstag, 23. Mai 2013
Drools Post 2 - The first Drool rule
I said, I will use Eclipse as IDE (or more precisely I will use Spring Tool Suite (STS) because I am using Spring quite often). Besides, Maven is required. Now lets start.
I just installed the JBoss Drools Plugin using the update site (http://download.jboss.org/drools/release/5.5.0.Final/org.drools.updatesite/). As you can see I am using 5.5.0.Final and not 6.0.0 because currently it has BETA status. Also there seems to be some problems when using Java 7, because the plugin is not working with compiled classes of the newest Java version.
After the installation of the plugin there should be some new possibilities. For example when you create a new file in your project, it should be possible to select Drools resources.
Now lets use on of these new possibilites. Lets create a new "Drools Project". I named it "drools-playground". I hate if some framework or library requires the creation of a project. Perhaps I want to use different frameworks or tools within one project... but lets see. We have to create a new Drools Runtime (seems to be some kind of library folder). After this is done we have our project. I just added the Spring nature (which works fine), but after I tried to add a Maven nature to the project nothing works :) - or perhaps I just have to wait.
It seems that Jeremy (from the book) had the same idea, so instead of creating a Drools Project, he creates a maven project from the scratch. I think, this is what I should have done from the beginning.
So lets do it... for me its always interesting which artifacts are required to get started, so I will post them here. Remember this is just to get started with drools:
<!-- Drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>knowledge-api</artifactId>
<version>${drools.version}</version>
</dependency>
I use a property to set the version of drools. Just to make it complete, here is it:
<properties>
<drools.version>5.5.0.Final</drools.version>
</properties>
This is more the way I like it. So whats next, we should start with a small example right.So what do I want to do... well because I am doing lots of stuff in production industry lets use an example from this domain. I want to monitor sensor values. So just a simple rule:
Finally I have to classes SensorValue and SensorSimulator. A sensor value has a timestamp, a value and an id. Just to make it a little bit more interesting the type of the value is generic. The sensor simulator simple creates a sensor value each time his method nextValue() is called. After I cleanup my stuff I will upload the source code, so if anyone out there reads this and wants to use the produced stuff feel free :-).
package net.meisen.sensor
import net.meisen.sensor.simulation.SensorValue
rule "Critical value"
when
$v : SensorValue ( value >50.0 )
then
System.err.println("Critical sensor value state.");
end
That was very easy. The rule is formulated using the MVFLEX Expresison Language. It consists of a package name, the required imports (in my case the POJO) and the rules. A rule contains a when part and a then part.
public class RuleTest {
private BasicSensorSimulator<Double> simulator;
private StatefulKnowledgeSession ksession;
@Before
public void init() {
simulator = new BasicSensorSimulator<Double>();
simulator.setRange(new DoubleRange(51.0, 100.0));
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("/rules
/sensor_value_rule.drl", SensorValue.class),
ResourceType.DRL);
if (kbuilder.hasErrors()) {
System.err.println(kbuilder.getErrors().toString());
fail();
}
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.
getKnowledgePackages());
ksession = kbase.newStatefulKnowledgeSession();
}
@Test
public void testRule() {
ksession.insert(simulator.nextValue());
ksession.fireAllRules();
ksession.dispose();
}
Very simple, but it does what it has to do. I get the expected warning:
Critical sensor value state.
What have I done? First I created a KnowledgeBuilder, which is responsible, as far as I understand, for loading and transforming the rules, so that the knowlege packages become available. These packages are used to create the knowledge base or more precisely to initializes it. Finally, this knowledge base can provide us with session. One important thing is that, in the example, I am using a stateful session. In contradiction to a stateless session such a session remembers changes when rules are fired and checks if such a change result in new evaluation results for already checked rules.
During the test I just insert some data into the session and trigger the rule engine to fire the different rules. Firing a rule means to check if the conditions are fulfilled and if something has to be done.As Jeremy points out: "Whenever you work with a session, it's important to always remember to use the dispose() function to dispose of it when you're done. If you don't, the garbage collector won't be able to free up the resources for you, and that means problems."
I just installed the JBoss Drools Plugin using the update site (http://download.jboss.org/drools/release/5.5.0.Final/org.drools.updatesite/). As you can see I am using 5.5.0.Final and not 6.0.0 because currently it has BETA status. Also there seems to be some problems when using Java 7, because the plugin is not working with compiled classes of the newest Java version.
After the installation of the plugin there should be some new possibilities. For example when you create a new file in your project, it should be possible to select Drools resources.
Now lets use on of these new possibilites. Lets create a new "Drools Project". I named it "drools-playground". I hate if some framework or library requires the creation of a project. Perhaps I want to use different frameworks or tools within one project... but lets see. We have to create a new Drools Runtime (seems to be some kind of library folder). After this is done we have our project. I just added the Spring nature (which works fine), but after I tried to add a Maven nature to the project nothing works :) - or perhaps I just have to wait.
It seems that Jeremy (from the book) had the same idea, so instead of creating a Drools Project, he creates a maven project from the scratch. I think, this is what I should have done from the beginning.
So lets do it... for me its always interesting which artifacts are required to get started, so I will post them here. Remember this is just to get started with drools:
<!-- Drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>knowledge-api</artifactId>
<version>${drools.version}</version>
</dependency>
I use a property to set the version of drools. Just to make it complete, here is it:
<properties>
<drools.version>5.5.0.Final</drools.version>
</properties>
This is more the way I like it. So whats next, we should start with a small example right.So what do I want to do... well because I am doing lots of stuff in production industry lets use an example from this domain. I want to monitor sensor values. So just a simple rule:
- when a sensor measures a value greater than 50.0 then show a warning message
Finally I have to classes SensorValue and SensorSimulator. A sensor value has a timestamp, a value and an id. Just to make it a little bit more interesting the type of the value is generic. The sensor simulator simple creates a sensor value each time his method nextValue() is called. After I cleanup my stuff I will upload the source code, so if anyone out there reads this and wants to use the produced stuff feel free :-).
A first rule
Now the interesting part begins. After doing the necessary POJO and programming stuff, I want to formulate the rule. First a so called DRL file has to be generated. This can either be done in the simple way, by using the Eclipse Text Editor or by using the more comfortable Eclipse PlugIn. Because I installed the plugin and I wanted to see what this plugin can do, I will use this method. I also created a folder src/main/rules to store my rules at this location. So here is the rule:package net.meisen.sensor
import net.meisen.sensor.simulation.SensorValue
rule "Critical value"
when
$v : SensorValue ( value >50.0 )
then
System.err.println("Critical sensor value state.");
end
That was very easy. The rule is formulated using the MVFLEX Expresison Language. It consists of a package name, the required imports (in my case the POJO) and the rules. A rule contains a when part and a then part.
Getting it to work
Now to test my little rule, I want to use a test. So I have an initialization and the tests.public class RuleTest {
private BasicSensorSimulator<Double> simulator;
private StatefulKnowledgeSession ksession;
@Before
public void init() {
simulator = new BasicSensorSimulator<Double>();
simulator.setRange(new DoubleRange(51.0, 100.0));
KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("/rules
/sensor_value_rule.drl", SensorValue.class),
ResourceType.DRL);
if (kbuilder.hasErrors()) {
System.err.println(kbuilder.getErrors().toString());
fail();
}
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.
getKnowledgePackages());
ksession = kbase.newStatefulKnowledgeSession();
}
@Test
public void testRule() {
ksession.insert(simulator.nextValue());
ksession.fireAllRules();
ksession.dispose();
}
Very simple, but it does what it has to do. I get the expected warning:
Critical sensor value state.
What have I done? First I created a KnowledgeBuilder, which is responsible, as far as I understand, for loading and transforming the rules, so that the knowlege packages become available. These packages are used to create the knowledge base or more precisely to initializes it. Finally, this knowledge base can provide us with session. One important thing is that, in the example, I am using a stateful session. In contradiction to a stateless session such a session remembers changes when rules are fired and checks if such a change result in new evaluation results for already checked rules.
During the test I just insert some data into the session and trigger the rule engine to fire the different rules. Firing a rule means to check if the conditions are fulfilled and if something has to be done.As Jeremy points out: "Whenever you work with a session, it's important to always remember to use the dispose() function to dispose of it when you're done. If you don't, the garbage collector won't be able to free up the resources for you, and that means problems."
Abonnieren
Posts (Atom)
