remove site (moved to http://github.com/EasyRules/easyrules-website)
parent
3ad299a699
commit
809ef71059
@ -1 +0,0 @@
|
||||
www.easyrules.org
|
@ -1,20 +0,0 @@
|
||||
version: 2.2.0
|
||||
highlighter: pygments
|
||||
url: http://www.easyrules.org
|
||||
google_analytics_id: UA-46301888-1
|
||||
exclude: ["CNAME", "README"]
|
||||
|
||||
author :
|
||||
name : Mahmoud Ben Hassine
|
||||
email : mahmoud.benhassine@icloud.com
|
||||
github : benas
|
||||
twitter : _benas_
|
||||
web : http://benas.github.io
|
||||
|
||||
project:
|
||||
name: Easy Rules
|
||||
github: easy-rules
|
||||
|
||||
markdown: redcarpet
|
||||
redcarpet:
|
||||
extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "strikethrough", "superscript", "with_toc_data"]
|
@ -1,10 +0,0 @@
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', '{{ site.google_analytics_id }}']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
@ -1 +0,0 @@
|
||||
</html>
|
@ -1,74 +0,0 @@
|
||||
<div class="unit one-fifth">
|
||||
<aside>
|
||||
|
||||
<h4>About Easy Rules</h4>
|
||||
<ul>
|
||||
<li class="{% if page.title == "Overview" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/about/overview.html">Overview</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Getting started" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/about/getting-started.html">Getting started</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>User guide</h4>
|
||||
<ul>
|
||||
<li class="{% if page.title == "Introduction" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/introduction.html">Introduction</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Defining rules" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/defining-rules.html">Defining rules</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Rule listener" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/rule-listener.html">Rule listener</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Rules engine" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/rules-engine.html">Rules engine</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Managing rules" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/managing-rules.html">Managing rules</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Scheduling rules engine" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/scheduling-rules-engine.html">Scheduling a rules engine</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Embedding rules engine" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/user-guide/embedding-rules-engine.html">Embedding a rules engine</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Tutorials</h4>
|
||||
<ul>
|
||||
<li class="{% if page.title == "Hello world tutorial" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/tutorials/hello-world-tutorial.html">Hello world tutorial</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Shop tutorial" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/tutorials/shop-tutorial.html">Shop tutorial</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Scheduler tutorial" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/tutorials/scheduler-tutorial.html">Scheduler tutorial</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "Spring tutorial" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/tutorials/spring-tutorial.html">Spring tutorial</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h4>Get involved</h4>
|
||||
<ul>
|
||||
<li class="{% if page.title == "Release notes" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/get-involved/release-notes.html">Release notes</a>
|
||||
</li>
|
||||
<li class="{% if page.title == "FAQ" %}current{% endif %}">
|
||||
<a href="{{ site.url }}/get-involved/faq.html">FAQs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/benas/easy-rules">Source repository</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/benas/easy-rules/issues">Issue tracker</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</aside>
|
||||
</div>
|
@ -1,14 +0,0 @@
|
||||
<footer>
|
||||
<div class="grid">
|
||||
<div class="unit one-third center-on-mobiles">
|
||||
<p>Project created and maintained by <a target="_blank" href="{{ site.author.web }}">{{ site.author.name}}</a>
|
||||
and the <a href="https://github.com/benas/easy-rules#awesome-contributors" target="_blank">awesome contributors</a>.</p>
|
||||
</div>
|
||||
<div class="unit two-thirds align-right center-on-mobiles">
|
||||
<p>Easy Rules is released under the terms of the <a href="http://opensource.org/licenses/mit-license.php/" target="_blank">MIT license</a>.<br/>
|
||||
This website is inspired by and built with <a target="_blank" href="http://jekyllrb.com">Jekyll</a>.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
@ -1,14 +0,0 @@
|
||||
<header>
|
||||
<div class="grid">
|
||||
<div class="unit one-third">
|
||||
<a href="{{ site.url }}/index.html">
|
||||
<h1>
|
||||
<span class="shadow">{{ site.project.name }}</span>
|
||||
</h1>
|
||||
</a>
|
||||
</div>
|
||||
<nav class="main-nav unit two-thirds">
|
||||
{% include primary-nav-items.html %}
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
@ -1,15 +0,0 @@
|
||||
<ul>
|
||||
<li> </li>
|
||||
<li class="{% if page.overview %}current{% endif %}">
|
||||
<a href="{{ site.url }}/index.html">Home</a>
|
||||
</li>
|
||||
<li class="{% if page.doc %}current{% endif %}">
|
||||
<a href="{{ site.url }}/about/overview.html">Documentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="{{ site.url }}/apidocs/">API docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/{{ site.author.github }}/{{ site.project.github }}">View on GitHub</a>
|
||||
</li>
|
||||
</ul>
|
@ -1,22 +0,0 @@
|
||||
<div class="section-nav">
|
||||
<div class="left align-right">
|
||||
{% if page.prev_section != null %}
|
||||
<a href="{{ site.url }}/{{ page.prev_section }}.html" class="prev">
|
||||
Back
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="prev disabled">Back</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="right align-left">
|
||||
{% if page.next_section != null %}
|
||||
<a href="{{ site.url }}/{{ page.next_section }}.html" class="next">
|
||||
Next
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="next disabled">Next</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
@ -1,19 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ page.title }}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="author" content="Mahmoud Ben Hassine">
|
||||
<meta name="description" content="Open source java rules engine">
|
||||
<meta name="keywords" content="java, rules engine, open source">
|
||||
<link href='http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'>
|
||||
<link href='http://fonts.googleapis.com/css?family=Arizonia' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="{{ site.url }}/css/normalize.css" />
|
||||
<link rel="stylesheet" href="{{ site.url }}/css/gridism.css" />
|
||||
<link rel="stylesheet" href="{{ site.url }}/css/style.css" />
|
||||
<link rel="stylesheet" href="{{ site.url }}/css/pygments.css" />
|
||||
<link rel="icon" type="image/x-icon" href="{{ site.url }}/favicon.ico" />
|
||||
<script src="{{ site.url }}/js/modernizr-2.5.3.min.js"></script>
|
||||
</head>
|
@ -1,16 +0,0 @@
|
||||
{% include top.html %}
|
||||
|
||||
<body class="wrap">
|
||||
|
||||
{% include header.html %}
|
||||
|
||||
{{ content }}
|
||||
|
||||
{% include footer.html %}
|
||||
|
||||
{% include analytics.html %}
|
||||
|
||||
</body>
|
||||
|
||||
{% include bottom.html %}
|
||||
|
@ -1,21 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<section class="docs">
|
||||
<div class="grid">
|
||||
|
||||
<div class="unit four-fifths">
|
||||
<article>
|
||||
<h1>{{ page.header }}</h1>
|
||||
{{ content }}
|
||||
{% include section_nav.html %}
|
||||
</article>
|
||||
</div>
|
||||
|
||||
{% include docs_contents.html %}
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
</div>
|
||||
</section>
|
@ -1,17 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<section class="news">
|
||||
<div class="grid">
|
||||
|
||||
<div class="unit four-fifths">
|
||||
{{ content }}
|
||||
{% include section_nav.html %}
|
||||
</div>
|
||||
|
||||
{% include docs_contents.html %}
|
||||
<div class="clear"></div>
|
||||
|
||||
</div>
|
||||
</section>
|
@ -1,59 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Getting started
|
||||
header: Getting started
|
||||
prev_section: about/overview
|
||||
next_section: user-guide/introduction
|
||||
doc: true
|
||||
---
|
||||
|
||||
Easy Rules is a Java library. It requires a Java 1.7+ runtime.
|
||||
|
||||
## Building from source
|
||||
|
||||
To build Easy Rules from sources, you need to have [git](http://www.git-scm.com) and [maven](http://maven.apache.org/) installed and set up.
|
||||
|
||||
Please follow these instructions :
|
||||
|
||||
{% highlight bash %}
|
||||
$ git clone https://github.com/benas/easy-rules.git
|
||||
$ cd easy-rules
|
||||
$ mvn package
|
||||
{% endhighlight %}
|
||||
|
||||
Easy Rules core jar **_easyrules-core-{{site.version}}.jar_** will be generated in the **_target_** folder.
|
||||
|
||||
## Use with maven
|
||||
|
||||
Easy Rules is a single jar file with no dependencies. You have to add the jar **_easyrules-core-{{site.version}}.jar_** to your application's classpath.
|
||||
|
||||
If you use maven, add the following dependency to your **_pom.xml_** :
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.easyrules</groupId>
|
||||
<artifactId>easyrules-core</artifactId>
|
||||
<version>{{site.version}}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## Quick start archetype
|
||||
|
||||
The quick start archetype generates a skeleton project with the right dependency to Easy Rules.
|
||||
In order to generate a quick start project, just run the following command:
|
||||
|
||||
```
|
||||
$>mvn archetype:generate \
|
||||
-DarchetypeGroupId=org.easyrules \
|
||||
-DarchetypeArtifactId=easyrules-archetype \
|
||||
-DarchetypeVersion={{ site.version }}
|
||||
```
|
||||
|
||||
You will be asked for your project's groupId, artifactId, version and base package. Once finished, you will get a fully
|
||||
functional sample application that you can run with the following command:
|
||||
|
||||
```
|
||||
$>mvn compile exec:java -Dexec.mainClass=${your.base.package}.Launcher
|
||||
```
|
||||
|
||||
where `${your.base.package}` is the value of the base package you were asked for when creating the project.
|
@ -1,21 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Overview
|
||||
header: What is Easy rules?
|
||||
next_section: about/getting-started
|
||||
doc: true
|
||||
---
|
||||
|
||||
Easy Rules is a simple yet powerful Java rules engine providing the following features:
|
||||
|
||||
* Lightweight framework and easy to learn API
|
||||
* POJO based development
|
||||
* Useful abstractions to define business rules and apply them easily
|
||||
* The ability to create composite rules from primitive ones
|
||||
* Dynamic rule configuration at runtime using JMX
|
||||
|
||||
In a very interesting <a href="http://martinfowler.com/bliki/RulesEngine.html" target="_blank">article</a> about rules engines, <a href="http://martinfowler.com/" target="_blank">Martin Fowler</a> says:
|
||||
|
||||
>You can build a simple rules engine yourself. All you need is to create a bunch of objects with conditions and actions, store them in a collection, and run through them to evaluate the conditions and execute the actions.
|
||||
|
||||
This is exactly what Easy Rules does, with more features like rule composition and dynamic configuration.
|
@ -1,504 +0,0 @@
|
||||
/*! normalize.css 2012-03-11T12:53 UTC - http://github.com/necolas/normalize.css */
|
||||
|
||||
/* =============================================================================
|
||||
HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Corrects block display not defined in IE6/7/8/9 & FF3
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects inline-block display not defined in IE6/7/8/9 & FF3
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
video {
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents modern browsers from displaying 'audio' without controls
|
||||
* Remove excess height in iOS5 devices
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
|
||||
* Known issue: no IE6 support
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Base
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
|
||||
* http://clagnut.com/blog/348/#c790
|
||||
* 2. Prevents iOS text size adjust after orientation change, without disabling user zoom
|
||||
* www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
|
||||
*/
|
||||
|
||||
html {
|
||||
font-size: 100%; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses font-family inconsistency between 'textarea' and other form elements.
|
||||
*/
|
||||
|
||||
html,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses margins handled incorrectly in IE6/7
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Links
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses outline displayed oddly in Chrome
|
||||
*/
|
||||
|
||||
a:focus {
|
||||
outline: thin dotted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Improves readability when focused and also mouse hovered in all browsers
|
||||
* people.opera.com/patrickl/experiments/keyboard/test
|
||||
*/
|
||||
|
||||
a:hover,
|
||||
a:active {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Typography
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses font sizes and margins set differently in IE6/7
|
||||
* Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
margin: 0.83em 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.17em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1em;
|
||||
margin: 1.33em 0;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 0.75em;
|
||||
margin: 2.33em 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling not present in IE7/8/9, S5, Chrome
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses style set to 'bolder' in FF3+, S4/5, Chrome
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling not present in S5, Chrome
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses styling not present in IE6/7/8/9
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses margins set differently in IE6/7
|
||||
*/
|
||||
|
||||
p,
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects font family set oddly in IE6, S4/5, Chrome
|
||||
* en.wikipedia.org/wiki/User:Davidgothberg/Test59
|
||||
*/
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, serif;
|
||||
_font-family: 'courier new', monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
* Improves readability of pre-formatted text in all browsers
|
||||
*/
|
||||
|
||||
pre {
|
||||
white-space: pre;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Addresses CSS quotes not supported in IE6/7
|
||||
* 2. Addresses quote property not supported in S4
|
||||
*/
|
||||
|
||||
/* 1 */
|
||||
|
||||
q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
/* 2 */
|
||||
|
||||
q:before,
|
||||
q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents sub and sup affecting line-height in all browsers
|
||||
* gist.github.com/413930
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Lists
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses margins set differently in IE6/7
|
||||
*/
|
||||
|
||||
dl,
|
||||
menu,
|
||||
ol,
|
||||
ul {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0 0 0 40px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses paddings set differently in IE6/7
|
||||
*/
|
||||
|
||||
menu,
|
||||
ol,
|
||||
ul {
|
||||
padding: 0 0 0 40px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects list images handled incorrectly in IE7
|
||||
*/
|
||||
|
||||
nav ul,
|
||||
nav ol {
|
||||
list-style: none;
|
||||
list-style-image: none;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
|
||||
* 2. Improves image quality when scaled in IE7
|
||||
* code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0; /* 1 */
|
||||
-ms-interpolation-mode: bicubic; /* 2 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Corrects overflow displayed oddly in IE9
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Figures
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Addresses margin not present in IE6/7/8/9, S5, O11
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Forms
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Corrects margin displayed oddly in IE6/7
|
||||
*/
|
||||
|
||||
form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Define consistent border, margin, and padding
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Corrects color not being inherited in IE6/7/8/9
|
||||
* 2. Corrects text not wrapping in FF3
|
||||
* 3. Corrects alignment displayed oddly in IE6/7
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0;
|
||||
white-space: normal; /* 2 */
|
||||
*margin-left: -7px; /* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Corrects font size not being inherited in all browsers
|
||||
* 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
|
||||
* 3. Improves appearance and consistency in all browsers
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-size: 100%; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
vertical-align: baseline; /* 3 */
|
||||
*vertical-align: middle; /* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
|
||||
*/
|
||||
|
||||
button,
|
||||
input {
|
||||
line-height: normal; /* 1 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Improves usability and consistency of cursor style between image-type 'input' and others
|
||||
* 2. Corrects inability to style clickable 'input' types in iOS
|
||||
* 3. Removes inner spacing in IE7 without affecting normal text inputs
|
||||
* Known issue: inner spacing remains in IE6
|
||||
*/
|
||||
|
||||
button,
|
||||
input[type="button"],
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
cursor: pointer; /* 1 */
|
||||
-webkit-appearance: button; /* 2 */
|
||||
*overflow: visible; /* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-set default cursor for disabled elements
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Addresses box sizing set to content-box in IE8/9
|
||||
* 2. Removes excess padding in IE8/9
|
||||
* 3. Removes excess padding in IE7
|
||||
Known issue: excess padding remains in IE6
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
*height: 13px; /* 3 */
|
||||
*width: 13px; /* 3 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Addresses appearance set to searchfield in S5, Chrome
|
||||
* 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes inner padding and search cancel button in S5, Chrome on OS X
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-decoration,
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes inner padding and border in FF3+
|
||||
* www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Removes default vertical scrollbar in IE6/7/8/9
|
||||
* 2. Improves readability and alignment in all browsers
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto; /* 1 */
|
||||
vertical-align: top; /* 2 */
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
Tables
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Remove most spacing between table cells
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
.highlight .hll { background-color: #222222 }
|
||||
/* .highlight { background: #000000; color: #cccccc } */
|
||||
.highlight .c { color: #777777; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #cccccc; border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .g { color: #cccccc } /* Generic */
|
||||
.highlight .k { color: #cdcd00 } /* Keyword */
|
||||
.highlight .l { color: #cccccc } /* Literal */
|
||||
.highlight .n { color: #cccccc } /* Name */
|
||||
.highlight .o { color: #3399cc } /* Operator */
|
||||
.highlight .x { color: #cccccc } /* Other */
|
||||
.highlight .p { color: #cccccc } /* Punctuation */
|
||||
.highlight .cm { color: #777777; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #777777; font-style: italic } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #777777; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #cd5c5c; font-weight: bold } /* Comment.Special */
|
||||
.highlight .gd { color: #cd5c5c } /* Generic.Deleted */
|
||||
.highlight .ge { color: #cccccc; font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00cd00 } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { color: #cccccc; font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #cdcd00 } /* Keyword.Constant */
|
||||
.highlight .kd { color: #00cd00 } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #cd00cd } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #cdcd00 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #cdcd00 } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #00cd00 } /* Keyword.Type */
|
||||
.highlight .ld { color: #cccccc } /* Literal.Date */
|
||||
.highlight .m { color: #cd00cd } /* Literal.Number */
|
||||
.highlight .s { color: #cd5c5c } /* Literal.String */
|
||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||
.highlight .nb { color: #cd00cd } /* Name.Builtin */
|
||||
.highlight .nc { color: #00cdcd } /* Name.Class */
|
||||
.highlight .no { color: #cccccc } /* Name.Constant */
|
||||
.highlight .nd { color: #cccc00 } /* Name.Decorator */
|
||||
.highlight .ni { color: #cccccc } /* Name.Entity */
|
||||
.highlight .ne { color: #666699; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #f0e68c } /* Name.Function */
|
||||
.highlight .nl { color: #cccccc } /* Name.Label */
|
||||
.highlight .nn { color: #cccccc } /* Name.Namespace */
|
||||
.highlight .nx { color: #cccccc } /* Name.Other */
|
||||
.highlight .py { color: #cccccc } /* Name.Property */
|
||||
.highlight .nt { color: #00cccc } /* Name.Tag */
|
||||
.highlight .nv { color: #00cdcd } /* Name.Variable */
|
||||
.highlight .ow { color: #cdcd00 } /* Operator.Word */
|
||||
.highlight .w { color: #cccccc } /* Text.Whitespace */
|
||||
.highlight .mf { color: #cd00cd } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #cd00cd } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #cd00cd } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #cd00cd } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #cd5c5c } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #cd5c5c } /* Literal.String.Char */
|
||||
.highlight .sd { color: #cd5c5c } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #cd5c5c } /* Literal.String.Double */
|
||||
.highlight .se { color: #cd5c5c } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #cd5c5c } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #cd5c5c } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #cd5c5c } /* Literal.String.Other */
|
||||
.highlight .sr { color: #cd5c5c } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #cd5c5c } /* Literal.String.Single */
|
||||
.highlight .ss { color: #cd5c5c } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #cd00cd } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #00cdcd } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #00cdcd } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #00cdcd } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #cd00cd } /* Literal.Number.Integer.Long */
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 71 KiB |
@ -1,177 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: FAQ
|
||||
prev_section: get-involved/release-notes
|
||||
doc: true
|
||||
---
|
||||
|
||||
## <a name="1"></a>[1. Why is Easy Rules called the "The stupid Java rules engine"?](#1)
|
||||
|
||||
The goal behind Easy Rules is to provide a lightweight rules engine without features that 80% of application
|
||||
do not need. The term "stupid" is actually the perfect term to describe how the engine works: It iterates
|
||||
over a set of ordered rules and execute rules when their conditions are met. This what makes it easy to learn use and
|
||||
use following the KISS principle.
|
||||
|
||||
## <a name="2"></a>[2. I would like to return a value upon a rule execution, how to do that?](#2)
|
||||
|
||||
By design, rules do not return values. But you can always make your rules return a result after execution. Here is an example:
|
||||
|
||||
```java
|
||||
@Rule(name = "my rule")
|
||||
public static class MyRule<T> {
|
||||
|
||||
private boolean executed;
|
||||
|
||||
private T result;
|
||||
|
||||
//@Condition
|
||||
public boolean when() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//@Action
|
||||
public void then() throws MyException {
|
||||
try {
|
||||
System.out.println("my rule has been executed");
|
||||
result = null; // assign your result here
|
||||
executed = true;
|
||||
} catch (MyException e) {
|
||||
// executed flag will remain false if an exception occurs
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isExecuted() {
|
||||
return executed;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
This rule will return a result if it executes successfully. After firing rules, you query the `executed` flag on your
|
||||
rule instance and get the execution result.
|
||||
|
||||
## <a name="3"></a>[3. I've registered multiple instances of the same rule with different inputs, but it seems only the first instance is registered. What's happening?](#3)
|
||||
|
||||
Rules have unique names within a rules engine registry. If you register multiple instances of the same rule, only the first instance will be considered.
|
||||
Other instances will be ignored since they have the same name. Let's see an example:
|
||||
|
||||
```java
|
||||
@Rule(name = "AgeRule",
|
||||
description = "Check if person's age is > 18
|
||||
and marks the person as adult")
|
||||
public class AgeRule {
|
||||
|
||||
private Person person;
|
||||
|
||||
private int adultAge = 18;
|
||||
|
||||
public AgeRule(Person person) {
|
||||
this.person = person;
|
||||
}
|
||||
|
||||
@Condition
|
||||
public boolean isAdult() {
|
||||
return person.getAge() > adultAge;
|
||||
}
|
||||
|
||||
@Action
|
||||
public void markAsAdult(){
|
||||
person.setAdult(true);
|
||||
System.out.printf(
|
||||
"Person %s has been marked as adult",
|
||||
person.getName());
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
The `Person` type is a simple POJO having a `name` and `age` fields. Let's register multiple instances of the `AgeRule`:
|
||||
|
||||
```java
|
||||
Person tom = new Person("Tom", 20);
|
||||
Person david = new Person("David", 19);
|
||||
|
||||
RulesEngine rulesEngine = aNewRulesEngine().build();
|
||||
|
||||
//first run
|
||||
AgeRule ageRule = new AgeRule(tom);
|
||||
rulesEngine.registerRule(ageRule);
|
||||
rulesEngine.fireRules();
|
||||
|
||||
//second run
|
||||
ageRule = new AgeRule(david);
|
||||
rulesEngine.registerRule(ageRule);
|
||||
rulesEngine.fireRules();
|
||||
```
|
||||
|
||||
Both Tom and David are adults, so you are expecting to see:
|
||||
|
||||
```
|
||||
Person Tom has been marked as adult.
|
||||
Person David has been marked as adult.
|
||||
```
|
||||
|
||||
But actually you get:
|
||||
|
||||
```
|
||||
Person Tom has been marked as adult.
|
||||
Person Tom has been marked as adult.
|
||||
```
|
||||
|
||||
The second rule instance has been ignored at registration time since it has the same name ( "AgeRule" ) as the first instance.
|
||||
|
||||
So how to deal with multiple data using the same rule?
|
||||
|
||||
You have 2 solutions: Either you clear rules after the first run using `rulesEngine.clearRules()`, or register your rule only once,
|
||||
vary input using a setter (that you should add to your rule) and re-fire rules:
|
||||
|
||||
```java
|
||||
//create persons
|
||||
Person tom = new Person("Tom", 20);
|
||||
Person david = new Person("David", 19);
|
||||
|
||||
//create a rules engine
|
||||
RulesEngine rulesEngine = aNewRulesEngine().build();
|
||||
AgeRule ageRule = new AgeRule();
|
||||
rulesEngine.registerRule(ageRule);
|
||||
|
||||
//first run
|
||||
ageRule.setPerson(tom);
|
||||
rulesEngine.fireRules();
|
||||
|
||||
//second run
|
||||
ageRule.setPerson(david);
|
||||
rulesEngine.fireRules();
|
||||
```
|
||||
|
||||
This is more efficient than registering new instances for each new business data input.
|
||||
|
||||
## <a name="4"></a>[4. Is Easy Rules usable with Android?](#4)
|
||||
|
||||
Yes. Thanks to the community, Easy Rules has been made Android compatible since version 1.3
|
||||
|
||||
## <a name="5"></a>[5. Can I use Easy Rules in a web application?](#5)
|
||||
|
||||
Sure. Easy Rules is very lightweight and can be used both in a standalone application or embedded in an application server,
|
||||
a servlet container or a dependency injection container.
|
||||
|
||||
## <a name="6"></a>[6. How to deal with tread safety?](#6)
|
||||
|
||||
If you run Easy Rules in a multi-threaded environment, you should take into account the following considerations:
|
||||
|
||||
* Easy Rules engine holds a set of rules, it is **not** thread safe.
|
||||
* By design, rules in Easy Rules encapsulate the business object model they operate on, so they are **not** thread safe neither.
|
||||
|
||||
Do not try to make everything synchronized or locked down! Easy Rules engine is very a lightweight object
|
||||
and you can create an instance per thread, this is by far the easiest way to avoid thread safety problems.
|
||||
And if, at this exact point of time reading this line, you are already thinking about performance,
|
||||
don't forget that <a href="http://c2.com/cgi/wiki?PrematureOptimization" target="_blank"><em>"Premature optimization is the root of all evil" - Donald Knuth</em></a>.
|
||||
|
||||
## <a name="7"></a>[7. I have another question, how do I do?](#7)
|
||||
|
||||
Feel free to ask your question in the [Gitter](https://gitter.im/benas/easy-rules) channel of the project: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/benas/easy-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
@ -1,169 +0,0 @@
|
||||
---
|
||||
layout: news
|
||||
title: "Release notes"
|
||||
prev_section: tutorials/spring-tutorial
|
||||
next_section: get-involved/faq
|
||||
doc: true
|
||||
---
|
||||
|
||||
<article>
|
||||
<h2>
|
||||
<a href="/get-involved/release-notes.html">{{ page.title }}</a>
|
||||
</h2>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 2.2.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2015-12-07</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This release adds the following features:</p>
|
||||
<ul>
|
||||
<li>New method <code>getRules()</code> in the <code>RulesEngine</code> API to get registered rules in a rules engine
|
||||
(<a href="https://github.com/benas/easy-rules/issues/22" target="_blank">Issue #22</a>).</li>
|
||||
<li>New method <code>getParameters()</code> in the <code>RulesEngine</code> API to get engine parameters
|
||||
encapsulated in the <code>RulesEngineParameters</code> class
|
||||
(<a href="https://github.com/benas/easy-rules/issues/28" target="_blank">Issue #28</a>).</li>
|
||||
<li>New <code>@SpringRule</code> that turns a POJO into a Spring prototype-scoped rule bean
|
||||
(<a href="https://github.com/benas/easy-rules/issues/29" target="_blank">Issue #29</a>).</li>
|
||||
<li>Support for meta-annotations: You can now define your own annotation which itself is annotated with <code>@Rule</code>
|
||||
(<a href="https://github.com/benas/easy-rules/pull/26" target="_blank">PR #26</a>).</li>
|
||||
<li>The default rule name is now equal to the class name (<a href="https://github.com/benas/easy-rules/issues/24" target="_blank">Issue #24</a>).</li>
|
||||
<li>The default rule description is now equal to <code>when[ConditionMethod]then[ActionMethods]</code> (<a href="https://github.com/benas/easy-rules/issues/24" target="_blank">Issue #24</a>).</li>
|
||||
</ul>
|
||||
<p>This version also added many improvements, bug fixes and documentation updates.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 2.1.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2015-06-28</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This release brings the following new features:</p>
|
||||
<ul>
|
||||
<li>New APIs to embed easy rules in a <a href="http://www.spring.io" target="_blank">Spring</a> container.</li>
|
||||
<li>New APIs to schedule a rules engine using <a href="http://www.quartz-scheduler.org" target="_blank">Quartz</a> (<a href="https://github.com/benas/easy-rules/pull/15" target="_blank">PR #15</a>).</li>
|
||||
<li>New maven archetype to create a quick start project.
|
||||
</ul>
|
||||
<p>This version also added new tutorials and many improvements and bug fixes.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 2.0.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2015-05-21</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This is a major release of Easy Rules with some API breaking changes.</p>
|
||||
<p>The most important change is the merge of <code>DefaultRulesEngine</code> and <code>AnnotatedRulesEngine</code>.
|
||||
With version 1.x, rules that implement the <code>Rule</code> interface and rules that are annotated POJOs required to be used with different engines.
|
||||
Version 2.0 removes this constraint and all types of rules can now be used in a consistent way through the single and unified <code>RulesEngine</code> interface.</p>
|
||||
<p>This version also brings a lot of new features and improvements:</p>
|
||||
<ul>
|
||||
<li>Added a new <code>RulesEngineBuilder</code> as the main entry point to create rules engines</li>
|
||||
<li>Added a new <code>RuleListener</code> to be able to add custom behavior before/after the execution of each rule (<a href="https://github.com/benas/easy-rules/issues/11" target="_blank">Issue #11</a>)</li>
|
||||
<li>Added a new parameter <code>skipOnFirstFailedRule</code> to skip next rules when a rule fails (<a href="https://github.com/benas/easy-rules/issues/10" target="_blank">Issue #10</a>).</li>
|
||||
<li>Added a new parameter <code>silentMode</code> to mute all loggers</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 1.3.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2015-03-11</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This release added the following features:</p><p></p>
|
||||
<ul>
|
||||
<li>Moved JMX support to a separate module so that the core engine can be used in both Java and Android applications (<a href="https://github.com/benas/easy-rules/pull/5" target="_blank">PR #5</a>).</li>
|
||||
<li>Fixed <a href="https://github.com/benas/easy-rules/issues/6" target="_blank">issue #6</a>: Can't register multiple rules with the same priority to DefaultRulesEngine</li>
|
||||
<li>Refactored tests to use <a href="http://mockito.org/" target="_blank">Mockito</a> and <a href="http://assertj.org" target="_blank">AssertJ</a></li>
|
||||
<li>Improved test coverage</li>
|
||||
<li>Updated documentation and tutorials</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 1.2.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2014-10-15</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This release brings the following improvements:</p><p></p>
|
||||
<ul>
|
||||
<li>Added a method in <code>RulesEngine</code> interface to unregister a rule.</li>
|
||||
<li>Added a <a href="{{site.url}}/tutorials/rule-priority.html">tutorial</a> with a showcase of rules priorities.</li>
|
||||
<li>Improved code quality by fixing several sonar errors/warnings</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 1.1.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2014-10-02</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This release introduced a big refactoring of Easy Rules APIs to provide the following features:</p><p></p>
|
||||
<ul>
|
||||
<li>Added annotation support to provide a POJO based development model</li>
|
||||
<li>Added new site for documentation and tutorials</li>
|
||||
<li>Added new set of tutorials for basic and advanced usage of Easy Rules APIs </li>
|
||||
<li>Renamed base package from <code>io.github.benas</code> to <code>org.easyrules</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 1.0.1</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2014-01-24</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This minor release fixed the base package name.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p></p>
|
||||
|
||||
<div class="release">
|
||||
<span class="post-category">
|
||||
<span class="label">Version 1.0.0</span>
|
||||
</span>
|
||||
<div class="post-meta">
|
||||
<span class="post-date">2013-12-23</span>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<p>This is the first stable version of Easy Rules. It contains initial core API and implementation:</p>
|
||||
<ul>
|
||||
<li>Basic abstractions for rules and rules engine</li>
|
||||
<li>Ability to create composite rules from primitive ones</li>
|
||||
<li>Ability to manage rules at runtime via JMX</li>
|
||||
<li>Java fluent API to create rules engine</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 157 KiB |
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
@ -1,133 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Easy rules • The stupid Java™ rules engine.
|
||||
overview: true
|
||||
---
|
||||
|
||||
<section class="intro">
|
||||
<div class="grid">
|
||||
<div class="unit whole">
|
||||
<p class="first">The stupid Java™ rules engine.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="features">
|
||||
<div class="grid">
|
||||
<div class="unit one-third">
|
||||
<h2>Lightweight</h2>
|
||||
<p>
|
||||
A zero dependencies jar with a lot of features! Use it in a standalone or embedded mode.
|
||||
</p>
|
||||
<a href="{{ site.url }}/about/getting-started.html" class="">Get started →</a>
|
||||
</div>
|
||||
<div class="unit one-third">
|
||||
<h2>POJO based</h2>
|
||||
<p>
|
||||
Turn your POJOs into business rules with a couple of intuitive annotations.
|
||||
</p>
|
||||
<a href="{{ site.url }}/about/overview.html" class="">Read documentation →</a>
|
||||
</div>
|
||||
<div class="unit one-third">
|
||||
<h2>Simple yet powerful</h2>
|
||||
<p>
|
||||
Easy rules provides a simple API that is easy to learn. You can get it up and running in minutes!
|
||||
</p>
|
||||
<a href="{{ site.url }}/tutorials/hello-world.html" class="">2 minutes tutorial →</a>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="quickstart">
|
||||
<div class="grid">
|
||||
<div class="unit code" style="width: 50%">
|
||||
<p class="title">Then, fire it!</p>
|
||||
<div class="shell">
|
||||
<div class="highlight"><pre><code class="language-java" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size: 16px"><span class="kd">public class</span> <span class="nc">Test</span> <span class="o">{</span>
|
||||
<span class="kd">public static void</span> <span class="nf">main</span><span class="o">(</span>String<span class="o">[]</span> args<span class="o">)</span> <span class="o">{</span>
|
||||
<span class="c1">// create a rules engine</span>
|
||||
RulesEngine rulesEngine <span class="o">=</span>
|
||||
aNewRulesEngine<span class="o">()</span>.build<span class="o">();</span>
|
||||
<span class="c1">//register the rule</span>
|
||||
rulesEngine<span class="o">.</span><span class="na">registerRule</span><span class="o">(</span><span class="k">new</span> MyRule<span class="o">());</span>
|
||||
<span class="c1">//fire rules</span>
|
||||
rulesEngine<span class="o">.</span><span class="na">fireRules</span><span class="o">();</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></code></pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="unit code" style="width: 50%">
|
||||
<p class="title">First, define your rule..</p>
|
||||
<div class="shell">
|
||||
<div class="highlight"><pre><code class="language-java" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size: 16px"><span class="nd">@Rule</span> <span class="o">(</span>name <span class="o">=</span> <span class="s">"my awesome rule"</span> <span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyRule</span> <span class="o">{</span>
|
||||
<span class="nd">@Condition</span>
|
||||
<span class="kd">public boolean</span> <span class="nf">when</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> true<span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="nd">@Action</span>
|
||||
<span class="kd">public void</span> <span class="nf">then</span><span class="o">()</span> <span class="o">{</span>
|
||||
System<span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Easy Rules rocks!"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></code></pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="free-hosting">
|
||||
<div class="grid">
|
||||
<div class="unit whole">
|
||||
<div class="grid pane">
|
||||
<div class="unit whole">
|
||||
<div class="pane-content">
|
||||
<h2>Latest news</h2>
|
||||
<p><strong>06/12/2015:</strong> Version 2.2 is here with meta-annotation support! Check what's new <a href="./get-involved/release-notes.html">here</a>.</p>
|
||||
<p><strong>28/06/2015:</strong> Version 2.1 is out with <a href="http://www.spring.io" target="_blank">Spring</a> and <a href="http://www.quartz-scheduler.org" target="_blank">Quartz</a> support. Check what's new <a href="./get-involved/release-notes.html">here</a>.</p>
|
||||
<p><strong>21/05/2015:</strong> Version 2.0 is finally released! checkout what's new <a href="./get-involved/release-notes.html">here</a>.</p>
|
||||
</div>
|
||||
|
||||
<div class="pane-content">
|
||||
<h2>License</h2>
|
||||
<p>Easy Rules is open source, hosted on <a target="_blank" href="https://github.com/benas/easy-rules">GitHub</a> and is released under the terms of the <a target="_blank" href="http://opensource.org/licenses/mit-license.php/">MIT License</a>.</p>
|
||||
</div>
|
||||
|
||||
<div class="pane-content align-center">
|
||||
<iframe src="http://ghbtns.com/github-btn.html?user=benas&repo=easy-rules&type=watch&count=true"
|
||||
allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
|
||||
<iframe src="http://ghbtns.com/github-btn.html?user=benas&repo=easy-rules&type=fork&count=true"
|
||||
allowtransparency="true" frameborder="0" scrolling="0" width="95" height="20"></iframe>
|
||||
<iframe src="http://ghbtns.com/github-btn.html?user=benas&type=follow&count=true"
|
||||
allowtransparency="true" frameborder="0" scrolling="0" width="165" height="20"></iframe>
|
||||
</div>
|
||||
<div class="pane-content">
|
||||
<h2>Credits</h2>
|
||||
<div class="grid">
|
||||
<div class="unit four-fifths">
|
||||
<p>Many thanks to <a href="https://www.yourkit.com/" target="_blank">YourKit, LLC</a> for providing a free license of
|
||||
<a href="https://www.yourkit.com/java/profiler/index.jsp" target="_blank">YourKit Java Profiler</a> to kindly support the development of Easy Rules.</p>
|
||||
</div>
|
||||
<div class="unit one-fifth">
|
||||
<img class="logo" src="{{ site.url }}/img/yourkit.png" alt="yourkit profiler"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div class="unit four-fifths">
|
||||
<p>Many thanks to <a href="https://travis-ci.org" target="_blank">Travis CI</a> for providing a free
|
||||
continuous integration service for open source projects.</p>
|
||||
</div>
|
||||
<div class="unit one-fifth">
|
||||
<img class="logo" src="{{ site.url }}/img/travis-ci.jpg" alt="travis-ci"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,106 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Hello world tutorial
|
||||
header: Hello World tutorial
|
||||
prev_section: user-guide/embedding-rules-engine
|
||||
next_section: tutorials/shop-tutorial
|
||||
doc: true
|
||||
---
|
||||
|
||||
This tutorial shows how to use Easy Rules in a very simple application.
|
||||
The goal is to ask the user if he is a friend of duke and says 'Hello duke's friend!' only if he replies 'yes'.
|
||||
|
||||
Based on this requirement, the rule is pretty straightforward :
|
||||
|
||||
* The condition is that the user input must be equal to 'yes'
|
||||
* The action is to say 'Hello duke's friend!' to the user
|
||||
|
||||
First, let's create a rule class:
|
||||
|
||||
```java
|
||||
@Rule(name = "Hello World rule",
|
||||
description = "Say Hello to duke's friends only")
|
||||
public class HelloWorldRule {
|
||||
|
||||
/**
|
||||
* The user input which represents the data
|
||||
* that the rule will operate on.
|
||||
*/
|
||||
private String input;
|
||||
|
||||
@Condition
|
||||
public boolean checkInput() {
|
||||
//The rule should be applied only if
|
||||
//the user's response is yes (duke friend)
|
||||
return input.equalsIgnoreCase("yes");
|
||||
}
|
||||
|
||||
@Action
|
||||
public void sayHelloToDukeFriend() throws Exception {
|
||||
//When rule conditions are satisfied,
|
||||
//prints 'Hello duke's friend!' to the console
|
||||
System.out.println("Hello duke's friend!");
|
||||
}
|
||||
|
||||
public void setInput(String input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Then, we have to register an instance of this rule in a Easy Rules engine and launch the tutorial with the following class:
|
||||
|
||||
```java
|
||||
public class Launcher {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println("Are you a friend of duke?[yes/no]:");
|
||||
String input = scanner.nextLine();
|
||||
|
||||
/**
|
||||
* Declare the rule
|
||||
*/
|
||||
HelloWorldRule helloWorldRule = new HelloWorldRule();
|
||||
|
||||
/**
|
||||
* Set business data to operate on
|
||||
*/
|
||||
helloWorldRule.setInput(input.trim());
|
||||
|
||||
/**
|
||||
* Create a rules engine and register the business rule
|
||||
*/
|
||||
RulesEngine rulesEngine = aNewRulesEngine().build();
|
||||
|
||||
rulesEngine.registerRule(helloWorldRule);
|
||||
|
||||
/**
|
||||
* Fire rules
|
||||
*/
|
||||
rulesEngine.fireRules();
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To run this tutorial, you can follow these instructions from the root directory of Easy Rules :
|
||||
|
||||
{% highlight bash %}
|
||||
$ mvn install
|
||||
$ cd easyrules-samples
|
||||
$ mvn exec:java -P runHelloWorldTutorial
|
||||
{% endhighlight %}
|
||||
|
||||
You would get the following output:
|
||||
|
||||
```
|
||||
Are you a friend of duke? [yes/no]:
|
||||
yes
|
||||
INFO: Rule 'Hello World rule' triggered.
|
||||
Hello duke's friend!
|
||||
INFO: Rule 'Hello World rule' performed successfully.
|
||||
```
|
||||
|
@ -1,93 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Scheduler tutorial
|
||||
header: Scheduler tutorial
|
||||
prev_section: tutorials/shop-tutorial
|
||||
next_section: tutorials/spring-tutorial
|
||||
doc: true
|
||||
---
|
||||
|
||||
This tutorial shows how to schedule a rules engine using the `RulesEngineScheduler` API.
|
||||
|
||||
We would like to print the current time only if the seconds value is even. So let's get started.
|
||||
|
||||
First, we will create a rule that checks the current time and print it to the console if seconds are even:
|
||||
|
||||
```java
|
||||
@Rule(name = "time rule",
|
||||
description = "Print the current time
|
||||
only if seconds are even")
|
||||
public class TimeRule {
|
||||
|
||||
private Date now;
|
||||
|
||||
@Condition
|
||||
public boolean checkTime() {
|
||||
now = new Date();
|
||||
return now.getSeconds() % 2 == 0;
|
||||
}
|
||||
|
||||
@Action
|
||||
public void printTime() {
|
||||
System.out.println("Seconds in " + now + " are even");
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Then, we have to register an instance of this rule in a Easy Rules engine and schedule the engine:
|
||||
|
||||
```java
|
||||
public class Launcher {
|
||||
|
||||
public static final Date NOW = new Date();
|
||||
|
||||
public static final int EVERY_SECOND = 1;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
RulesEngine rulesEngine = RulesEngineBuilder
|
||||
.aNewRulesEngine()
|
||||
.named("time rules engine")
|
||||
.withSilentMode(true)
|
||||
.build();
|
||||
|
||||
TimeRule timeRule = new TimeRule();
|
||||
rulesEngine.registerRule(timeRule);
|
||||
|
||||
RulesEngineScheduler scheduler =
|
||||
RulesEngineScheduler.getInstance();
|
||||
scheduler.scheduleAtWithInterval(rulesEngine,
|
||||
NOW,
|
||||
EVERY_SECOND);
|
||||
scheduler.start();
|
||||
|
||||
System.out.println("Hit 'enter' to stop the application");
|
||||
System.in.read();
|
||||
scheduler.stop();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That's it! The `TimeRule` will be triggered every second and will print the current time only if seconds value is even.
|
||||
|
||||
|
||||
To run this tutorial, you can follow these instructions from the root directory of Easy Rules :
|
||||
|
||||
{% highlight bash %}
|
||||
$ mvn install
|
||||
$ cd easyrules-samples
|
||||
$ mvn exec:java -P runSchedulerTutorial
|
||||
{% endhighlight %}
|
||||
|
||||
You should see in the console something like:
|
||||
|
||||
```
|
||||
Hit enter to stop the application
|
||||
Seconds in Tue Jun 23 12:57:32 CEST 2015 are even
|
||||
Seconds in Tue Jun 23 12:57:34 CEST 2015 are even
|
||||
Seconds in Tue Jun 23 12:57:36 CEST 2015 are even
|
||||
Seconds in Tue Jun 23 12:57:38 CEST 2015 are even
|
||||
[Enter]
|
||||
```
|
||||
|
@ -1,261 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Shop tutorial
|
||||
header: Shop tutorial
|
||||
prev_section: tutorials/hello-world-tutorial
|
||||
next_section: tutorials/scheduler-tutorial
|
||||
doc: true
|
||||
---
|
||||
|
||||
In this tutorial, we have a shop application and we would like to implement the following requirement: deny children from buying alcohol.
|
||||
The minimal legal age to be considered as adult is 18. This tutorial is split in two parts:
|
||||
|
||||
1. Part 1: Implement the business rule of denying children from buying alcohol
|
||||
2. Part 2: Make the legal age configurable via JMX so we can change it at runtime
|
||||
|
||||
## Part 1 : Implement the business rule
|
||||
|
||||
Our shop customers are represented by the _Person_ class:
|
||||
|
||||
```java
|
||||
public class Person {
|
||||
private String name;
|
||||
private int age;
|
||||
private boolean adult;
|
||||
//getters and setters omitted
|
||||
}
|
||||
```
|
||||
|
||||
We will define the following rules:
|
||||
|
||||
* Rule 1: should operate an a `Person` instance, check that the person age is greater than 18 and set the adult flag.
|
||||
* Rule 2: should operate an a `Person` instance, check that the person is adult and deny children (ie, non adult) from buying alcohol.
|
||||
|
||||
Rule 1 should be fired **_before_** rule 2. We will set rule 1 priority to 1 and rule 2 priority to 2 so that Easy Rules engine fire them in this order.
|
||||
|
||||
First, let's create a class for rule 1:
|
||||
|
||||
```java
|
||||
public class AgeRule extends BasicRule {
|
||||
|
||||
private static final int ADULT_AGE = 18;
|
||||
|
||||
private Person person;
|
||||
|
||||
public AgeRule(Person person) {
|
||||
super("AgeRule",
|
||||
"Check if person's age is > 18 and
|
||||
marks the person as adult", 1);
|
||||
this.person = person;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate() {
|
||||
return person.getAge() > ADULT_AGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
person.setAdult(true);
|
||||
System.out.printf("Person %s has been marked as adult",
|
||||
person.getName());
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
As required, this rule class operates on a person that is passed at construction time.
|
||||
|
||||
The `evaluate` method checks if the person's age is greater than 18.
|
||||
|
||||
The `execute` will mark the person as adult by setting the `adult` flag.
|
||||
|
||||
Finally, the third constructor argument which represents the rule priority is set to 1 to tells Easy Rules engine to fire this rule in first order.
|
||||
|
||||
Now, let's create a class for rule 2:
|
||||
|
||||
```java
|
||||
public class AlcoholRule extends BasicRule {
|
||||
|
||||
private Person person;
|
||||
|
||||
public AlcoholRule(Person person) {
|
||||
super("AlcoholRule",
|
||||
"Children are not allowed to buy alcohol",
|
||||
2);
|
||||
this.person = person;
|
||||
}
|
||||
|
||||
@Condition
|
||||
public boolean evaluate() {
|
||||
return !person.isAdult();
|
||||
}
|
||||
|
||||
@Action
|
||||
public void execute(){
|
||||
System.out.printf("Shop: Sorry %s,
|
||||
you are not allowed to buy alcohol",
|
||||
person.getName());
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
As for rule 1, the class operates on a person instance and prints the denial message for children.
|
||||
|
||||
To launch the tutorial, we will use the following class:
|
||||
|
||||
```java
|
||||
public class Launcher {
|
||||
|
||||
public static void main(String[] args) {
|
||||
//create a person instance
|
||||
Person tom = new Person("Tom", 14);
|
||||
System.out.println("Tom:
|
||||
Hi! can I have some Vodka please?");
|
||||
|
||||
//create a rules engine
|
||||
RulesEngine rulesEngine = aNewRulesEngine()
|
||||
.named("shop rules engine")
|
||||
.build();
|
||||
|
||||
//register rules
|
||||
rulesEngine.registerRule(new AgeRule(tom));
|
||||
rulesEngine.registerRule(new AlcoholRule(tom));
|
||||
|
||||
//fire rules
|
||||
rulesEngine.fireRules();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
To run the first part of the tutorial, you can follow these instructions from the root directory of Easy Rules :
|
||||
|
||||
{% highlight bash %}
|
||||
$ mvn install
|
||||
$ cd easyrules-samples
|
||||
$ mvn exec:java -P runShopTutorialPart1
|
||||
{% endhighlight %}
|
||||
|
||||
You should get the following output:
|
||||
|
||||
```
|
||||
Tom: Hi! can I have some Vodka please?
|
||||
INFO: Rule alcoholRule triggered.
|
||||
Shop: Sorry Tom, you are not allowed to buy alcohol
|
||||
INFO: Rule alcoholRule performed successfully.
|
||||
```
|
||||
|
||||
As expected, since Tom's age is under 18, he has not been allowed to buy alcohol.
|
||||
|
||||
## Part 2 : Changing the legal adult age at runtime
|
||||
|
||||
In this second part, we will expose the legal adult age as a JMX attribute.
|
||||
So first, let's define an interface that allows us to change this age via JMX:
|
||||
|
||||
```java
|
||||
@javax.management.MXBean
|
||||
public interface AgeJmxRule extends JmxRule {
|
||||
|
||||
int getAdultAge();
|
||||
|
||||
void setAdultAge(int adultAge);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Then, we should make our `AgeRule` implement the `AgeJmxRule` interface to expose the the legal adult age as a JMX attribute.
|
||||
So here is the new `AgeRule` class:
|
||||
|
||||
```java
|
||||
public class AgeRule extends BasicRule implements AgeJmxRule {
|
||||
|
||||
private int adultAge = 18;
|
||||
|
||||
private Person person;
|
||||
|
||||
public AgeRule(Person person) {
|
||||
super("AgeRule",
|
||||
"Check if person's age is > 18
|
||||
and marks the person as adult", 1);
|
||||
this.person = person;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean evaluate() {
|
||||
return person.getAge() > adultAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
person.setAdult(true);
|
||||
System.out.printf("Person %s has been marked as adult",
|
||||
person.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAdultAge() {
|
||||
return adultAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdultAge(int adultAge) {
|
||||
this.adultAge = adultAge;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, let's suspend the program to change the legal adult age value at runtime via any compliant JMX client and see the engine behavior after this change:
|
||||
|
||||
```java
|
||||
public class Launcher {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
//create a person instance
|
||||
Person tom = new Person("Tom", 14);
|
||||
System.out.println("Tom:
|
||||
Hi! can I have some Vodka please?");
|
||||
|
||||
//create a Jmx rules engine
|
||||
JmxRulesEngine rulesEngine = aNewJmxRulesEngine()
|
||||
.named("shop rules engine")
|
||||
.build();
|
||||
|
||||
//register rules
|
||||
rulesEngine.registerJmxRule(new AgeRule(tom));
|
||||
rulesEngine.registerRule(new AlcoholRule(tom));
|
||||
|
||||
//fire rules
|
||||
rulesEngine.fireRules();
|
||||
|
||||
// Update adult age via a JMX client.
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println("Change adult age via a JMX client
|
||||
and then press enter");
|
||||
scanner.nextLine();
|
||||
|
||||
System.out.println("Re fire rules after
|
||||
updating adult age...");
|
||||
|
||||
rulesEngine.fireRules();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
To run the second part of the tutorial, run the following command:
|
||||
{% highlight bash %}
|
||||
$ mvn exec:java -P runShopTutorialPart2
|
||||
{% endhighlight %}
|
||||
|
||||
You will be asked to change the legal adult age via a JMX compliant client.
|
||||
|
||||
In the next screenshot, we use <a href="https://visualvm.java.net" target="_blank">VisualVM</a> to change the age value:
|
||||
|
||||
<img style="width: 100%" src="{{site.url}}/img/jmx.png">
|
||||
|
||||
If you change the age value to 13 for example, you will see that Tom will be able to buy alcohol since his age (14) is greater than the new legal adult age (13).
|
||||
|
||||
That's all! In this tutorial, we have seen how to create a real business rule with Easy Rules and how to reconfigure it at runtime.
|
@ -1,97 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Spring tutorial
|
||||
header: Spring tutorial
|
||||
prev_section: tutorials/scheduler-tutorial
|
||||
next_section: get-involved/release-notes
|
||||
doc: true
|
||||
---
|
||||
|
||||
In this tutorial, you will learn how to use Easy Rules embedded in a <a href="http://www.spring.io" target="_blank">Spring</a> container.
|
||||
|
||||
You will create a dummy rule and a rules engine and configure them as Spring beans. So let's get started.
|
||||
|
||||
First you need to add the following dependency to your **_pom.xml_**:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.easyrules</groupId>
|
||||
<artifactId>easyrules-spring</artifactId>
|
||||
<version>{{site.version}}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Then, let's create the dummy rule:
|
||||
|
||||
```java
|
||||
@Rule(name = "dummy rule")
|
||||
public class DummyRule {
|
||||
|
||||
@Condition
|
||||
public boolean when() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Action
|
||||
public void then(){
|
||||
System.out.println("Hey, I'm managed by Spring");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, we we can use the `RulesEngineFactoryBean` to configure a rules engine and register the dummy rule:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<!-- configure rule -->
|
||||
<bean id="rule" class="org.easyrules.samples.spring.DummyRule"/>
|
||||
|
||||
<!-- configure rules engine -->
|
||||
<bean id="rulesEngine"
|
||||
class="org.easyrules.spring.RulesEngineFactoryBean">
|
||||
<property name="rules">
|
||||
<list>
|
||||
<ref bean="rule"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
```
|
||||
|
||||
Finally, we can get the rules engine from the Spring context and fire rules:
|
||||
|
||||
```java
|
||||
public class Launcher {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("org/easyrules/samples/spring/application-context.xml");
|
||||
RulesEngine rulesEngine = (RulesEngine) context.getBean("rulesEngine");
|
||||
|
||||
rulesEngine.fireRules();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
That's all. To run the tutorial, you can follow these instructions from the root directory of Easy Rules:
|
||||
|
||||
{% highlight bash %}
|
||||
$ mvn install
|
||||
$ cd easyrules-samples
|
||||
$ mvn exec:java -P runSpringTutorial
|
||||
{% endhighlight %}
|
||||
|
||||
You would get the following output:
|
||||
|
||||
```
|
||||
INFO: Rule 'dummy rule' triggered.
|
||||
Hey, I'm managed by Spring
|
||||
INFO: Rule 'dummy rule' performed successfully.
|
||||
```
|
||||
|
@ -1,143 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Defining rules
|
||||
header: Defining rules
|
||||
prev_section: user-guide/introduction
|
||||
next_section: user-guide/rule-listener
|
||||
doc: true
|
||||
---
|
||||
|
||||
The key API in Easy Rules is the `Rule` interface:
|
||||
|
||||
```java
|
||||
public interface Rule {
|
||||
|
||||
/**
|
||||
* This method encapsulates the rule's conditions.
|
||||
* @return true if the rule should be applied, false else
|
||||
*/
|
||||
boolean evaluate();
|
||||
|
||||
/**
|
||||
* This method encapsulates the rule's actions.
|
||||
* @throws Exception if an error occurs
|
||||
* during actions performing
|
||||
*/
|
||||
void execute() throws Exception;
|
||||
|
||||
//Getters and setters for rule name,
|
||||
//description and priority omitted.
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
The `evaluate` method encapsulates conditions that must evaluate to _TRUE_ to trigger the rule.
|
||||
|
||||
The `execute` method encapsulates actions that should be performed when rule's conditions are satisfied.
|
||||
|
||||
You can define rules in two ways:
|
||||
|
||||
* By implementing the `Rule` interface or extending the `BasicRule` class
|
||||
* Adding annotations on a POJO
|
||||
|
||||
## Defining rules by extending _BasicRule_
|
||||
|
||||
Easy Rules provides a simple implementation of the `Rule` interface named `BasicRule`. This class implements most of methods
|
||||
defined in the `Rule` interface. You can extends this class and override `evaluate` and
|
||||
`execute` methods to provide your conditions and actions logic. Here is an example:
|
||||
|
||||
```java
|
||||
public class MyRule extends BasicRule {
|
||||
|
||||
private BusinessData myBusinessData; //data to operate on
|
||||
|
||||
@Override
|
||||
public boolean evaluate() {
|
||||
//my rule conditions
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
//my actions
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Defining rules using annotations
|
||||
|
||||
Easy Rules provides the `@Rule` annotation that can turn a POJO into a rule. Here is an example:
|
||||
|
||||
```java
|
||||
@Rule(name = "my rule", description = "my rule description")
|
||||
public class MyRule {
|
||||
|
||||
private BusinessData myBusinessData; //data to operate on
|
||||
|
||||
@Condition
|
||||
public boolean when() {
|
||||
//my rule conditions
|
||||
return true;
|
||||
}
|
||||
|
||||
@Action(order = 1)
|
||||
public void then() throws Exception {
|
||||
//my actions
|
||||
}
|
||||
|
||||
@Action(order = 2)
|
||||
public void finally() throws Exception {
|
||||
//my final actions
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
The `@Condition` annotation marks the method to execute to evaluate the rule conditions.
|
||||
This method must be public, have no parameters and return a boolean type. Only one method can be annotated with `@Condition` annotation.
|
||||
|
||||
The `@Action` annotation marks methods to execute to perform rule actions. Rules can have multiple actions.
|
||||
|
||||
<div class="note info">
|
||||
<h5>Actions can be executed in a specified order</h5>
|
||||
<p>You can also define the execution order of actions with the
|
||||
<em>order</em> attribute:<br/><em>@Action(order = 1)</em><br/>By default, the order of an action is 0.</p>
|
||||
</div>
|
||||
|
||||
|
||||
## Composite rules
|
||||
|
||||
Easy Rules allows you to create complex rules from primitive ones. A `CompositeRule` is composed of a set of rules.
|
||||
|
||||
This is typically an implementation of the <a href="http://en.wikipedia.org/wiki/Composite_pattern" target="_blank">composite design pattern</a>.
|
||||
|
||||
A composite rule is triggered if **_all_** conditions of its composing rules are satisfied.
|
||||
When a composite rule is applied, actions of **_all_** composing rules are performed in the **natural order** of
|
||||
rules which is rules priorities by default.
|
||||
|
||||
To create a composite rule from two primitive rules, you can use the following snippet:
|
||||
|
||||
```java
|
||||
//Create a composite rule from two primitive rules
|
||||
CompositeRule myCompositeRule =
|
||||
new CompositeRule("myCompositeRule", "a composite rule");
|
||||
myCompositeRule.addRule(myRule1);
|
||||
myCompositeRule.addRule(myRule2);
|
||||
|
||||
//Register the composite rule as a regular rule
|
||||
RulesEngine rulesEngine = aNewRulesEngine().build();
|
||||
rulesEngine.registerRule(myCompositeRule);
|
||||
```
|
||||
|
||||
## Rules priorities
|
||||
|
||||
Each rule in Easy Rules has a priority. This represents the default order in which registered rules are fired.
|
||||
By default, lower values represent higher priorities.
|
||||
To override this behavior, you should override the `compareTo` method to provide a custom priority strategy.
|
||||
|
||||
* If you decided to extend the `BasicRule` class, you can specify rule priority at construction time or by overriding
|
||||
the `getPriority()` method
|
||||
|
||||
* If your rule is a annotated POJO, you should annotate the method that provides priority with `@Priority` annotation.
|
||||
This method must be public, have no arguments and return an Integer type
|
@ -1,99 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Embedding rules engine
|
||||
header: Embedding rules engine
|
||||
prev_section: user-guide/scheduling-rules-engine
|
||||
next_section: tutorials/hello-world-tutorial
|
||||
doc: true
|
||||
---
|
||||
|
||||
Easy Rules is a lightweight library that can be used in a standalone Java application or embedded in a web server or a dependency injection container.
|
||||
|
||||
As of version 2.1.0, Easy Rules provides support for <a href="http://www.spring.io" target="_blank">Spring</a>.
|
||||
Support for other DI containers will be added in future versions.
|
||||
|
||||
In this section, you will learn how to configure rules and rules engine as Spring beans.
|
||||
First you need to add the following dependency to your **_pom.xml_**:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.easyrules</groupId>
|
||||
<artifactId>easyrules-spring</artifactId>
|
||||
<version>{{site.version}}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Then, you can configure your rules and the rules engine as follows:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<!-- configure rule -->
|
||||
<bean id="rule" class="DummyRule" scope="prototype"/>
|
||||
|
||||
<!-- configure rule listener -->
|
||||
<bean id="ruleListener" class="DummyRuleListener"/>
|
||||
|
||||
<!-- configure rules engine -->
|
||||
<bean id="rulesEngine" class="org.easyrules.spring.RulesEngineFactoryBean">
|
||||
<property name="skipOnFirstAppliedRule" value="true"/>
|
||||
<property name="skipOnFirstFailedRule" value="true"/>
|
||||
<property name="rulePriorityThreshold" value="10"/>
|
||||
<property name="silentMode" value="false"/>
|
||||
<property name="rules">
|
||||
<list>
|
||||
<ref bean="rule"/>
|
||||
</list>
|
||||
</property>
|
||||
<property name="ruleListeners">
|
||||
<list>
|
||||
<ref bean="ruleListener"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
```
|
||||
|
||||
The `RulesEngineFactoryBean` is responsible for creating rules engine instances.
|
||||
As you can see, this factory bean is the main entry point to configure:
|
||||
|
||||
* Rules
|
||||
* Rules listeners
|
||||
* And engine parameters (priority threshold, skipOnFirstAppliedRule, silentMode, etc)
|
||||
|
||||
<div id="thread-safety" class="note info">
|
||||
<h5>Heads up!</h5>
|
||||
<p>If your rules are not thread safe, you should consider make them of scope <strong>prototype</strong>.</p>
|
||||
<p>The rules engine instance returned by the <code>RulesEngineFactoryBean</code> is already of scope <strong>prototype</strong>.</p>
|
||||
</div>
|
||||
|
||||
To get the engine and fires rules, you can use the following snippet:
|
||||
|
||||
```java
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
|
||||
RulesEngine rulesEngine = (RulesEngine) context.getBean("rulesEngine");
|
||||
|
||||
rulesEngine.fireRules();
|
||||
```
|
||||
|
||||
<div class="note">
|
||||
<h5>Hint:</h5>
|
||||
<p>The main advantage of using Easy Rules with Spring is the ability to register/unregister rules through the Xml configuration
|
||||
without recompiling your application.</p>
|
||||
</div>
|
||||
|
||||
You can find a complete tutorial on how to use Easy Rules with Spring [here]({{site.url}}/tutorials/spring-tutorial.html).
|
||||
|
||||
# Using the @SpringRule annotation
|
||||
|
||||
The `@SpringRule` annotation is a meta-annotation that turns a POJO into:
|
||||
|
||||
* A rule compatible with Easy Rules
|
||||
* A **prototype-scoped** Spring bean
|
||||
|
||||
This annotation is the combination of `@Rule` and `@Component` annotations.
|
@ -1,21 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Introduction
|
||||
header: Introduction
|
||||
prev_section: about/getting-started
|
||||
next_section: user-guide/defining-rules
|
||||
doc: true
|
||||
---
|
||||
|
||||
Most business rules can be represented by the following definition:
|
||||
|
||||
* _Name_: a unique rule name within a rules namespace
|
||||
* _Description_: a brief description of the rule
|
||||
* _Priority_: rule priority regarding to other rules
|
||||
* _Conditions_: set of conditions that should be satisfied to apply the rule
|
||||
* _Actions_: set of actions to perform when conditions are satisfied
|
||||
|
||||
Easy Rules provides an abstraction for each of these key points to define business rules.
|
||||
|
||||
Next section will show you how to define a rule either by extending a base class provided by Easy Rules or by annotating your
|
||||
own domain class.
|
@ -1,42 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Managing rules
|
||||
header: Managing rules at runtime
|
||||
prev_section: user-guide/rules-engine
|
||||
next_section: user-guide/scheduling-rules-engine
|
||||
doc: true
|
||||
---
|
||||
|
||||
Being able to dynamically reconfigure business rules at runtime in production systems is a recurrent requirement.
|
||||
|
||||
Thanks to JMX, Easy Rules can expose rules attributes to be managed via any JMX compliant client.
|
||||
|
||||
First, you need to add the following dependency to your **_pom.xml_**:
|
||||
|
||||
```xml
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.easyrules</groupId>
|
||||
<artifactId>easyrules-jmx</artifactId>
|
||||
<version>{{site.version}}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
To make your rule manageable via JMX, it should:
|
||||
|
||||
* implement the `JmxRule` interface or extend the `BasicJmxRule` class
|
||||
* or be annotated with `javax.management.MXBean` if it is a annotated POJO
|
||||
|
||||
Once you defined your rule as a Jmx compliant object, you can register it in a `JmxRulesEngine` as a managed rule:
|
||||
|
||||
```java
|
||||
JmxRulesEngine rulesEngine = aNewJmxRulesEngine.build();
|
||||
rulesEngine.registerJmxRule(myJmxCompliantRule);
|
||||
```
|
||||
|
||||
This will register your rule as a JMX managed bean with the following object name:
|
||||
|
||||
`org.easyrules.core.jmx:type=YourRuleClassName,name=YourRuleName`
|
||||
|
||||
An example of using dynamic rule reconfiguration at runtime is provided in the [shop tutorial]({{site.url}}/tutorials/shop-tutorial.html).
|
@ -1,38 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Rule listener
|
||||
header: Rule listener
|
||||
prev_section: user-guide/defining-rules
|
||||
next_section: user-guide/rules-engine
|
||||
doc: true
|
||||
---
|
||||
|
||||
You can listen to rule execution events through the `RuleListener` API:
|
||||
|
||||
```java
|
||||
public interface RuleListener {
|
||||
/**
|
||||
* Triggered before a rule is executed.
|
||||
*/
|
||||
void beforeExecute(Rule rule);
|
||||
/**
|
||||
* Triggered after a rule is executed successfully.
|
||||
*/
|
||||
void onSuccess(Rule rule);
|
||||
/**
|
||||
* Triggered after a rule is executed with error.
|
||||
*/
|
||||
void onFailure(Rule rule, Exception exception);
|
||||
}
|
||||
```
|
||||
|
||||
You can implement this interface to provide custom behavior to execute before/after each rule.
|
||||
To register your listener, use the following snippet:
|
||||
|
||||
```java
|
||||
RulesEngine rulesEngine = aNewRulesEngine()
|
||||
.withRuleListener(myRuleListener)
|
||||
.build();
|
||||
```
|
||||
|
||||
You can register as many listeners as you want, they will be executed in their registration order.
|
@ -1,96 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Rules engine
|
||||
header: Rules engine
|
||||
prev_section: user-guide/defining-rules
|
||||
next_section: user-guide/managing-rules
|
||||
doc: true
|
||||
---
|
||||
|
||||
Easy Rules engine holds a registry of rules with unique names. Each instance of Easy Rules engine can be seen as a separate namespace.
|
||||
|
||||
Rules are applied according to their natural order (which is priority by default).
|
||||
|
||||
## Create a rules engine
|
||||
|
||||
To create a rules engine and register a rule, you can use the static method `RulesEngineBuilder.aNewEngineBuilder()`:
|
||||
|
||||
```java
|
||||
RulesEngine rulesEngine = aNewEngineBuilder().build();
|
||||
rulesEngine.registerRule(myRule);
|
||||
```
|
||||
|
||||
You can then fire registered rules as follows:
|
||||
|
||||
```java
|
||||
rulesEngine.fireRules();
|
||||
```
|
||||
|
||||
## Rules engine parameters
|
||||
|
||||
Easy Rules engine can be configured with the following parameters:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th>Parameter</th>
|
||||
<th>Type</th>
|
||||
<th>Required</th>
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>rulePriorityThreshold</td>
|
||||
<td>int</td>
|
||||
<td>no</td>
|
||||
<td>Integer.MAX_VALUE</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>skipOnFirstAppliedRule</td>
|
||||
<td>boolean</td>
|
||||
<td>no</td>
|
||||
<td>false</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>skipOnFirstFailedRule</td>
|
||||
<td>boolean</td>
|
||||
<td>no</td>
|
||||
<td>false</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>silentMode</td>
|
||||
<td>boolean</td>
|
||||
<td>no</td>
|
||||
<td>false</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
* The `skipOnFirstAppliedRule` parameter tells the engine to skip next rules when a rule is applied.
|
||||
|
||||
* The `skipOnFirstFailedRule` parameter tells the engine to skip next rules when a rule fails.
|
||||
|
||||
* The `rulePriorityThreshold` parameter tells the engine to skip next rules if priority exceeds the defined threshold.
|
||||
|
||||
* The `silentMode` allows you to mute all loggers when needed.
|
||||
|
||||
You can specify these parameters through the `RulesEngineBuilder` API:
|
||||
|
||||
```java
|
||||
RulesEngine rulesEngine = aNewRulesEngine()
|
||||
.withRulePriorityThreshold(10)
|
||||
.withSkipOnFirstAppliedRule(true)
|
||||
.withSkipOnFirstFailedRule(true)
|
||||
.withSilentMode(true)
|
||||
.build();
|
||||
```
|
||||
|
||||
All parameters are encapsulated in the `RulesEngineParameters` class. If you want to get parameters from your engine,
|
||||
you can use the following snippet:
|
||||
|
||||
```java
|
||||
RulesEngineParameters parameters = myEngine.getParameters();
|
||||
```
|
||||
|
||||
This allows you to reset the engine parameters after its creation.
|
@ -1,48 +0,0 @@
|
||||
---
|
||||
layout: docs
|
||||
title: Scheduling rules engine
|
||||
header: Scheduling a rules engine
|
||||
prev_section: user-guide/managing-rules
|
||||
next_section: user-guide/embedding-rules-engine
|
||||
doc: true
|
||||
---
|
||||
|
||||
Easy Rules provides APIs to schedule a rules engine using the popular Java scheduler <a href="http://www.quartz-scheduler.org" target="_blank">Quartz</a>.
|
||||
|
||||
To schedule a rules engine instance, first you need to add the following dependency to your **_pom.xml_**:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.easyrules</groupId>
|
||||
<artifactId>easyrules-quartz</artifactId>
|
||||
<version>{{site.version}}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Then, you can create a `RulesEngineScheduler` as follows:
|
||||
|
||||
```java
|
||||
RulesEngine rulesEngine = aNewRulesEngine().build();
|
||||
|
||||
Date now = new Date();
|
||||
int everySecond = 1;
|
||||
|
||||
RulesEngineScheduler scheduler = RulesEngineScheduler.getInstance();
|
||||
scheduler.scheduleAtWithInterval(rulesEngine, now, everySecond);
|
||||
```
|
||||
|
||||
This will schedule the rules engine to start now and repeat every second.
|
||||
|
||||
The `RulesEngineScheduler` API provides methods to schedule a rules engine:
|
||||
|
||||
* At a fixed point of time using `scheduleAt(RulesEngine engine, Date when)`
|
||||
* Repeatedly with a predefined interval using `scheduleAtWithInterval(RulesEngine engine, Date when, int interval)`
|
||||
* Using unix cron-like expression with `scheduleCron(RulesEngine engine, String cronExpression)`
|
||||
|
||||
To unregister a rules engine, use the following snippet:
|
||||
|
||||
```java
|
||||
scheduler.unschedule(rulesEngine);
|
||||
```
|
||||
|
||||
You can find a tutorial about scheduling rules engine in the [Scheduler tutorial]({{site.url}}/tutorials/scheduler-tutorial.html).
|
Loading…
Reference in New Issue