Archive

Posts Tagged ‘Rules’

Rules hot deploy using Drools / Guvnor – final

05/30/2010 5 comments

In this final part of the tutorial, I will present how to deploy rules to Guvnor.

As a web application (. War), Guvnor provides much of its functionality as Servlets. Recently, a feature to communicate via REST has been incorporated so we can create, update or delete content from the server. This API is known as REST API, and responds in the URL of / api. For example, create a package, the syntax used is as follows:

/ org.drools.guvnor.Guvnor / api / packages /<package name>. package

Similar to the package creation is the creation of rules, made as follows:

/ org.drools.guvnor.Guvnor / api / packages / <package name> /<rule name>. drl

As these invocations are done via REST, HTTP methods to these URLs are created as follows:

  • GET -> reading
  • POST -> creation
  • PUT -> update
  • DELETE -> delete

That is, assuming the previous examples, and in the case of my machine, reading the rule created previously could be done by making a GET to the URL http://localhost:8080/drools-guvnor/org. drools.guvnor.Guvnor / packages / seguradora/ admissaosegurado.drl

If the reader is in doubt as to how to make such a request, below is an example on how to create a rule using Apache Commons HTTP:

 
/**
* @param drl The rule to be created, that is, the body of the rule itself
* @param drlName The rule name
* @param packageName Guess =)
*/
public static void createDrl (String drl, String drlName, String packageName) throws HttpException, IOException {
		String uri = URL_FOR_RULES_CREATION.replace("{0}", packageName).replace("{1}", drlName);
		PostMethod post = new PostMethod(uri);
		post.setRequestBody(drl);
		sendRequest(post);
	}
private static void sendRequest (HttpMethod method, String username, String password) throws HttpException, IOException {
		HttpClient client = new HttpClient();		
		client.getState().setCredentials("users", host, new UsernamePasswordCredentials(username, password));
		method.setDoAuthentication(true);
		
		client.executeMethod(method);
		
		int statusCode = method.getStatusCode();
		String response = method.getResponseBodyAsString();
		
		if (statusCode != 200 || !response.equals("OK")) {
			throw new HttpException("Something went wrong with the invocation. Status code: " + statusCode + ". Response: " + response);
		}		
	}

However, here is a sign of a problem with this approach: even the present version of Guvnor, the build and create a package / snapshot can not be done in an automated manner using this approach (so, it prevents the immediate consumption of these rules ). I´m not sure if a can expose my solution to this problem on this blog (due to a number of restrictions). However, if I have any appeal of the community I will be happy to check these constraints and if there are no issues, I may publish it here.

How to dynamically create the rule

Rule creation can be done through a set of classes available in the package org.drools.guvnor.client.modeldriven.brl .* , available in JAR drools-compiler- . Thus the creation of a simple rule can be made as follows:

 

**
* @param rule Presumably, a POJO that contains data from the the rule to be generated.
*/
public String generateRuleData(Rule rule) {
		RuleModel model = new RuleModel();
		model.name = rule.getName();
		
		FieldConstraint constraint = evaluate(rule);
		 
		FactPattern fact = new FactPattern(NOME_DO_FATO);
		fact.boundName = VARIABLE_THAT_REPRESENTS_THE_FACT;
		fact.addConstraint(constraint);
		
		model.lhs = new IPattern[]{fact};
		model.rhs = getActions(rule);
		
		BRLPersistence persistence = BRDRLPersistence.getInstance();
		String ruleData = persistence.marshal(model);
		
		return ruleData;
	}

/**
* This method will retrieve a custom model of what will happen inside a rule´s body.
* Remeber that IAction is an interface, so, evaluate the possible implementations.
*/
protected IAction[] getActions(Rule rule) {

//In my case, the method will retrieve a representation of setting a value onto the fact.
		ActionSetField actionSetField = new ActionSetField(VARIABLE_THAT_REPRESENTS_THE_FACT);		
		
		actionSetField.fieldValues = new ActionFieldValue[] {new ActionFieldValue(
"attribute", "value", "type - String, Integer, etc.")};
		
		
		return new IAction[]{actionSetField};
	}

protected FieldConstraint evaluate (Rule rule) {
/*Must return an implementation of the interface FieldConstraint. The available implementations (so far) are the class SingleFieldConstraint and the class CompositeFieldConstraint, that represent, respectively, a single operation on a fact definition and many operations. For particular reasons, I won´t present here this method implementation, so it´s on the reader. */

return null;
}

Where:

  • FactPattern class represents the fact. In the constructor of the same, will the fact that the name will be used. In boundName attribute, you create a variable to perform the assignment.

  • In the method

  • addConstraint are added to the clauses of fact.
  • In

  • attributes rhs and lhs, class RuleModel are added, respectively, the definition of fact and the definition of the consequences.

This method will then return the representation of the rule as String. I won´t go into details here of how to accomplish the definition of fact, as unknown, until now, automated way of creating this in the body’s own rule. Also, since I went into detail about how the syntax for defining the first part of this tutorial, then left to the reader the automated generation ddo fact.

Once the generation is made, just synchronize it with the model presented in the first part of this tutorial and ready, we have the rule generation and creation in Guvnor presented.

solution analysis

Thereby closing the tutorial, step to the critical analysis of the solution (as I hope to do every time I post a tutorial here).

One of the most serious problems with this solution was the fact that you were referred from the party itself, ie the impossibility of creating a snapshot to enable the immediate consumption of the rules. This can cause major problems for those who want immediate solution to the problem (although, as already mentioned, I have the solution to this problem and hope to submit as soon as possible for both the community and for the team responsible for the Guvnor).

Another problem, too, is the creation of a sequence of rules. You can create sequences through the implementation of the rules attribute salience , that can be embedded in the body of rules, and by creating flows rule . However, both mechanisms add problems when it made an automatic creation of new rules, which ultimately makes the scheme impractical.

And finally, citing the problems I cite also the management of these rules is problematic when done by Guvnor, recommended, so some sort of maintaining the route database. This creates a different problem when the use of rules is achieved, because the consumer of the rules is optimized to work with URLs or files, or if consumption of rules is done via the database, it is necessary to create a REST API own (or at least a Servlet that responds by GET method). Moreover, the consumer rules only works with the built package, which can generate an additional problem generation.

That said, it must be noted that the control of an application via API rules is extremely powerful, because besides being a flexible mechanism (from the standpoint of the system operator) is also relatively easy to manage.

Furthermore, a mechanism is also extremely fast (in benchmarks that I made between two different machines and after the creation of consumer rules, the meter accused times between 1 and 10 msec).

Therefore, it is the burden of developers and / or the architect of an application to analyze the cost / benefit of this. Just leave here a reminder that the problems I mentioned occur in development time, and advantages occur with the application already put into production. That is, I believe that the benefits always overwhelm the problems, either from or in any other Drools Rules Engine.

Advertisements

Rules hot deploy using Drools / Guvnor – part 2

05/24/2010 7 comments

In the first part of this tutorial, I introduced the basics and the Drools Guvnor, as well as demonstrated the creation of a simple rule in Guvnor. The objective of this part is to show how to consume the rule set, as well as present as expose it as web service.

Preparing rules for consumption

To prepare the rules for consumption, it is necessary to generate a snapshot of the rules. This is done by his own administration interface Guvnor by selecting the package, performing the same build and selecting the option to create snapshot, as shown:

As a rule created to consume

The rules can be consumed by the Drools API itself, as shown in the code below:

package com.alesaudate.drools.sample.client;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.drools.RuleBase;
import org.drools.StatelessSession;
import org.drools.agent.RuleAgent;
import org.drools.definition.type.FactType;

public class Client {
private Properties config;
private String factName;
private Map factValues;
private Map expectedResultsMap;
private static Map agents = new HashMap();

public void consume () throws InstantiationException, IllegalAccessException {
RuleAgent agent = getAgent(getConfig().getProperty("url"));
RuleBase ruleBase = agent.getRuleBase();
FactType factType = ruleBase.getFactType(getFactName());
Object fact = factType.newInstance();
Map values = getFactValues();
for (String key : values.keySet()) {
factType.set(fact, key, values.get(key));
}
StatelessSession statelessSession = ruleBase.newStatelessSession();
statelessSession.execute(fact);
Map expectedResults = getExpectedResultsMap();
for (String key : expectedResults.keySet()) {
Object resultValue = factType.get(fact, key);
expectedResults.put(key, resultValue);
}
}
private RuleAgent getAgent(String url) {
if (!agents.containsKey(url)) {
RuleAgent agent = RuleAgent.newRuleAgent(getConfig());
agents.put(url, agent);
}
return agents.get(url);
}
// getters and setters…

}

Where the field config is the configuration of the API (to be explained), the field factName represents the fully qualified name of the POJO that will be used as fact (in our example, is seguradora.Segurado) factValues is a map that will be used to populate fields and the fact expectedResultsMap is a map that will be used to retrieve the desired values of the implementation of the rule (in our case, the status field is interesting).

The field config can be configured using the following data:

  • newInstance: Used to determine whether a new instance of the rule will be created (for the case of rules that keep state)
  • file: to determine which file (local) will be read
  • dir: to establish a directory for reading
  • url: URL to determine a reading (which will be used, in our case)
  • poll: interval in seconds, rereading the selected source (to determine whether the rule needs to be updated on the local machine)
  • name: name of the configuration
  • localCacheDir: directory will be cached remotely read the rule.

For the last class as an example, you can perform the reading of the rule using the following code:

 
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Client client = new Client();
		Properties config = new Properties();
		config.put("url", "http://localhost:8080/drools-guvnor/org.drools.guvnor.Guvnor/package/seguradora/LATEST");
		client.setConfig(config);
		client.setFactName("seguradora.Segurado");
		
		Map factValues = new HashMap();
		factValues.put("idade", 18);
		client.setFactValues(factValues);
		
		Map expectedResults = new HashMap();
		expectedResults.put("status", null);
		client.setExpectedResultsMap(expectedResults);
		
		
		client.consume();
		
		System.out.println(client.getExpectedResultsMap());
		
	}

Still using the example code, you can expose the rules as services for two distinct ways:

  • Creating a custom web service (the sample code is available on the downloads page, next to the sample code consumer rules)
  • Using Drools Server, placing a file. properties (similar to the properties file passed as parameter to the client) in the “WEB-INF/classes” Application of Drools Server. In this way, however, the web service will be exposed as REST.

The downloads page , is available for download the client’s consumption and exposure rule as SOAP web service.

The next part will present how to perform deploy a rule dynamically.

Rules hot deploy using Drools / Guvnor – part 1

05/18/2010 2 comments

A SOA well done should be developed along the lines of business for which the architecture is being developed. One example is an insurer, where the services may well be made for each sector of insurance offered, as well as a customer base. Thus, if the insurer will act in a new class of insurance, all she has to do is to reuse the customer service, to offer these new portfolios.

However (and still using the example of insurance companies) should be noted that the selection of new users must abide by certain rules (eg, an insured can not be less than eighteen years), it should also be noted that these rules are not always immutable (and if the insurer decides that insured below eighteen years may be accepted only in life insurance, what if, during the operation of the system, the system user decides that insured under eighteen years can only be accepted with parental consent?).

To reflect this flexibility, the architecture SOA takes the concept of Business Rules. Are rules that are usually understandable by business analysts and can be easily changed. Some engines expose those rules in the form of web services and other options to facilitate the relaxation of such. Some also facilitate hot deploy rules to allow this flexibility.

To illustrate this concept of + hot deploy rules, created this tutorial on how to develop rules from the Drools API, post them on JBoss Guvnor and eat them so performative.

Why exemplify using Drools Guvnor + (or JBoss BRMS)?

The JBoss Guvnor is a system of governance rules that open source has an extremely user-friendly management interface. Also, your engine has, so native systems that facilitate the hot deploy and manage these rules natively through Apache Jackrabbit .

Below is the print screen splash screen Guvnor:

What terms need to know when using Drools?

  • Package: logical organization to hold a collection of rules (similar to packages of Java classes).
  • Model: entity that will store the data input and output rules.
  • Fact finding that will cause a rule to run (similar to a if, in Java).
  • Rule: snippet of code that, given certain facts, it will run.
  • Snapshot: compiling the package at some point, which is what effectively will be used to generate a new snapshot (ie, is a “snapshot” of the package).

What this tutorial applies to versions

This tutorial is based on version 5.0 of Guvnor, based on JBoss AS version 4.2.3. The set is available for download here .

How do I create a rule using Drools?

Syntax (simplified) to create rules in Drools is:

 package seguradora

declare Segurado
    idade : Integer
    status : String
end


rule "menores de idade não são autorizados"
when
	seg : Segurado( idade &gt;= 18)
then
	seg.setStatus ("AUTORIZADO");
end 

In code, you can see the model “insured” who possesses the attributes age (like Integer) and status (of type String – the fact that Integer and String classes belong to the package java.lang, it is not necessary to put the fully qualified name of them). The rule, in the clause “when”, and receives an insured assigns the variable “sec”. The fact here is the excerpt:

Segurado( idade >= 18)

That is, the rule only evaluate the code in the clause then if, and only if the insured has an age attribute with a value greater than or equal to 18. If so, the words:

seg.setStatus ("AUTORIZADO");

will be evaluated. Note that here it is developed purely in Java code, or ceases to be native to the Drools.

How can I make this rule will deploy Guvnor

To accomplish deploy this rule, just follow the steps:

  • Create a new category, the Administration
  • menu Knowledge Bases , create a new package (package );
  • Still

  • Knowledge Bases , select the option to create a new rule, as the example:

  • The written text box that appears, type the text of the rule.
  • Click Validate
  • If everything is OK, click Save changes

There, the rule is set to deploy. For the implementation of the rule, however, you must perform some coding, I’ll post next post. See you there!