[id='first-rule-project_{context}']
= First Rule Project

This guide walks you through the process of creating a simple Drools application project.

== Prerequisites

* https://adoptium.net[JDK] {java-version}+ with `JAVA_HOME` configured appropriately
* https://maven.apache.org/download.html[Apache Maven] {maven-version}+ 
* Optionally, an IDE, such as IntelliJ IDEA, VSCode or Eclipse

== Creating a project with maven archetype

Create a project with the following command.

[source,shell,subs=attributes+]
----
mvn archetype:generate -DarchetypeGroupId=org.kie -DarchetypeArtifactId=kie-drools-exec-model-ruleunit-archetype -DarchetypeVersion={drools-version}
----

During the command execution, input property values interactively. 
[source,subs=attributes+]
----
Define value for property 'groupId': org.example
Define value for property 'artifactId': my-project
Define value for property 'version' 1.0-SNAPSHOT: : 
Define value for property 'package' org.example: : 
...
 Y: : Y
...
[INFO] BUILD SUCCESS
----

Now your first rule project is created. Let's look into the project.

Firstly, `pom.xml`.
[source,xml]
----
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-ruleunits-engine</artifactId>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-model-compiler</artifactId>
    </dependency>
----
They are required dependencies for executable model with rule unit use cases.

[NOTE]
====
You can still use traditional Drools 7 style rules without rule unit. In this case, use `kie-drools-exec-model-archetype`.
====

The archetype contains one DRL file as an example `src/main/resources/org/example/rules.drl`.

[source]
----
package org.example;

unit MeasurementUnit;

rule "will execute per each Measurement having ID color"
when
	/measurements[ id == "color", $colorVal : val ]
then
	controlSet.add($colorVal);
end

query FindColor
    $m: /measurements[ id == "color" ]
end
----
This rule checks incoming `Measurement` data and stores its value in a global variable `controlSet` when it's color information.

`when` part implements the pattern matching and `then` part implements the action when the conditions are met.

Next, find `src/main/java/org/example/MeasurementUnit.java` that is specified as `unit MeasurementUnit` in the rule. It is called `rule unit` that groups data sources, global variables and DRL rules.

[source,java]
----
public class MeasurementUnit implements RuleUnitData {

    private final DataStore<Measurement> measurements;
    private final Set<String> controlSet = new HashSet<>();

    ...
----

`/measurements` in `rules.drl` is bound to the `measurements` field in `MeasurementUnit`. So you know that the inserted data type is `Measurement`. This class also defines a global variable `controlSet`.

Then, `src/main/java/org/example/Measurement.java` is a Java bean class used in the rule. Such an object is called `Fact`.

Finally, `src/test/java/org/example/RuleTest.java` is the test case that executes the rule. You can learn the basic API usage that is used in your own applications.

[source,java]
----
        MeasurementUnit measurementUnit = new MeasurementUnit();

        RuleUnitInstance<MeasurementUnit> instance = RuleUnitProvider.get().createRuleUnitInstance(measurementUnit);
----
Create a `MeasurementUnit` instance. Then create a `RuleUnitInstance` with the `MeasurementUnit` instance using `RuleUnitProvider`.

[source,java]
----
        measurementUnit.getMeasurements().add(new Measurement("color", "red"));
        measurementUnit.getMeasurements().add(new Measurement("color", "green"));
        measurementUnit.getMeasurements().add(new Measurement("color", "blue"));
----
Add `Measurement` facts into `measurementUnit.measurements`. It means the facts are inserted into {RULE_ENGINE}.

[source,java]
----
        List<Measurement> queryResult = instance.executeQuery("FindColor").stream().map(tuple -> (Measurement) tuple.get("$m")).collect(toList());
----
Execute a query named `FindColor`. When you execute a query, rules that are matched with inserted facts are automatically fired. If you want to only fire rules without a query, you can call `instance.fire()` instead.

[source,java]
----
        instance.dispose();
----
At the end, call `dispose()` to release resources retained by the `RuleUnitInstance`.

Let's run the test with `mvn clean test`.
----
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.example.RuleTest
2022-06-13 12:49:56,499 [main] INFO  Creating RuleUnit
2022-06-13 12:49:56,696 [main] INFO  Insert data
2022-06-13 12:49:56,700 [main] INFO  Run query. Rules are also fired
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.411 s - in org.example.RuleTest
----

Now you can add your own rules and facts to this project!

[NOTE]
====
The rule project requires code generation that is triggered by mvn compile phase. If you directly run `RuleTest.java` in IDE, you may need to run `mvn compile` first.
====
