Skip to content

SabreOSS/yare

Repository files navigation

YARE - Rules Engine in Plain Java

Build Status Maven Central

YARE (Yet Another Rules Engine) is a rule engine written in Java. It is an approach to implement an Expert System which is reliable, fast and full of capabilities.

Why Yet Another Rules Engine?

Beyond the advantages of business rules engines YARE makes its own contribution to user experience:

  • YARE is significantly faster than other rules engines for single-type collection input (e.q. List<Flight>).
  • YARE allows for sequential evaluation, which is useful when it comes to modifying facts during execution.
  • YARE allows for function evaluation in condition segment of rule.
  • YARE is using three-valued logic (true/false/null).
  • YARE provides rule converters for XML, JSON and YAML.

Getting Started

To start playing with YARE just add the dependency to com.sabre.oss.yare:yare-engine:

Maven

<dependency>
    <groupId>com.sabre.oss.yare</groupId>
    <artifactId>yare-engine</artifactId>
    <version>${yare.version}</version>
</dependency>

Gradle

dependencies {
  compile "com.sabre.oss.yare:yare-engine:$yareVersion"
}

Example

First step towards evaluation using the rule engine is to define a rule.

We can do it using:

  • Java DSL
Rule rule = RuleDsl.ruleBuilder()
                .name("Should match flight with first class of service")
                .fact("flightFact", com.sabre.oss.yare.example.fact.Flight.class)
                .predicate(
                        equal(
                                value("${flightFact.classOfService}"),
                                value("First Class")
                        )
                )
                .action("collect",
                        param("context", value("${ctx}")),
                        param("fact", value("${flightFact}")))
                .build();
  • XML
<Rule xmlns="http://www.sabre.com/schema/oss/yare/rules/v1">
    <Attribute name="ruleName" value="Should match flight with first class of service" type="String"/>
    <Fact name="flightFact" type="com.sabre.oss.yare.example.fact.Flight"/>
    <Predicate>
        <Operator type="equal">
            <Value>${flightFact.classOfService}</Value>
            <Value>First Class</Value>
        </Operator>
    </Predicate>
    <Action name="collect">
        <Parameter name="context">
            <Value>${ctx}</Value>
        </Parameter>
        <Parameter name="fact">
            <Value>${flightFact}"</Value>
        </Parameter>
    </Action>
</Rule>
  • JSON
{
  "attributes" : [ {
    "name" : "ruleName",
    "value" : "Should match flight with first class of service",
    "type" : "String"
  } ],
  "facts" : [ {
    "name" : "flightFact",
    "type" : "com.sabre.oss.yare.example.fact.Flight"
  } ],
  "predicate" : {
    "equal" : [ {
      "value" : "${flightFact.classOfService}"
    }, {
      "value" : "First Class"
    } ]
  },
  "actions" : [ {
    "name" : "collect",
    "parameters" : [ {
      "name" : "context",
      "value" : "${ctx}"
    }, {
      "name" : "fact",
      "value" : "${flightFact}"
    } ]
  } ]
}
  • YAML
attributes:
- name: "ruleName"
  value: "Should match flight with first class of service"
  type: "String"
facts:
- name: "flightFact"
  type: "com.sabre.oss.yare.example.fact.Flight"
predicate:
  equal:
  - value: "${flightFact.classOfService}"
  - value: "First Class"
actions:
- name: "collect"
  parameters:
  - name: "context"
    value: "${ctx}"
  - name: "fact"
    value: "${flightFact}"

As you can see we operate on Flight fact so let's define it too.

public class Flight {
        private String destination;
        private String classOfService;

        // getters and setters
}

Since we are using collect action we have to provide implementation as well.

public class Action {
        public void collect(List<Flight> result, Flight fact) {
            result.add(fact);
        }
}

Last, but certainly not least, we need to create the rules engine itself. Exactly as shown below.

RulesEngine rulesEngine = new RulesEngineBuilder()
                .withRulesRepository((uri) -> Collections.singletonList(rule))
                .withActionMapping("collect", method(new Action(), (action) -> action.collect(null, null)))
                .build()

The only thing left is to evaluate our example.

RuleSession ruleSession = rulesEngine.createSession("ruleSet");
List<Flight> result = ruleSession.execute(new ArrayList(), flights);

For more information about how to use YARE please read YARE User's Guide and check yare-examples module.

Contributing

We accept pull request via GitHub. Here are some guidelines which will make applying PRs easier for us:

  • No tabs. Please use spaces for indentation.
  • Respect the code style.
  • Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change.
  • Provide JUnit tests for your changes and make sure they don't break anything by running mvn clean verify.

See CONTRIBUTING document for more details.

JDK support policy

YARE supports each LTS (Long Term Support) version of the Java platform starting from the version 1.8. Moreover, it is compatible with every non-LTS version released after the latest LTS.

Each JDK has separate Travis pipeline to ensure proper compatibility. Please make sure your changes don't break any supported version.

Currently YARE supports following JDK versions:

  • JDK 8
  • JDK 11
  • JDK 12

License

Copyright 2018 Sabre GLBL Inc.

Output artifacts are under the MIT license.

Apache License Version 2.0 is utilized for project's tooling only (Maven Wrapper) and is not a part of output artifacts.

About

YARE is a rules engine for Java that simplifies processing rules

Resources

License

Stars

Watchers

Forks

Packages

No packages published