Jess Rule Engine en JSR 94

1. Overzicht

Het gebruik van een rule engine is een geweldige manier om de bedrijfslogica te scheiden van onze standaardcode en om onze applicatiecode te beschermen tegen zakelijke wijzigingen.

In een eerder artikel over Java Rule Engines noemden we de JSR 94-specificatie. De Jess Rule Engine is bijzonder belangrijkals de implementatie van de referentieregels voor JSR 94, dus laten we er eens naar kijken.

2. Jess Rule Engine

Jess is een van de eerste regelengines die gemakkelijk met Java kan worden geïntegreerd. Jess gebruikt een verbeterde implementatie van het zeer efficiënte Rete-algoritme, waardoor het voor de meeste scenario's veel sneller is dan een eenvoudige Java-lus.

Regels kunnen worden uitgevoerd vanuit regelsets die zijn geschreven in de native Jess Rules Language, een uitgebreide op Lisp gebaseerde syntaxis, of vanuit een meer uitgebreide XML-indeling. We gebruiken het oorspronkelijke formaat.

Er is een op Eclipse gebaseerde IDE voor ontwikkeling (voor oudere versies van Eclipse) en een aantal uitstekende documentatie over het gebruik en de integratie van Jess met Java. Er is zelfs een REPL-opdrachtregelinterface waar we onze ideeën kunnen uitproberen voordat we een regelbestand maken.

Als de referentieregel-engine voor JSR 94, is Jess per definitie JSR 94-compatibel, hoewel het niet langer actief wordt ontwikkeld.

2.1. Een kort woord over JSR 94

JSR 94 biedt een API die we kunnen gebruiken om ons onafhankelijk te maken van welke rule engine we ook kiezen. We kunnen elke JSR 94-compliant rule engine in onze code pluggen en enkele regels uitvoeren zonder dat we de manier waarop we omgaan met de rule engine in onze applicatie hoeven te veranderen.

Dit betekent niet dat de onderliggende regels van de rule engine er hetzelfde uitzien - het kan zijn dat we deze moeten herschrijven als we de rule engine wijzigen, maar het betekent wel dat we delen van onze applicatie niet hoeven te herschrijven om de nieuwe rule engine te gebruiken. De enige codewijzigingen die we nodig hebben, zijn het bijwerken van de naam van het stuurprogramma en enkele namen van regelbestanden.

2.2. De Jess JSR 94-driver

Hoewel er een engine voor referentieregels is bestuurder voor Jess inbegrepen voor JSR 94, Jess zelf is niet inbegrepen, aangezien het een commercieel gelicentieerd product is. De referentiestuurprogramma komt in de org.jcp.jsr94.jess pakket, maar er is een nieuwere driver beschikbaar in het jess.jsr94 pakket wanneer we Jess downloaden.

Laten we beginnen met het bekijken van de native Java-integratie van Jess voordat we verder gaan om te zien hoe de JSR 94-laag dit verandert.

3. Verstrekte voorbeelden

Voordat we Jess in onze code gaan integreren, moeten we ervoor zorgen dat we het hebben gedownload en beschikbaar hebben gemaakt op ons klassenpad. We moeten ons registreren voor de gratis proefversie van 30 dagen, tenzij we al een licentie hebben.

Dus laten we Jess downloaden, het gedownloade Jess71p2.jar, en voer een van de voorbeelden uit om er zeker van te zijn dat we een werkende versie hebben.

3.1. Zelfstandige Jess

Laten we eens kijken in de Jess71p2 / voorbeelden directory, waar het Jess directory bevat enkele voorbeeldregelsets. De pricing_engine directory toont een integratie die kan worden uitgevoerd via een ant build.xml script. Laten we onze directory wijzigen naar het voorbeeld van de prijsbepalingsengine en het programma uitvoeren via mieren test:

cd Jess71p2 / voorbeelden / pricing_engine ant test

Hiermee wordt een voorbeeld van een prijsregelset gebouwd en uitgevoerd:

Buildfile: Jess71p2 \ voorbeelden \ pricing_engine \ build.xml ... test: [java] Artikelen voor bestelling 123: [java] 1 CD-schrijver: 199,99 ... [java] Artikelen voor bestelling 666: [java] 1 Incredibles-dvd: 29.99 [java] Aanbieding voor bestelling 666: [java] BOUW SUCCESVOL Totale tijd: 1 seconde

3.2. Jess met JSR 94

Nu we Jess aan het werk hebben, gaan we JSR 94 downloaden en het vervolgens uitpakken om een ​​jsr94-1.0-directory te maken met daarin de mappen ant, doc, lib en src.

unzip jreng-1_0a-fr-spec-api.zip

Dit geeft ons de JSR 94 API en Jess-referentiestuurprogramma, maar het wordt niet geleverd met de gelicentieerde Jess-implementatie, dus als we nu een voorbeeld proberen uit te voeren, krijgen we de volgende foutmelding:

Fout: de referentie-implementatie Jess is niet gevonden.

Dus laten we de Jess-referentie-implementatie toevoegen, jess.jar, dat kwam als onderdeel van de Jess71p2 die we eerder hebben gedownload en kopieer het naar de JSR 94-lib-map, voer dan het voorbeeld uit:

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

In het voorbeeld worden enkele regels uitgevoerd om het resterende krediet van een klant te bepalen wanneer facturen worden betaald:

Beheer API verworven RuleAdministrator: [e-mail beschermd] ... Runtime API verworven RuleRuntime: [e-mail beschermd] Resultaat kredietlimiet klant: 3000 ... Factuur 2 bedrag: 1750 status: betaald Vrijgegeven stateful regelsessie.

4. Jess integreren met Java

Nu we Jess en JSR 94 hebben gedownload en enkele regels zowel native als via de JSR hebben uitgevoerd, laten we eens kijken hoe we een Jess-regelset in een Java-programma kunnen integreren.

In ons voorbeeld beginnen we met het uitvoeren van een eenvoudig Jess-regelsbestand, hallojess.clp, van Java-code, en kijk dan naar een ander regelbestand, bonus.clp, die enkele van onze objecten zullen gebruiken en wijzigen.

4.1. Afhankelijkheid van Maven

Er is geen Maven-afhankelijkheid beschikbaar voor Jess, dus als we dat nog niet hebben gedaan, laten we de Jess-pot downloaden en uitpakken (jess.jar) en mvn installeren het naar onze lokale Maven-repository:

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

We kunnen het dan op de gebruikelijke manier als afhankelijkheid toevoegen:

 gov. sandia jess 7.1p2 

4.2. Hallo Jess-regelsbestand

Laten we vervolgens de eenvoudigste regelbestanden maken om een ​​bericht af te drukken. We slaan het regelbestand op als hallojess.clp:

(afdruk t "Hallo van Jess!" crlf)

4.3. Jess Rule Engine

Laten we nu een instantie maken van de Jess Rete regelmotor, resetten () het naar de oorspronkelijke staat, laadt u de regels in hallojess.clp, en voer ze uit:

openbare klasse HelloJess {openbare statische leegte hoofd (String [] args) gooit JessException {Rete engine = nieuwe Rete (); engine.reset (); engine.batch ("hellojess.clp"); engine.run (); }

Voor dit eenvoudige voorbeeld hebben we zojuist het potentieel toegevoegd JessException naar onze hoofd methode gooit clausule.

Wanneer we ons programma uitvoeren, zien we de uitvoer:

Hallo van Jess!

5. Jess integreren met Java met gegevens

Nu alles correct is geïnstalleerd en we regels kunnen uitvoeren, laten we eens kijken hoe we gegevens toevoegen die de rule engine kan verwerken en hoe we de resultaten ophalen.

Eerst hebben we enkele Java-klassen nodig om mee te werken, en dan een nieuwe regelset die ze gebruikt.

5.1. Model

Laten we wat eenvoudig maken Vraag en Antwoord klassen:

openbare klasse Vraag {privé String-vraag; privé int balans;  // getters en setters  openbare vraag (String-vraag, int balans) {this.question = vraag; this.balance = balans; }} public class Answer {private String antwoord; privé int nieuwBalans;  // getters en setters  openbaar antwoord (String answer, int newBalance) {this.answer = answer; this.newBalance = newBalance; }}

5.2 Jess-regel met invoer en uitvoer

Laten we nu een eenvoudige Jess-regelset maken met de naam bonus.clp dat we een Vraag naar en ontvang een Antwoord van.

Ten eerste, wij importeren onze Vraag en Antwoord klassen en gebruik dan Jess's deftemplate functie om ze beschikbaar te maken voor de rule engine:

(import com.baeldung.rules.jsr94.jess.model. *) (deftemplate-vraag (declareer (van-klasse-vraag))) (deftemplate-antwoord (declareer (van-klasse-antwoord)))

Let op het gebruik van haakjes, die Jess-functieaanroepen aanduiden.

Laten we nu gebruiken defrule om een ​​enkele regel toe te voegen voorkomen-roodstand in Jess's uitgebreide Lisp-formaat dat ons een bonus van $ 50 geeft als het saldo in ons Vraag is onder nul:

(vermijd-roodstand "Geef $ 50 aan iemand die rood staat" opheffen? q <- (Vraag {saldo (toevoegen (nieuw antwoord "Overgetrokken bonus" (+? q. saldo 50)))))

Hier de "?” bindt een object aan een variabele q wanneer de voorwaarden aan de rechterkant van de "<-“ bij elkaar passen. In dit geval vindt de rule engine een Vraag dat heeft een balans minder dan 0.

Als dit het geval is, worden de acties rechts van de "=>” worden geactiveerd zodat de motor toevoegens een nieuw antwoord bezwaar maken tegen het werkgeheugen. We geven het de twee vereiste constructorargumenten: "Overdrawn bonus" voor de antwoord parameter en een (+) functie om de newAmount parameter.

5.3. Gegevens manipuleren met de Jess Rule Engine

We kunnen gebruiken toevoegen() om één object tegelijk toe te voegen aan het werkgeheugen van onze rule engine, of Voeg alles toe() om een ​​verzameling gegevens toe te voegen. Laten we gebruiken toevoegen() om een ​​enkele vraag toe te voegen:

Vraag vraag = nieuwe vraag ("Kan ik een bonus krijgen?", -5); engine.add (gegevens);

Laten we, met al onze gegevens op hun plaats, onze regels uitvoeren:

engine.run ();

De Jess Rete engine werkt zijn magie en keert terug wanneer alle relevante regels zijn uitgevoerd. In ons geval hebben we een Antwoord inspecteren.

Laten we een jess.Filter om onze Antwoord van de rule engine naar een Herhaalbaar resultaten object:

Iterator resultaten = engine.getObjects (nieuwe jess.Filter.ByClass (Answer.class)); while (results.hasNext ()) {Answer answer = (Answer) results.next (); // verwerk ons ​​antwoord}

We hebben geen referentiegegevens in ons eenvoudige voorbeeld, maar als we dat doen, kunnen we een WorkingMemoryMarker en engine.mark () om de status van het werkgeheugen van de rule engine te markeren na het toevoegen van de gegevens. Dan kunnen we bellen motor.resetToMark met onze marker om het werkgeheugen terug te zetten naar onze "geladen" staat en de rule engine efficiënt te hergebruiken voor een andere set objecten:

WorkingMemoryMarker-markering; // load reference data marker = engine.mark (); // laad specifieke gegevens en voer regels uit engine.resetToMark (marker);

Laten we nu eens kijken hoe we dezelfde regelset uitvoeren met JSR 94.

6. JSR 94 gebruiken om de Jess Rule Engine te integreren

JSR 94 standaardiseert hoe onze code interageert met een rule engine. Dit maakt het gemakkelijker om onze rule engine te wijzigen zonder onze applicatie significant te veranderen als er een beter alternatief komt.

De JSR 94 API wordt geleverd in twee hoofdpakketten:

  • javax.rules.admin - voor het laden van chauffeurs en regels
  • javax.rules - om de regels uit te voeren en resultaten te extraheren

We zullen bekijken hoe we de klassen in beide kunnen gebruiken.

6.1. Afhankelijkheid van Maven

Laten we eerst een Maven-afhankelijkheid toevoegen voor jsr94:

 jsr94 jsr94 1.1 

6.2. Beheer-API

Om JSR 94 te kunnen gebruiken, moeten we een instantiëren RuleServiceProvider. Laten we er een maken en deze doorgeven aan onze Jess-regelsdriver:

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

Laten we nu de JSR 94 van Jess nemen Regel Beheerder, laad onze voorbeeldregelset in een JSR 94 RuleExecutionSet, en registreer het voor uitvoering met een URI naar keuze:

RuleAdministrator ruleAdministrator = serviceProvider.getRuleAdministrator (); InputStream ruleInput = JessRunner.class.getResourceAsStream (rulesFile); HashMap vendorProperties = nieuwe HashMap (); RuleExecutionSet ruleExecutionSet = ruleAdministrator .getLocalRuleExecutionSetProvider (vendorProperties) .createRuleExecutionSet (ruleInput, vendorProperties); String rulesURI = "rules: // com / baeldung / rules / bonus"; ruleAdministrator.registerRuleExecutionSet (rulesURI, ruleExecutionSet, vendorProperties);

De Jess-chauffeur heeft de vendorProperties kaart die we hebben geleverd Regel Beheerder, maar het maakt deel uit van de interface en mogelijk hebben andere leveranciers het nodig.

Nu onze rule engine-provider, Jess, is geïnitialiseerd en onze regelset is geregistreerd, zijn we bijna klaar om onze regels uit te voeren.

Voordat we ze kunnen uitvoeren, hebben we een runtime-instantie en een sessie nodig om ze uit te voeren. Laten we ook een tijdelijke aanduiding toevoegen, berekenenResultaten (), voor waar de magie zal gebeuren, en laat de sessie los:

RuleRuntime ruleRuntime = ruleServiceProvider.getRuleRuntime (); StatelessRuleSession statelessRuleSession = (StatelessRuleSession) ruleRuntime.createRuleSession (rulesURI, nieuwe HashMap (), RuleRuntime.STATELESS_SESSION_TYPE); berekenenResultaten (statelessRuleSession); statelessRuleSession.release ();

6.3. Uitvoerings-API

Nu we alles op zijn plaats hebben, gaan we implementeren berekenResultaten om onze initiële gegevens te verstrekken, onze regels uit te voeren in een staatloze sessie en de resultaten te extraheren:

Lijstgegevens = nieuwe ArrayList (); data.add (nieuwe vraag ("Kan ik een bonus krijgen?", -5)); Lijstresultaten = statelessRuleSession.executeRules (data);

Omdat JSR 94 is geschreven voordat JDK 5 uitkwam, gebruikt de API geen generieke geneesmiddelen, dus laten we gewoon een Iterator om de resultaten te zien:

Iterator itr = results.iterator (); while (itr.hasNext ()) {Object obj = itr.next (); if (obj instanceof Answer) {int answerBalance = ((Answer) obj) .getCalculatedBalance ()); }}

We hebben in ons voorbeeld een staatloze sessie gebruikt, maar we kunnen ook een StatefuleRuleSession als we de staat tussen aanroepen willen behouden.

7. Conclusie

In dit artikel hebben we geleerd hoe we de Jess-rule engine in onze applicatie kunnen integreren door de native klassen van Jess te gebruiken en, met wat meer moeite, door JSR 94 te gebruiken. We hebben gezien hoe bedrijfsregels kunnen worden gescheiden in afzonderlijke bestanden die worden verwerkt door de rule engine wanneer onze applicatie wordt uitgevoerd.

Als we regels hebben voor dezelfde bedrijfslogica, geschreven voor een andere JSR 94-compliant rule engine, dan kunnen we eenvoudig het stuurprogramma voor onze alternatieve rule engine toevoegen en de stuurprogrammanaam bijwerken die onze applicatie zou moeten gebruiken, en er zouden geen verdere codewijzigingen moeten zijn vereist.

Er zijn meer details op jess.sandia.gov voor het insluiten van Jess in een Java-applicatie, en Oracle heeft een handige gids voor Aan de slag met de Java Rule Engine API (JSR 94).

Zoals gewoonlijk is de code die we in dit artikel hebben bekeken, beschikbaar op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found