Jess Rule Engine és JSR 94

1. Áttekintés

A szabálymotor használata nagyszerű módja annak, hogy elválasszuk az üzleti logikát a kazánlap kódjától, és megvédjük alkalmazáskódunkat az üzleti változásoktól.

A Java Rule Motorokról szóló korábbi cikkünkben megemlítettük a JSR 94 specifikációt. A Jess Rule motornak különös jelentősége vanreferencia-szabályként a JSR 94 meghajtó végrehajtása, tehát vessünk egy pillantást rá.

2. Jess szabály motor

A Jess az egyik legkorábbi szabálymotor, amely könnyen integrálható a Java-val. Jess a rendkívül hatékony Rete algoritmus továbbfejlesztett megvalósítását használja, ami a legtöbb esetben sokkal gyorsabb, mint egy egyszerű Java hurok.

A szabályok végrehajthatók a natív Jess szabályok nyelvén, kibővített Lisp-alapú szintaxissal írt szabálykészletekből, vagy egy sokkal részletesebb XML formátumból. A natív formátumot fogjuk használni.

Van egy Eclipse-alapú IDE a fejlesztéshez (az Eclipse régebbi verzióihoz) és néhány kiváló dokumentáció a Jess használatáról és a Java-val történő integrálásáról. Van még egy REPL parancssori felület is, ahol kipróbálhatjuk ötleteinket, mielőtt létrehoznánk egy szabályfájlt.

A JSR 94 referencia-szabálymotorjaként Jess definíció szerint megfelel a JSR 94-nek, bár már nincs aktív fejlesztés alatt.

2.1. Gyors szó a JSR 94-ről

A JSR 94 biztosít egy API-t, amellyel függetlenséget biztosíthatunk a választott szabálymotortól. Bármely JSR 94 kompatibilis szabálymotort bekapcsolhatunk a kódunkba, és futtathatunk néhány szabályt anélkül, hogy módosítanunk kellene a szabálymotorral való interakciót az alkalmazásunkban.

Ez nem azt jelenti, hogy a szabálymotor alapjául szolgáló szabályok ugyanúgy néznek ki - lehet, hogy ezeket át kell írnunk, ha megváltoztatjuk a szabálymotort, de ez azt jelenti, hogy az új szabálymotor használatához nem kell átírnunk alkalmazásunk egyes részeit. Az egyetlen kódváltozásra szükségünk lesz, hogy frissítsük az illesztőprogram nevét és néhány szabályfájl nevét.

2.2. A Jess JSR 94 pilóta

Bár van egy referencia szabály motor sofőr Jess esetében, amely a JSR 94-hez tartozik, maga Jess nem szerepel, mivel ez egy engedélyezett kereskedelmi termék. A referencia meghajtó a org.jcp.jsr94.jess csomagot, de egy újabb illesztőprogram elérhető a jess.jsr94 csomagot, amikor letöltjük Jess-t.

Kezdjük azzal, hogy megnézzük Jess natív Java integrációját, mielőtt továbblépnénk, hogy lássuk, hogyan változtatja meg ezt a JSR 94 réteg.

3. Bemutatott példák

Mielőtt elkezdenénk integrálni Jess-t a kódunkba, győződjünk meg arról, hogy letöltöttük és elérhetővé tettük az osztályúton. Regisztrálnunk kell az ingyenes 30 napos próbaverzió letöltésére, hacsak még nincs licencünk.

Tehát töltsük le Jess-t, csomagoljuk ki a letöltöttet Jess71p2.jar, és futtassa az egyik példáját, hogy megbizonyosodjon arról, hogy van-e működő verziónk.

3.1. Önálló Jess

Nézzük meg a Jess71p2 / példák könyvtár, ahol a jess könyvtár tartalmaz néhány példa szabálykészletet. A pricing_engine a könyvtár egy integrációt mutat, amelyet egy hangyán keresztül lehet végrehajtani build.xml forgatókönyv. Változtassuk könyvtárunkat az árazási motor példájára, és futtassuk a programot hangya teszt:

cd Jess71p2 / example / pricing_engine ant teszt

Ez felépíti és futtatja az árképzési példa példáját:

Buildfile: Jess71p2 \ example \ pricing_engine \ build.xml ... test: [java] Elemek a 123-as rendeléshez: [java] 1 CD-író: 199,99 ... [java] A 666-os rendeléshez tartozó elemek: [java] 1 Incredibles DVD: 29,99 [java] Ajánlatok a 666-os megrendeléshez: [java] SIKERES ÉPÍTÉS Teljes idő: 1 másodperc

3.2. Jess JSR 94-gyel

Most, hogy Jess dolgozik, töltsük le a JSR 94-et, majd csomagoljuk ki, hogy létrehozzunk egy jsr94-1.0 könyvtárat, benne ant, doc, lib és src könyvtárakkal.

csomagolja ki a jreng-1_0a-fr-spec-api.zip fájlt

Ez megadja a JSR 94 API-t és a Jess referencia-illesztőprogramot, de nem jár a licencelt Jess-implementációval, így ha most megpróbálunk futtatni egy példát, a következő hibát kapjuk:

Hiba: A Jess referencia-megvalósítás nem található.

Tehát tegyük hozzá a Jess referencia megvalósítást, jess.jar, amely a korábban letöltött Jess71p2 részeként jött létre, és átmásoltuk a JSR 94 lib könyvtárba, majd futtassuk a példát:

cp Jess71p2 / lib / jess.jar jsr94-1.0 / lib / java -jar jsr94-1.0 / lib / jsr94-example.jar

A példa néhány szabályt futtat az ügyfél fennmaradó jóváírásának meghatározásához a számlák kifizetésekor:

Administration API megszerzett RuleAdministrator: [e-mail védett] ... Futásidejű API megszerzett RuleRuntime: [e-mail védett] Ügyfél hitelkeretének eredménye: 3000 ... 2. számla összege: 1750 állapota: kifizetett Released Stateful Rule Session.

4. Jess integrálása a Java-ba

Most, hogy letöltöttük a Jess és a JSR 94 programokat, és futtattunk néhány szabályt natív módon és a JSR-en keresztül is, nézzük meg, hogyan lehet integrálni a Jess szabálykészletet egy Java programba.

Példánkban egy egyszerű Jess-szabályfájl futtatásával kezdjük, hellojess.clp, Java kódból, majd nézzen meg egy másik szabályfájlt, bónusz.clp, amely felhasználja és módosítja néhány objektumunkat.

4.1. Maven-függőség

Jess számára nem áll rendelkezésre Maven-függőség, ezért ha még nem tettük meg, töltsük le és csomagoljuk ki a Jess-t (jess.jar) és mvn install a helyi Maven-tárunkba:

mvn install: install-file -Dfile = jess.jar -DgroupId = gov.sandia -DartifactId = jess -Dversion = 7.1p2 -Dpackaging = jar -DgeneratePom = true

Ezután hozzáadhatjuk függőségként a szokásos módon:

 gov.sandia jess 7.1p2 

4.2. Hello Jess szabályok fájlja

Ezután hozzuk létre a legegyszerűbb szabályfájlokat az üzenet kinyomtatásához. Mentjük a szabályfájlt hellojess.clp:

(kinyomtatott t "Hello Jess-től!" crlf)

4.3. Jess Rule Engine

Most hozzunk létre egy példányt a Jess-ről Rete szabály motor, Visszaállítás() kezdeti állapotába töltse be a szabályokat hellojess.clp, és futtassa őket:

public class HelloJess {public static void main (String [] args) dobja JessException {Rete motor = new Rete (); motor.reset (); motor.batch ("hellojess.clp"); motor.fut (); }

Ehhez az egyszerű példához csak hozzáadtuk a lehetőséget JessException a miénknek fő- mód dob kikötés.

A program futtatásakor látni fogjuk a kimenetet:

Hello Jess-től!

5. Jess integrálása a Java-ba adatokkal

Most, hogy mindent helyesen telepítettünk és futtathatunk szabályokat, nézzük meg, hogyan adunk hozzá adatokat a szabálymotor feldolgozásához, és hogyan szerezzük be az eredményeket.

Először szükségünk lesz néhány Java osztályra, hogy működjünk, majd egy új szabálykészlettel, amely ezeket használja.

5.1. Modell

Készítsünk néhány egyszerűt Kérdés és Válasz osztályok:

public class Kérdés {private String kérdés; privát int mérleg;  // getterek és beállítók  nyilvános kérdés (String kérdés, int egyensúly) {this.question = kérdés; ez.egyensúly = egyensúly; }} public class Answer {private String válasz; private int newBalance;  // getterek és beállítók  public Answer (String válasz, int newBalance) {this.answer = válasz; this.newBalance = newBalance; }}

5.2 Jess-szabály bemenettel és kimenettel

Most hozzunk létre egy egyszerű Jess-szabálykészletet bónusz.clp hogy elhaladunk a Kérdés és kap egy Válasz tól től.

Először mi import a mi Kérdés és Válasz osztályokat, majd használja a Jess-eket deftemplate funkció elérhetővé tétele a szabálymotor számára:

(com.baeldung.rules.jsr94.jess.model. * importálása) (deftemplate Kérdés (deklarálás (osztályból származó kérdés))) (Deftemplate Answer (deklarálás (osztályon belüli válasz)))

Vegye figyelembe a zárójelek használatát, amelyek Jess függvényhívásokat jelölnek.

Most használjuk megrontani egyetlen szabály hozzáadásához elkerülni-folyószámlahitel Jess kibővített Lisp formátumában, amely 50 dolláros bónuszt ad nekünk, ha az egyenleg a mi Kérdés nulla alatt van:

(az "50 dollárt adj mindenkinek, aki túlhúzott"? q <- (kérdés {egyenleg (add (új válasz: "Túlhúzott bónusz" (+? q.egyensúly 50))))

Itt a „?” objektumot köt egy változóhoz q amikor a „jobb oldali<-“ mérkőzés. Ebben az esetben a szabálymotor akkor találja meg a Kérdés hogy van egy egyensúly kevesebb, mint 0.

Amikor ez megtörténik, akkor a „=>” működésbe lépnek, így a motor hozzás a új Válasz objektum a munkamemória ellen. Megadjuk a két szükséges konstruktor argumentumot: “Overdrawn bonus” a válasz paraméter és a (+) függvény a newAmount paraméter.

5.3. Adatok kezelése a Jess Rule motorral

Tudjuk használni add () egyszerre egyetlen objektumot hozzáadni a szabály motorunk munkamemóriájához, vagy az összes hozzáadása() adatgyűjtemény hozzáadásához. Használjuk add () egyetlen kérdés hozzáadásához:

Kérdés kérdés = új kérdés ("Kaphatok bónuszt?", -5); motor.add (adatok);

Ha az összes adatunk a helyén van, hajtsuk végre a szabályainkat:

motor.fut ();

A Jess Rete a motor varázslatos lesz, és visszatér, ha minden vonatkozó szabály végrehajtásra kerül. Esetünkben lesz egy Válasz megvizsgálni.

Használjuk a jess.Szűrő hogy kivonjuk a mi Válasz a szabály motorból egy an Iterálható eredmények objektum:

Iterátor eredmények = motor.getObjects (új jess.Filter.ByClass (Answer.class)); while (results.hasNext ()) {Válasz válasz = (Válasz) results.next (); // válaszunk feldolgozása}

Egyszerű példánkban nincs referenciaadat, de ha mégis, használhatjuk a WorkingMemoryMarker és motor.mark () az adatok hozzáadása után a szabálymotor munkamemóriájának állapotának megjelölésére. Akkor hívhatunk motor.resetToMark markerünkkel állítsuk vissza a munkamemóriát a „betöltött” állapotunkba, és hatékonyan használjuk fel újra a szabálymotort egy másik objektumkészlethez:

WorkingMemoryMarker marker; // terhelési referenciaadat jelölő = motor.mark (); // specifikus adatok betöltése és a szabályok futtatása engine.resetToMark (marker);

Most nézzük meg, hogyan futtatjuk ugyanazt a szabálykészletet a JSR 94 használatával.

6. A JSR 94 használata a Jess Rule Engine integrálásához

A JSR 94 szabványosítja a kódunk és egy szabálymotor kölcsönhatását. Ez megkönnyíti a szabálymotor cseréjét anélkül, hogy jelentősen megváltoztatnánk az alkalmazásunkat, ha jobb alternatíva jön.

A JSR 94 API két fő csomagban található:

  • javax.rules.admin - a járművezetők és szabályok betöltéséhez
  • javax.szabályok - a szabályok futtatása és az eredmények kinyerése

Megvizsgáljuk, hogyan lehet használni az osztályokat mindkettőben.

6.1. Maven-függőség

Először adjunk hozzá egy Maven-függőséget jsr94:

 jsr94 jsr94 1.1 

6.2. Adminisztráció API

A JSR 94 használatának megkezdéséhez példányt kell adnunk a RuleServiceProvider. Hozzunk létre egyet, átadva a Jess-szabályokat:

Karakterlánc RULE_SERVICE_PROVIDER = "jess.jsr94"; Class.forName (RULE_SERVICE_PROVIDER + ".RuleServiceProviderImpl"); RuleServiceProvider ruleServiceProvider = RuleServiceProviderManager.getRuleServiceProvider (RULE_SERVICE_PROVIDER);

Most szerezzük be Jess JSR 94-est RuleAdministrator, töltsük be a példakészletet egy JSR 94-be RuleExecutionSet, és regisztrálja végrehajtásra egy választott URI-val:

RuleAdministrator ruleAdministrator = serviceProvider.getRuleAdministrator (); InputStream ruleInput = JessRunner.class.getResourceAsStream (rulesFile); HashMap vendorProperties = new HashMap (); RuleExecutionSet ruleExecutionSet = ruleAdministrator .getLocalRuleExecutionSetProvider (vendorProperties) .createRuleExecutionSet (ruleInput, vendorProperties); String szabályokURI = "szabályok: // com / baeldung / szabályok / bónusz"; ruleAdministrator.registerRuleExecutionSet (rulesURI, ruleExecutionSet, vendorProperties);

A Jess sofőrnek nincs szüksége vendorProperties térképet szolgáltattunk RuleAdministrator, de ez a felület része, és más gyártók megkövetelhetik.

Most, hogy a szabálymotor-szolgáltatónkat, Jess inicializáltuk és a szabálykészletünket regisztráltuk, majdnem készen állunk a szabályok futtatására.

Mielőtt futtathatnánk őket, egy futásidejű példányra és egy munkamenetre van szükségünk a futtatáshoz. Adjunk hozzá helyőrzőt is, calcResults (), mert hol fog történni a varázslat, és engedje el a munkamenetet:

RuleRuntime ruleRuntime = ruleServiceProvider.getRuleRuntime (); StatelessRuleSession statelessRuleSession = (StatelessRuleSession) ruleRuntime.createRuleSession (rulesURI, új HashMap (), RuleRuntime.STATELESS_SESSION_TYPE); calcResults (statelessRuleSession); statelessRuleSession.release ();

6.3. Végrehajtási API

Most, hogy minden a helyén van, hajtsuk végre eredményeket számol kezdeti adataink megadásához, szabályaink hontalan munkamenetben történő végrehajtásához és az eredmények kinyeréséhez:

Lista adatok = new ArrayList (); data.add (új kérdés ("Van-e bónuszom?", -5)); Eredmények felsorolása = statelessRuleSession.executeRules (adatok);

Mivel a JSR 94-et még a JDK 5 megjelenése előtt írták, az API nem használ generikumokat, ezért használjunk csak egy Iterátor az eredmények megtekintéséhez:

Iterátor itr = eredmények.iterátor (); while (itr.hasNext ()) {Object obj = itr.next (); if (a Answer objektuma) {int answerBalance = ((Answer) obj) .getCalculatedBalance ()); }}

Példánkban hontalan munkamenetet használtunk, de létrehozhatunk egy StatefuleRuleSession ha fenn akarjuk tartani az állapotot az invokációk között.

7. Következtetés

Ebben a cikkben megtanultuk, hogyan integrálhatjuk a Jess szabálymotort alkalmazásunkba Jess natív osztályainak használatával, és valamivel több erőfeszítéssel a JSR 94 használatával. Láttuk, hogyan lehet az üzleti szabályokat külön fájlokká különíteni, amelyek feldolgozásra kerülnek a szabály motor által, amikor alkalmazásunk fut.

Ha ugyanarra az üzleti logikára vonatkozó szabályaink vannak, amelyeket egy másik JSR 94 kompatibilis szabálymotorhoz írtunk, akkor egyszerűen hozzáadhatjuk az alternatív szabálymotor illesztőprogramját, és frissíthetjük az alkalmazás által használt illesztőprogram nevét, és nem kell további kódváltozásokat végrehajtani. szükséges.

További részletek a jess.sandia.gov címen találhatók: Jess beágyazása Java-alkalmazásokba, az Oracle pedig hasznos útmutatóval rendelkezik a Java Rule Engine API használatának megkezdéséhez (JSR 94).

Szokás szerint a cikkben megnézett kód elérhető a GitHubon.