I've always stated that end business users struggle understanding the differences between rules and processes, and more recently rules and event processing. For them they have this problem in their mind and they just want to model it using some software. The traditional way of using two vendor offerings forces the business user to work with a process oriented or rules oriented approach which just gets in the way, often with great confusion over which tool they should be using to model which bit.
PegaSystems and Microsoft have done a great job of showing that the two can be combined and a behavioural modelling approach can be used. This allows the business user to work more naturally where the full range of approaches is available to them, without the tools getting in the way. From being process oriented to rule oriented or shades of grey in the middle - whatever suites the problem being modelled at that time.
Drools 5.0 takes this one step further by not only adding workflow with Drools Flow but also adding event processing with Drools Fusion, creating a more holistic approach to software development. Where the term holistic is used for emphasizing the importance of the whole and the interdependence of its parts. Drools 5.0 is the launch of what we call the Business Logic integration Platform (BLiP) .
Drools 5.0 is now split into 4 modules, each with their own manual - Guvnor, Expert, Fusion and Flow. Guvnor is our web based governance system, traditionally referred to in the rules world as a BRMS. We decided to move away from the BRMS term to a play on governance as it's not rules specific. Expert is the traditional rules engine. Fusion is the event processing side, it's a play on data/sensor fusion terminology. Finally there is Flow which is our workflow module.
Drools 5.0 will be the launch of what we call the Business Logic integration Platform (BLiP) - the BRMs is dead :) The future is for a unified and integrated solution for Rules, Processes and CEP - this is what users want and this is what we are aiming for. Drools 5.0 will split up into 4 main sub projects, the documentation has already been split to reflect this:
Drools Guvnor (BRMS/BPMS)
Drools Expert (rule engine),
Drools Flow (process/workflow)
Drools Fusion (cep/temporal reasoning)
Drools now has complete api/implementation separation that is no longer rules oriented. This is an important strategy as we move to support other forms of logic, such as workflow and event processing. The main change is that we are now knowledge oriented, instead of rule oriented. The module drools-api provide the interfaces and factories and we have made pains to provide much better javadocs, with lots of code snippets, than we did before. Drools-api also helps clearly show what is intended as a user api and what is just an engine api, drools-core and drools-compiler did not make this clear enough. The most common interfaces you will use are:
org.drools.builder.KnowledgeBuilder
org.drools.KnowledgeBase
org.drools.agent.KnowledgeAgent
org.drools.runtime.StatefulKnowledgeSession
org.drools.runtime.StatelessKnowledgeSession
Factory classes, with static methods, provide instances of the above interfaces. A pluggable provider approach is used to allow provider implementations to be wired up to the factories at runtime. The Factories you will most commonly used are:
org.drools.builder.KnowledgeBuilderFactory
org.drools.io.ResourceFactory
org.drools.KnowledgeBaseFactory
org.drools.agent.KnowledgeAgentFactory
Example 2.1. A Typical example to load a rule resource
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.DRL ); if ( kbuilder.hasErrors() ) { System.err.println( builder.getErrors().toString() ); } KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( builder.getKnowledgePackages() ); StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession(); ksession.insert( new Fibonacci( 10 ) ); ksession.fireAllRules(); ksession.dispose();
A Typical example to load a process resource. Notice the ResourceType
is changed, in accordance with the Resource
type:
Example 2.2. A Typical example to load a process resource. Notice the ResourceType
is changed, in accordance with the Resource
type
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.DRF ); if ( kbuilder.hasErrors() ) { System.err.println( builder.getErrors().toString() ); } KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( builder.getKnowledgePackages() ); StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession(); ksession.startProcess( "Buy Order Process" ); ksession.dispose();
'kbuilder', 'kbase', 'ksession' are the variable identifiers often used, the k prefix is for 'knowledge'.
Example 2.3. We have uniformed how decision trees are loaded, and they are now consistent with no need to pre generate the DRL with the spreadsheet compiler
DecisionTableConfiguration dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration(); dtconf.setInputType( DecisionTableInputType.XLS ); dtconf.setWorksheetName( "Tables_2" ); kbuilder.add( ResourceFactory.newUrlResource( "file://IntegrationExampleTest.xls" ), ResourceType.DTABLE, dtconf );
It is also possible to configure a KnowledgeBase
using configuration, via a xml change set, instead of programmatically.
Example 2.4. Here is a simple change set
<change-set xmlns='http://drools.org/drools-5.0/change-set' xmlns:xs='http://www.w3.org/2001/XMLSchema-instance' xs:schemaLocation='http://drools.org/drools-5.0/change-set change-set-5.0.xsd' > <add> <resource source='classpath:org/domain/someRules.drl' type='DRL' /> <resource source='classpath:org/domain/aFlow.drf' type='DRF' /> </add> </change-set>
Example 2.5. And it is added just like any other ResourceType
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.ChangeSet );
The other big change for the KnowledgeAgent
, compared to the RuleAgent
, is that polling scanner is now a service. further to this there is an abstraction between the agent notification and the resource monitoring, to allow other mechanisms to be used other than polling.
Example 2.6. These services currently are not started by default, to start them do the following
ResourceFactory.getResourceChangeNotifierService().start(); ResourceFactory.getResourceChangeScannerService().start();
There are two new interfaces added, ResourceChangeNotifier
and ResourceChangeMonitor
. KnowlegeAgents
subscribe for resource change notifications using the ResourceChangeNotifier
implementation. The ResourceChangeNotifier
is informed of resource changes by the added ResourceChangeMonitors
. We currently only provide one out of the box monitor, ResourceChangeScannerService
, which polls resources for changes. However the api is there for users to add their own monitors, and thus use a push based monitor such as JMS.
ResourceFactory.getResourceChangeNotifierService().addResourceChangeMonitor( myJmsMonitor);
New look web tooling
Web based decision table editor
Integrated scenario testing
WebDAV file based interface to repository
Declarative modelling of types (types that are not in pojos)
This works with the new "declare" statement - you can now declare types in drl itself. You can then populate these without using a pojo (if you like). These types are then available in the rulebase.
Fine grained security (lock down access to the app per package or per category). Users who only have category permissions have limited UI capability (ideal for business users)
Execution server - access rules via XML or JSON for execution
Category rules allows you to set 'parent rules' for a category. Any rules appearing in the given category will 'extend' the rule specified - ie inherit the conditions/LHS. The base rule for the category can be set on package configuration tab. RHS is not inherited, only the LHS
Scenario runner detects infinite loops
Scenario runner can show event trace that was recorded by audit logger
DSL sentences in guided editor can now be set to show enums as a dropdown, dates as a date picker, booleans as a checkbox and use regular expressions to validate the inputs (DSL Widgets in Guvnor)
Functions can be edited with text editor
It is possible to add objects to global collections.
Translations to English, Spanish, Chinese and Japanese
Shadow proxies are no longer needed. Shadow proxies protected the engine from information change on facts, which if occurred outside of the engine's control it could not be modified or retracted.
You no longer need to confine one PackageBuilder
to one package namespace. Just keeping adding your DRLs for any namespace and getPackages()
returns an array of Packages for each of the used namespaces.
It is now possible to attach a RuleBase
to a PackageBuilder
, this means that rules are built and added to the rulebase at the same time. PackageBuilder
uses the Package
instances of the actual RuleBase
as it's source, removing the need for additional Package
creation and merging that happens in the existing approach.
Example 2.8. Attaching RuleBase
to PackageBuilder
RuleBase ruleBase = RuleBaseFactory.newRuleBase(); PackageBuilder pkgBuilder = new PackageBuilder( ruleBase, null );
Stateful sessions can now saved and resumed at a later date. Pre-loaded data sessions can now be created. Pluggable strategies can be used for user object persistence, i.e. hibernate or identity maps.
Drools now supports a new base construct called Type Declaration. This construct fulfils two purposes: the ability to declare fact metadata, and the ability to dynamically generate new fact types local to the rule engine. The Guvnor modelling tool uses this underneath. One example of the construct is:
Example 2.9. Declaring StockTick
declare StockTick @role( event ) @timestamp( timestampAttr ) companySymbol : String stockPrice : double timestampAttr : long end
To declare and associate fact metadata, just use the @ symbol for each metadata ID you want to declare. Example:
To activate the dynamic bean generation, just add fields and types to your type declaration:
A series of DSL improvements were implemented, including a completely new parser and the ability to declare matching masks for matching variables. For instance, one can constrain a phone number field to a 2-digit country code + 3-digit area code + 8-digit phone number, all connected by a "-" (dash), by declaring the DSL map like: The phone number is {number:\d{2}-\d{3}-\d{8}} Any valid java regexp may be used in the variable mask.
Drools now supports "fireUntilHalt()" feature, that starts the engine in a reactive mode, where rules will be continually fired, until a halt() call is made. This is specially useful for CEP scenarios that require what is commonly known as "active queries".
Drools ReteOO algorithm now supports an option to start the rule base in a multi-thread mode, where Drools ReteOO network is split into multiple partitions and rules are then evaluated concurrently by multiple threads. This is also a requirement for CEP where there usually are several independent rules running concurrently, with near realtime performance/throughput requirements and the evaluation of one can not interfere with the evaluation of others.
Drools now supports XSD models. Remember though the XSD model is generated as pojos local to the Drools classloader. A helper class is there to assist in the creation of the model in the packagebuilder. Once the data model is generated you'll typically use the JAXB dataloader to insert data.
Drools now supports two data loaders, Smooks and JAXB. Smooks is an open source data transformation tool for ETL and JAXB a standard sun data mapping tool. Unit tests showing Smooks can be found here and JAXB here.
In addition to the ability of configuring options in drools through configuration files, system properties and by setting properties through the API setProperty()
method, Drools-API now supports type safe configuration.
We didn't want to add specific methods for each possible configuration methods for two reasons: it polutes the API and every time a new option is added to Drools, the API would have to change. This way, we followed a modular, class based configuration, where a new Option class is added to the API for each possible configuration, keeping the API stable, but flexible at the same time.
So, in order to set configuration options now, you just need to use the enumerations or factories provided for each option. For instance, if you want to configure the knowledge base for assert behavior "equality" and to automatically remove identities from pattern matchings, you would just use the enums:
Example 2.12. Configuring
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); config.setOption( AssertBehaviorOption.EQUALITY ); config.setOption( RemoveIdentitiesOption.YES );
For options that don't have a predefined constant or can assume multiple values, a factory method is provided. For instance, to configure the alpha threshold to 5, just use the "get" factory method:
As you can see, the same setOption()
method is used for the different possible configurations, but they are still type safe.
There are times when it is necessary to collect sets or lists of values that are derived from the facts attributes, but are not facts themselves. In such cases, it was not possible to use the collect CE. So, Drools now has two accumulate functions for such cases: collectSet for collecting sets of values (i.e., with no duplicate values) and collectList for collecting lists of values (i.e., allowing duplicate values):
Example 2.14. New accumulate functions
# collect the set of unique names in the working memory $names : Set() from accumulate( Person( $n : name, $s : surname ), collectSet( $n + " " + $s ) ) # collect the list of alarm codes from the alarms in the working memory $codes : List() from accumulate( Alarm( $c : code, $s : severity ), collectList( $c + $s ) )
Facts that implement support for property changes as defined in the Javabean(tm) spec, now can be annotated so that the engine register itself to listen for changes on fact properties. The boolean parameter that was used in the insert() method in the Drools 4 API is deprecated and does not exist in the drools-api module.
Batch Executor allows for the scripting of of a Knowledge session using Commands, which can also re, both the StatelessKnowledgeSession
and StatefulKnowledgeSession
implement this interface
Commands are created using the CommandFactory
and executed using the "execute" method, such as the following insert Command:
Typically though you will want to execute a batch of commands, this can be achieved via the composite Command BatchExecution
. BatchExecutionResults
is now used to handle the results, some commands can specify "out" identifiers which it used to add the result to the BatchExecutionResult
. Handily querries can now be executed and results added to the BatchExecutionResult
. Further to this results are scoped to this execute call and return via the BatchExecutionResults
:
Example 2.17. Using BatchExecutionResult
List<Command> cmds = new ArrayList<Command>(); cmds.add( CommandFactory.newSetGlobal( "list1", new ArrayList(), true ) ); cmds.add( CommandFactory.newInsert( new Person( "jon", 102 ), "person" ) ); cmds.add( CommandFactory.newQuery( "Get People" "getPeople" ); BatchExecutionResults results = ksession.execute( CommandFactory.newBatchExecution( cmds ) ); results.getValue( "list1" ); // returns the ArrayList results.getValue( "person" ); // returns the inserted fact Person results.getValue( "Get People" );// returns the query as a QueryResults instance. end
The CommandFactory
details the supported commands, all of which can marshalled using XStream and the BatchExecutionHelper
. This can be combined with the pipeline to automate the scripting of a session.
Example 2.18. Using PipelineFactory
Action executeResultHandler = PipelineFactory.newExecuteResultHandler(); Action assignResult = PipelineFactory.newAssignObjectAsResult(); assignResult.setReceiver( executeResultHandler ); Transformer outTransformer = PipelineFactory.newXStreamToXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() ); outTransformer.setReceiver( assignResult ); KnowledgeRuntimeCommand batchExecution = PipelineFactory.newBatchExecutor(); batchExecution.setReceiver( outTransformer ); Transformer inTransformer = PipelineFactory.newXStreamFromXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() ); inTransformer.setReceiver( batchExecution ); Pipeline pipeline = PipelineFactory.newStatelessKnowledgeSessionPipeline( ksession ); pipeline.setReceiver( inTransformer );
Using the above for a rulset that updates the price of a Cheese fact, given the following xml to insert a Cheese instance using an out-identifier:
Example 2.19. Updating Cheese fact
<batch-execution> <insert out-identifier='outStilton'> <org.drools.Cheese> <type>stilton</type> <price>25</price> <oldPrice>0</oldPrice> </org.drools.Cheese> </insert> </batch-execution>
We then get the following BatchExecutionResults
:
Example 2.20. Updating Cheese fact
<batch-execution-results> <result identifier='outStilton'> <org.drools.Cheese> <type>stilton</type> <oldPrice>0</oldPrice> <price>30</price> </org.drools.Cheese> </result> </batch-execution-results>
The MarshallerFactory
is used to marshal and unmarshal StatefulKnowledgeSessions
. At the simplest it can be used as follows:
Example 2.21. Using MarshallerFactory
// ksession is the StatefulKnowledgeSession // kbase is the KnowledgeBase ByteArrayOutputStream baos = new ByteArrayOutputStream(); Marshaller marshaller = MarshallerFactory.newMarshaller( kbase ); marshaller.marshall( baos, ksession ); baos.close();
However with marshalling you need more flexibility when dealing with referenced user data. To achieve this we have the ObjectMarshallingStrategy
interface. Two implementations are provided, but the user can implement their own. The two supplied are IdentityMarshallingStrategy
and SerializeMarshallingStrategy
. SerializeMarshallingStrategy
is the default, as used in the example above and it just calls the Serializable
or Externalizable
methods on a user instance. IdentityMarshallingStrategy
instead creates an int id for each user object and stores them in a Map
the id is written to the stream. When unmarshalling it simply looks to the IdentityMarshallingStrategy
map to retrieve the instance. This means that if you use the IdentityMarshallingStrategy
it's stateful for the life of the Marshaller instance and will create ids and keep references to all objects that it attempts to marshal.
Example 2.22. Code to use a IdentityMarshallingStrategy
ByteArrayOutputStream baos = new ByteArrayOutputStream(); Marshaller marshaller = MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[] { MarshallerFactory.newIdentityMarshallingStrategy() } ); marshaller.marshall( baos, ksession ); baos.close();
For added flexability we can't assume that a single strategy is suitable for this we have added the ObjectMarshallingStrategyAcceptor
interface that each ObjectMarshallingStrategy
has. The Marshaller has a chain of strategies and when it attempts to read or write a user object it iterates the strategies asking if they accept responsability for marshalling the user object. One one implementation is provided the ClassFilterAcceptor
. This allows strings and wild cards to be used to match class names. The default is "*.*", so in the above the IdentityMarshallingStrategy
is used which has a default "*.*" acceptor.
But lets say we want to serialise all classes except for one given package, where we will use identity lookup, we could do the following:
Example 2.23. Using identity lookup
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectMarshallingStrategyAcceptor identityAceceptor = MarshallerFactory.newClassFilterAcceptor( new String[] { "org.domain.pkg1.*" } ); ObjectMarshallingStrategy identityStratetgy = MarshallerFactory.newIdentityMarshallingStrategy( identityAceceptor ); Marshaller marshaller = MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[] { identityStratetgy, MarshallerFactory.newSerializeMarshallingStrategy() } ); marshaller.marshall( baos, ksession ); baos.close();
The KnowlegeAgent
is created by the KnowlegeAgentFactory
. The KnowlegeAgent
provides automatic loading, caching and re-loading, of resources and is configured from a properties files. The KnowledgeAgent
can update or rebuild this KnowlegeBase
as the resources it uses are changed. The strategy for this is determined by the configuration given to the factory, but it is typically pull based using regular polling. We hope to add push based updates and rebuilds in future versions.
The Following example constructs an agent that will build a new KnowledgeBase
from the files specified in the path String. It will poll those files every 30 seconds to see if they are updated. If new files are found it will construct a new KnowledgeBase, instead of updating the existing one, due to the "newInstance" set to "true" (however currently only the value of "true" is supported and is hard coded into the engine):
Example 2.24. Constructing an agent
// Set the interval on the ResourceChangeScannerService if you are to use it and default of 60s is not desirable. ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration(); sconf.setProperty( "drools.resource.scanner.interval", "30" ); // set the disk scanning interval to 30s, default is 60s ResourceFactory.getResourceChangeScannerService().configure( sconf ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration(); aconf.setProperty( "drools.agent.scanDirectories", "true" ); // we want to scan directories, not just files, turning this on turns on file scanning aconf.setProperty( "drools.agent.newInstance", "true" ); // resource changes results in a new instance of the KnowledgeBase being built, // this cannot currently be set to false for incremental building KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "test agent", // the name of the agent kbase, // the KnowledgeBase to use, the Agent will also monitor any exist knowledge definitions aconf ); kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) ); // resource to the change-set xml for the resources to add
KnowledgeAgents
can take a empty KnowledgeBase
or a populated one. If a populated KnowledgeBase
is provided, the KnowledgeAgent
will iterate KnowledgeBase
and subscribe to the Resource
that it finds. While it is possible for the KnowledgeBuilder
to build all resources found in a directory, that information is lost by the KnowledgeBuilder so those directories will not be continuously scanned. Only directories specified as part of the applyChangeSet(Resource)
method are monitored.
Drools 4.0 had simple "RuleFlow" which was for orchestrating rules. Drools 5.0 introduces a powerful (extensible) workflow engine. It allows users to specify their business logic using both rules and processes (where powerful interaction between processes and rules is possible) and offers a unified enviroment.
Timers:
A timer node can be added which causes the execution of the node to wait for a specific period. Currently just uses JDK defaults of initial delay and repeat delay, more complex timers will be available in further milestones.
Human Task:
Processes can include tasks that need to be executed by human actors. Human tasks include parameters like taskname, priority, description, actorId, etc. The process engine can easily be integrated with existing human task component (like for example a WS-HumanTask implementation) using our pluggable work items (see below). Swimlanes and assignment rules are also supported.
The palette in the screenshot shows the two new components, and the workflow itself shows the human task in use. It also shows two "work items" which is explained in the next section:
Domain Specific Work Items are pluggable nodes that users create to facilitate custom task execution. They provide an api to specify a new icon in the palette and gui editor for the tasks properties, if no editor gui is supplied then it defaults to a text based key value pair form. The api then allows execution behaviour for these work items to be specified. By default the Email and Log work items are provided. The Drools flow Manual has been updated on how to implement these.
The below image shows three different work items in use in a workflow, "Blood Pressure", "BP Medication", "Notify GP":
This one ows a new "Notification" work item:
Drools 4.0 used Xstream to store it's content, which was not easily human writeable. Drools 5.0 introduced the ePDL which is a XML specific to our process language, it also allows for domain specific extensions which has been talked about in detail in this blog posting "Drools Extensible Process Definition Language (ePDL) and the Semantic Module Framework (SMF)". An example of the XML language, with a DSL extension in red, is shown below.
Example 2.25. Example of the XML language
<process name="process name" id="process name" package-name="org.domain" xmlns="http://drools.org/drools-4.0/process" xmlns:mydsl="http://domain/org/mydsl" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://drools.org/drools-4.0/process drools-processes-4.0.xsd" > <nodes> <start id="0" /> <action id="1" dialect="java"> list.add( "action node was here" ); </action> <mydsl:logger id="2" type="warn"> This is my message <mydsl:logger> <end id="3" /> </nodes> <connections> <connection from="0 to="1" /> <connection from="1" to="2" /> <connection from="2" to="3" /> </connections> </process>
The underlying nodes for the framework are completely pluggable making it simple to extend and to implement other execution models. We already have a partial implementation for OSWorkflow and are working with Deigo to complete this to provide a migration path for OSWorkflow users. Other enhancements include exception scopes, the ability to include on-entry and on-exit actions on various node types, integration with our binary persistence mechanism to persist the state of long running processes, etc. Check out the Drools Flow documentation to learn more.
Human task management is very important in the context of processes. While we allow users to plug in any task component they prefer, we have developed a human task management component that supports the entire life cycle of human tasks based on the WS-HumanTask specification.
Event nodes that allow a process to respond to external events
Exception handlers and exception handler scopes to handle exceptions that could be thrown
A ForEach node allows instantiating a section of your flow multiple times, for each element in a collection
Data type support has been extended
Timers are integrated with common node types
As a result, new node types and properties have been added to the Drools Flow editor in Eclipse. You can also find examples of these new features in the integration tests (e.g. ProcessExceptionHandlerTest, ProcessTimerTest, etc.).
Our pluggable work item approach allows you to plug in domain-specific work in your process in a declarative manner. We plan to build a library of common work items and already provide an implementation for sending emails, finding files, archiving, executing system commands, logging and human tasks.
Improved support for persistence (JPA) and transactions (JTA).
Example 2.26. An example on how to use persistence and transactions in combination with processes
// create a new JPA-based session and specify the JPA entity manager factory Environment env = KnowledgeBaseFactory.newEnvironment(); env.set( EnvironmentName.ENTITY_MANAGER_FACTORY, Persistence.createEntityManagerFactory( "emf-name" ) ); env.set( EnvironmentName.TRANSACTION_MANAGER, TransactionManagerServices.getTransactionManager() ); StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, null, env ); // KnowledgeSessionConfiguration may be null, and a default will be used int sessionId = ksession.getId(); // if no transaction boundary is specified, the method invocation is executed in a new transaction automatically ProcessInstance processInstance = ksession.startProcess( "org.drools.test.TestProcess" ); // the users can also specify the transaction boundary themselves UserTransaction ut = (UserTransaction) new InitialContext().lookup( "java:comp/UserTransaction" ); ut.begin(); ksession.insert( new Person( "John Doe" ) ); ksession.startProcess( "org.drools.test.TestProcess" ); ksession.fireAllRules(); ut.commit();
Support direct access to process variables in both MVEL and Java in code constraints and actions, so if you have a variable called "person" in your process, you can now describe constraints like:
Example 2.27. Variable injection example
* [Java code constraint] return person.getAge() > 20; * [MVEL action] System.out.println(person.name);
Process instances can now listen for external events by marking the event node property "external" as true. External events are signaled to the engine using session.signalEvent(type, eventData)
More information on how to use events inside your processes can be found in the Drools Flow documentation here: https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/docs/drools-flow/html/ch03.html#d0e917
Process instances are now safe for multi-threading (as multiple thread are blocked from working on the same process instance)
Process persistence / transaction support has been further improved. Check out the drools-process/drools-process-enterprise project for more information.
The human task component has been extended to support all kinds of data for input / output / exceptions during task execution.
Example 2.28. As a result, the life cycle methods of the task client have been extended to allow content data
taskClient.addTask(task, contentData, responseHandler) taskClient.complete(taskId, userId, outputData,responseHandler) taskFail.complete(taskId, userId, outputData,responseHandler) long contentId = task.getTaskData().getDocumentContentId(); taskClient.getContent(contentId, responseHandler); ContentData content = responseHandler.getContent();
It is now possible to migrate old Drools4 RuleFlows (using the xstream format) to Drools5 processes (using readable xml) during compilation. Migration will automatically be performed when adding the RuleFlow to the KnowledgeBase when the following system property is set:
drools.ruleflow.port = true
The "Transform" work item allows you to easily transform data from one format to another inside processes. The code and an example can be found in the drools-process/drools-workitems directory.
Function imports are now also supported inside processes.
The history log - that keeps the history of all executed process instances in a database - has been extended so it is now caable of storing more detailed information for one specfic process instance. It is now possible to find out exactly which nodes were triggered during the execution of the process instance.
A new type of join has been added, one that will wait until n of its m incoming connections have been completed. This n could either be hardcoded in the process or based on the value of a variable in the process.
Improvements have been made to make persistence easier to configure. The persistence approach is based on a command service that makes sure that all the client invocations are executed inside a transaction and that the state is stored in the database after successful execution of the command. While this was already possible in M4 using the commands directly, we have extended this so that people can simply use the normal StatefulKnowledgeSession interface but simply can configure the persistence using configuration files. For more details, check out the chapter on persistence in the Drools Flow documentation.
Drools 5.0 brings to the rules world the full power of events processing by supporting a number of CEP features as well as supporting events as first class citizens in the rules engine.
Events are (from a rules engine perspective) a special type of fact that has a few special characteristics:
they are immutable
they have strong time-related relationships
they may have clear lifecycle windows
they may be transparently garbage collected after it's lifecycle window expires
they may be time-constrained
they may be included in sliding windows for reasoning
Any fact type can assume an event role, and its corresponding event semantics, by simply declaring the metadata for it.
Example 2.29. Both existing and generated beans support event semantics:
# existing bean assuming an event role import org.drools.test.StockTick declare StockTick @role( event ) end # generated bean assuming an event role declare Alarm @role( event ) type : String timestamp : long end
A new key "from entry-point" has been added to allow a pattern in a rule to listen on a stream, which avoids the overhead of having to insert the object into the working memory where it is potentially reasoned over by all rules.
$st : StockTick( company == "ACME", price > 10 ) from entry-point "stock stream"
Example 2.30. To insert facts into an entry point
WorkingMemoryEntryPoint entry = wm.getWorkingMemoryEntryPoint( "stock stream" ); entry.insert( ticker );
StreamTest shows a unit for this.
Event correlation and time based constraint support are requirements of event processing, and are completely supported by Drools 5.0. The new, out of the box, time constraint operators can be seen in these test case rules: test_CEP_TimeRelationalOperators.drl
As seen in the test above, Drools supports both: primitive events, that are point in time occurrences with no duration, and compound events, that are events with distinct start and end timestamps.
The complete list of operators are:
coincides
before
after
meets
metby
overlaps
overlappedby
during
includes
starts
startedby
finishes
finishedby
Drools 5.0 adds support for reasoning over sliding windows of events. For instance:
StockTick( symbol == "RHAT" ) over window:time( 60 )
The above example will only pattern match the RHAT stock ticks that happened in the last 60 clock ticks, discarding any event older than that.
Enabling full event processing capabilities requires the ability to configure and interact with a session clock. Drools adds support for time reasoning and session clock configuration, allowing it to not only run real time event processing but also simulations, what-if scenarios and post-processing audit by replaying a scenario.
Example 2.31. The Clock is specified as part of the SessionConfiguration, a new class that is optionally specified at session creation time
SessionConfiguration conf = new SessionConfiguration(); conf.setClockType( ClockType.PSEUDO_CLOCK ); StatefulSession session = ruleBase.newStatefulSession( conf );
Since events usually have strong temporal relationships, it is possible to infer a logical time window when events can possibly match. The engine uses that capability to calculate when an event is no longer capable of matching any rule anymore and automatically retracts that event.
Drools adopted a simplified syntax for time units, based on the ISO 8601 syntax for durations. This allows users to easily add temporal constraints to the rules writing time in well known units. Example:
SomeEvent( this after[1m,1h30m] $anotherEvent )
The above pattern will match if SomeEvent happens between 1 minute (1m) and 1 hour and 30 minutes after $anotherEvent
.
added the ability to define a per-type event expiration policy. In the example bellow, the StockTick events will expire 10 minutes after they enter the system:
declare StockTick @role( event ) @expires( 10m ) end
Support multiple runtimes: The IDE now supports multiple runtimes. A Drools runtime is a collection of jars on your file system that represent one specific release of the Drools project jars. To create a runtime, you must either point the IDE to the release of your choice, or you can simply create a new runtime on your file system from the jars included in the Drools Eclipse plugin. Drools runtimes can be configured by opening up the Eclipse preferences and selecting the Drools -> Installed Drools Runtimes category, as shown below.
Debugging of rules using the MVEL dialect has been fixed
Drools Flow Editor
Process Skins allow you to define how the different RuleFlow nodes are visualized. We now support two skins: the default one which existed before and a BPMN skin that visualizes the nodes using a BPMN-like representation: http://blog.athico.com/2008/10/drools-flow-and-bpmn.html
An (X)OR split now shows the name of the constraint as the connection label
Custom work item editors now signal the process correctly that it has been changed
Drools 4.0 is a major update over the previous Drools 3.0.x series. A whole new set of features were developed which special focus on language expressiveness, engine performance and tools availability. The following is a list of the most interesting changes.
New Conditional Elements: from, collect, accumulate and forall
New Field Constraint operators: not matches, not contains, in, not in, memberOf, not memberOf
New Implicit Self Reference field: this
Full support for Conditional Elements nesting, for First Order Logic completeness.
Support for multi-restrictions and constraint connectives && and ||
Parser improvements to remove previous language limitations, like character escaping and keyword conflicts
Support for pluggable dialects and full support for MVEL scripting language
Complete rewrite of DSL engine, allowing for full l10n
Fact attributes auto-vivification for return value restrictions and inline-eval constraints
Support for nested accessors, property navigation and simplified collection, arrays and maps syntax
Improved support for XML rules
Native support for primitive types, avoiding constant autoboxing
Support for transparent optional Shadow Facts
Rete Network performance improvements for complex rules
Support for Rule-Flows
Support for Stateful and Stateless working memories (rule engine sessions)
Support for Asynchronous Working Memory actions
Rules Engine Agent for hot deployment and BRMS integration
Dynamic salience for rules conflict resolution
Support for Parameterized Queries
Support for halt command
Support for sequential execution mode
Support for pluggable global variable resolver
Support for rule break-points on debugging
WYSIWYG support for rule-flows
New guided editor for rules authoring
Upgrade to support all new engine features
New BRMS tool
User friendly web interface with nice WEB 2.0 ajax features
Package configuration
Rule Authoring easy to edit rules both with guided editor ( drop-down menus ) and text editor
Package compilation and deployment
Easy deployment with Rule Agent
Easy to organize with categories and search assets
Versioning enabled, you can easily replace yours assets with previously saved
JCR compliant rule assets repository
As mentioned before Drools 4.0 is a major update over the previous Drools 3.0.x series. Unfortunately, in order to achieve the goals set for this release, some backward compatibility issues were introduced, as discussed in the mail list and blogs.
This section of the manual is a work in progress and will document a simple how-to on upgrading from Drools 3.0.x to Drools 4.0.x.
There are a few API changes that are visible to regular users and need to be fixed.
Drools 3.0.x had only one working memory type that worked like a stateful working memory. Drools 4.0.x introduces separate APIs for Stateful and Stateless working memories that are called now Rule Sessions. In Drools 3.0.x, the code to create a working memory was:
In Drools 4.0.x it must be changed to:
Example 2.34. Drools 4.0.x: Stateful Rule Session Creation
StatefulSession wm = rulebase.newStatefulSession();
The StatefulSession object has the same behavior as the
Drools 3.0.x WorkingMemory (it even extends the WorkingMemory
interface), so there should be no other problems with this fix.
Drools 4.0.x now supports pluggable dialects and has built-in support for Java and MVEL scripting language. In order to avoid keyword conflicts, the working memory actions were renamed as showed bellow:
Table 2.1. Working Memory Actions equivalent API methods
Drools 3.0.x | Drools 4.0.x |
WorkingMemory.assertObject() | WorkingMemory.insert() |
WorkingMemory.assertLogicalObject() | WorkingMemory.insertLogical() |
WorkingMemory.modifyObject() | WorkingMemory.update() |
The DRL Rule Language also has some backward incompatible changes as detailed bellow.
The Working Memory actions in rule consequences were also changed in a similar way to the change made in the API. The following table summarizes the change:
Table 2.2. Working Memory Actions equivalent DRL commands
Drools 3.0.x | Drools 4.0.x |
assert() | insert() |
assertLogical() | insertLogical() |
modify() | update() |
Drools 3.0.x did not had native support for primitive types and consequently, it auto-boxed all primitives in it's respective wrapper classes. That way, any use of a boxed variable binding required a manual unbox.
Drools 4.0.x has full support for primitive types and does not wrap values anymore. So, all previous unwrap method calls must be removed from the DRL.
Example 2.35. Drools 3.0.x manual unwrap
rule "Primitive int manual unbox"
when
$c : Cheese( $price : price )
then
$c.setPrice( $price.intValue() * 2 )
end
The above rule in 4.0.x would be:
Example 2.36. Drools 4.0.x primitive support
rule "Primitive support" when $c : Cheese( $price : price ) then $c.setPrice( $price * 2 ) end
The Drools Update tools is a simple program to help with the upgrade of DRL files from Drools 3.0.x to Drools 4.0.x.
At this point, its main objective is to upgrade the memory action calls from 3.0.x to 4.0.x, but expect it to grow over the next few weeks covering additional scenarios. It is important to note that it does not make a dumb text search and replace in rules file, but it actually parses the rules file and try to make sure it is not doing anything unexpected, and as so, it is a safe tool to use for upgrade large sets of rule files.
The Drools update tool can be found as a maven project in the following source repository http://anonsvn.labs.jboss.com/labs/jbossrules/trunk/experimental/drools-update/ you just need to check it out, and execute the maven clean install action with the project's pom.xml file. After resolve all the class path dependencies you are able to run the toll with the following command:
java -cp $CLASSPATH org.drools.tools.update.UpdateTool -f <filemask> [-d <basedir>] [-s <sufix>]
The program parameters are very easy to understand as following.
-h,--help, Shows a very simple list the usage help
-d your source base directory
-f pattern for the files to be updated. The format is the same as used by ANT: * = single file, directory ** = any level of subdirectories EXAMPLE: src/main/resources/**/*.drl = matches all DRL files inside any subdirectory of /src/main/resources
-s,--sufix the sufix to be added to all updated files
It is important to note that the DSL template engine was rewritten from scratch to improve flexibility. One of the new features of DSL grammars is the support to Regular Expressions. This way, now you can write your mappings using regexp to have additional flexibility, as explained in the DSL chapter. Although, now you have to escape characters with regexp meaning. Example: if previously you had a matching like:
Now, you need to escape '[' and ']' characters, as they have special meaning in regexps. So, the same mapping in Drools 4.0 would be:
Example 2.38. Drools 4.0.x mapping with escaped characters
[when][]- the {attr} is in \[ {values} \]={attr} in ( {values} )
Drools provides an Eclipse-based IDE (which is optional), but at its core only Java 1.5 (Java SE) is required.
A simple way to get started is to download and install the Eclipse plug-in - this will also require the Eclipse GEF framework to be installed (see below, if you don't have it installed already). This will provide you with all the dependencies you need to get going: you can simply create a new rule project and everything will be done for you. Refer to the chapter on the Rule Workbench and IDE for detailed instructions on this. Installing the Eclipse plug-in is generally as simple as unzipping a file into your Eclipse plug-in directory.
Use of the Eclipse plug-in is not required. Rule files are just textual input (or spreadsheets as the case may be) and the IDE (also known as the Rule Workbench) is just a convenience. People have integrated the rule engine in many ways, there is no "one size fits all".
Alternatively, you can download the binary distribution, and include the relevant jars in your projects classpath.
Drools is broken down into a few modules, some are required during rule development/compiling, and some are required at runtime. In many cases, people will simply want to include all the dependencies at runtime, and this is fine. It allows you to have the most flexibility. However, some may prefer to have their "runtime" stripped down to the bare minimum, as they will be deploying rules in binary form - this is also possible. The core runtime engine can be quite compact, and only require a few 100 kilobytes across 2 jar files.
The following is a description of the important libraries that make up JBoss Rules
drools-api.jar - this provides the interfaces and factories. Drools-api also helps clearly show what is intended as a user api and what is just an engine api.
drools-core.jar - this is the core engine, runtime component. Contains both the RETE engine and the LEAPS engine. This is the only runtime dependency if you are pre-compiling rules (and deploying via Package or RuleBase objects).
drools-compiler.jar - this contains the compiler/builder components to take rule source, and build executable rule bases. This is often a runtime dependency of your application, but it need not be if you are pre-compiling your rules. This depends on drools-core
drools-jsr94.jar - this is the JSR-94 compliant implementation, this is essentially a layer over the drools-compiler component. Note that due to the nature of the JSR-94 specification, not all features are easily exposed via this interface. In some cases, it will be easier to go direct to the Drools API, but in some environments the JSR-94 is mandated.
drools-decisiontables.jar - this is the decision tables 'compiler' component, which uses the drools-compiler component. This supports both excel and CSV input formats.
There are quite a few other dependencies which the above components require, most of which are for the drools-compiler, drools-jsr94 or drools-decisiontables module. Some key ones to note are "POI" which provides the spreadsheet parsing ability, and "antlr" which provides the parsing for the rule language itself.
NOTE: if you are using Drools in J2EE or servlet containers and you come across classpath issues with "JDT", then you can switch to the janino compiler. Set the system property "drools.compiler": For example: -Ddrools.compiler=JANINO.
For up to date info on dependencies in a release, consult the README_DEPENDENCIES.txt file, which can be found in the lib directory of the download bundle, or in the root of the project directory.
The "runtime" requirements mentioned here are if you are deploying rules as their binary form (either as KnowledgePackage objects, or KnowledgeBase objects etc). This is an optional feature that allows you to keep your runtime very light. You may use drools-compiler to produce rule packages "out of process", and then deploy them to a runtime system. This runtime system only requires drools-core.jar and drools-api for execution. This is an optional deployment pattern, and many people do not need to "trim" their application this much, but it is an ideal option for certain environments.
The rule workbench (for Eclipse) requires that you have Eclipse 3.4 or greater, as well as Eclipse GEF 3.4 or greater. You can install it either by downloading the plug-in or, or using the update site.
Another option is to use the JBoss IDE, which comes with all the plug-in requirements pre packaged, as well as a choice of other tools separate to rules. You can choose just to install rules from the "bundle" that JBoss IDE ships with.
GEF is the Eclipse Graphical Editing Framework, which is used for graph viewing components in the plug-in.
If you don't have GEF installed, you can install it using the built in update mechanism (or downloading GEF from the Eclipse.org website not recommended). JBoss IDE has GEF already, as do many other "distributions" of Eclipse, so this step may be redundant for some people.
Open the Help->Software updates...->Available Software->Add Site... from the help menu. Location is:
http://download.eclipse.org/tools/gef/updates/releases/
Next you choose the GEF plug-in:
Press next, and agree to install the plug-in (an Eclipse restart may be required). Once this is completed, then you can continue on installing the rules plug-in.
To install from the zip file, download and unzip the file. Inside the zip you will see a plug-in directory, and the plug-in jar itself. You place the plug-in jar into your Eclipse applications plug-in directory, and restart Eclipse.
Download the Drools Eclipse IDE plugin from the link below. Unzip the downloaded file in your main eclipse folder (do not just copy the file there, extract it so that the feature and plugin jars end up in the features and plugin directory of eclipse) and (re)start Eclipse.
http://www.jboss.org/drools/downloads.html
To check that the installation was successful, try opening the Drools perspective: Click the 'Open Perspective' button in the top right corner of your Eclipse window, select 'Other...' and pick the Drools perspective. If you cannot find the Drools perspective as one of the possible perspectives, the installation probably was unsuccessful. Check whether you executed each of the required steps correctly: Do you have the right version of Eclipse (3.4.x)? Do you have Eclipse GEF installed (check whether the org.eclipse.gef_3.4.*.jar exists in the plugins directory in your eclipse root folder)? Did you extract the Drools Eclipse plugin correctly (check whether the org.drools.eclipse_*.jar exists in the plugins directory in your eclipse root folder)? If you cannot find the problem, try contacting us (e.g. on irc or on the user mailing list), more info can be found no our homepage here:
A Drools runtime is a collection of jars on your file system that represent one specific release of the Drools project jars. To create a runtime, you must point the IDE to the release of your choice. If you want to create a new runtime based on the latest Drools project jars included in the plugin itself, you can also easily do that. You are required to specify a default Drools runtime for your Eclipse workspace, but each individual project can override the default and select the appropriate runtime for that project specifically.
You are required to define one or more Drools runtimes using the Eclipse preferences view. To open up your preferences, in the menu Window select the Preferences menu item. A new preferences dialog should show all your preferences. On the left side of this dialog, under the Drools category, select "Installed Drools runtimes". The panel on the right should then show the currently defined Drools runtimes. If you have not yet defined any runtimes, it should like something like the figure below.
To define a new Drools runtime, click on the add button. A dialog as shown below should pop up, requiring the name for your runtime and the location on your file system where it can be found.
In general, you have two options:
If you simply want to use the default jars as included in the Drools Eclipse plugin, you can create a new Drools runtime automatically by clicking the "Create a new Drools 5 runtime ..." button. A file browser will show up, asking you to select the folder on your file system where you want this runtime to be created. The plugin will then automatically copy all required dependencies to the specified folder. After selecting this folder, the dialog should look like the figure shown below.
If you want to use one specific release of the Drools project, you should create a folder on your file system that contains all the necessary Drools libraries and dependencies. Instead of creating a new Drools runtime as explained above, give your runtime a name and select the location of this folder containing all the required jars.
After clicking the OK button, the runtime should show up in your table of installed Drools runtimes, as shown below. Click on checkbox in front of the newly created runtime to make it the default Drools runtime. The default Drools runtime will be used as the runtime of all your Drools project that have not selected a project-specific runtime.
You can add as many Drools runtimes as you need. For example, the screenshot below shows a configuration where three runtimes have been defined: a Drools 4.0.7 runtime, a Drools 5.0.0 runtime and a Drools 5.0.0.SNAPSHOT runtime. The Drools 5.0.0 runtime is selected as the default one.
Note that you will need to restart Eclipse if you changed the default runtime and you want to make sure that all the projects that are using the default runtime update their classpath accordingly.
Whenever you create a Drools project (using the New Drools Project wizard or by converting an existing Java project to a Drools project using the "Convert to Drools Project" action that is shown when you are in the Drools perspective and you right-click an existing Java project), the plugin will automatically add all the required jars to the classpath of your project.
When creating a new Drools project, the plugin will automatically use the default Drools runtime for that project, unless you specify a project-specific one. You can do this in the final step of the New Drools Project wizard, as shown below, by deselecting the "Use default Drools runtime" checkbox and selecting the appropriate runtime in the drop-down box. If you click the "Configure workspace settings ..." link, the workspace preferences showing the currently installed Drools runtimes will be opened, so you can add new runtimes there.
You can change the runtime of a Drools project at any time by opening the project properties (right-click the project and select Properties) and selecting the Drools category, as shown below. Check the "Enable project specific settings" checkbox and select the appropriate runtime from the drop-down box. If you click the "Configure workspace settings ..." link, the workspace preferences showing the currently installed Drools runtimes will be opened, so you can add new runtimes there. If you deselect the "Enable project specific settings" checkbox, it will use the default runtime as defined in your global preferences.
As Drools is an open source project, instructions for building from source are part of the manual ! Building from source means you can stay on top with the latest features. Whilst aspects of Drools are quite complicated, many users have found ways to become contributors.
Drools works with JDK1.5 and above. you will need also need to have the following tools installed. Minimum requirement version numbers provided.
Ensure the executables for ant, maven and java are in your path. The examples given illustrative and are for a win32 system:
Path=D:\java\j2sdk1.5.0_8\bin;D:\java\apache-ant-1.7\bin;D:\java\maven-2.0.9\bin
Following environment variables will also need to be set. The examples given illustrative and are for a win32 system::
JAVA_HOME=D:\java\j2sdk1.5.0_8
ANT_HOME=D:\java\apache-ant-1.7
MAVEN_HOME=D:\java\maven-2.0.9
Past releases used to have an ant based build mechanism, but now maven is mandatory, although Ant is used internally in maven for document building proposes
Drools is available from two Subversion repositories.
Anonymous SVN
http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/
Developers secured SVN
https://svn.jboss.org/repos/labs/labs/jbossrules/trunk/
fmeyer:~/jboss $ svn checkout http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/ trunkAnd wait to complete the files download.
A trunk/drools-repository A trunk/drools-repository/.classpath A trunk/drools-repository/.project A trunk/drools-repository/doc A trunk/drools-repository/doc/repository_layout.jpeg A trunk/drools-repository/doc/high_level_design.jpeg A trunk/drools-repository/doc/javadoc A trunk/drools-repository/doc/javadoc/serialized-form.html A trunk/drools-repository/doc/javadoc/index-all.html A trunk/drools-repository/doc/javadoc/stylesheet.css A trunk/drools-repository/doc/javadoc/allclasses-frame.html A trunk/drools-repository/doc/javadoc/package-list A trunk/drools-repository/doc/javadoc/overview-tree.html A trunk/drools-repository/doc/javadoc/org A trunk/drools-repository/doc/javadoc/org/drools A trunk/drools-repository/doc/javadoc/org/drools/repository A trunk/drools-repository/doc/javadoc/org/drools/repository/class-use A trunk/drools-repository/doc/javadoc/org/drools/repository/class-use/RuleSet.html A trunk/drools-repository/doc/javadoc/org/drools/repository/class-use/RulesRepositoryException.html A trunk/drools-repository/doc/javadoc/org/drools/repository/class-use/RulesRepository.html A trunk/drools-repository/doc/javadoc/org/drools/repository/RuleSet.html .... snip .... A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/benchmark/waltz A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/benchmark/waltz/waltz.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/benchmark/manners A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/benchmark/manners/manners.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/benchmark/waltzdb A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/benchmark/waltzdb/waltzdb.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/TroubleTicketWithDSL.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/TroubleTicket.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/calculate.rfm A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/generation.rf A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/calculate.rf A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/registerNeighbor.rfm A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/killAll.rfm A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/registerNeighbor.rf A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/conway-agendagroup.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/killAll.rf A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/conway-ruleflow.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/conway/generation.rfm A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/ticketing.dsl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/StateExampleUsingSalience.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/golf.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/LogicalAssertionsNotPingPong.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/StateExampleDynamicRule.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/sudoku A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/sudoku/sudoku.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/HelloWorld.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/ExamplePolicyPricing.xls A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/HonestPolitician.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/Fibonacci.drl A trunk/drools-examples/drools-examples-drl/src/main/rules/org/drools/examples/StateExampleUsingAgendGroup.drl A trunk/drools-examples/drools-examples-drl/pom.xml A trunk/drools-examples/drools-examples-drl/build.xml U trunk Checked out revision 13656.
Although, we highly recommend command line tools to work with repository you can also use both Eclipse's integrated SVN client or TortoiseSVN
Setup TortoiseSVN to checkout from the subversion repository and click
'OK'
Once the checkout has finished you should see the
folders as shown below.
Now that we have the source the next step is to build and install the source. Since version 3.1 Drools uses Maven 2 to build the system. There are two profiles available which enable the associated modules "documentation" and "Eclipse"; this enables quicker building of the core modules for developers. The Eclipse profile will download Eclipse into the drools-Eclipse folder, which is over 100MB download (It depends on your operating system), however this only needs to be done once; if you wish you can move that Eclipse download into another location and specify it with -DlocalEclipseDrop=/folder/jboss-drools/local-Eclipse-drop-mirror. The following builds all the jars, the documentation and the Eclipse zip with a local folder specified to avoid downloading Eclipse:
mvn -Declipse -Ddocumentation clean install -DlocalEclipseDrop=/folder/jboss-drools/local-Eclipse-drop-mirror
You can produce distribution builds, which puts everything into zips, as follows:
mvn -Declipse -Ddocumentation clean install -DlocalEclipseDrop=/folder/jboss-drools/local-Eclipse-drop-mirror mvn -Ddocumentation -Declipse -Dmaven.test.skip package javadoc:javadoc assembly:assembly -DlocalEclipseDrop=/folder/jboss-drools/local-Eclipse-drop-mirror
Note that install must be done first as javadoc:javadoc won't work unless the jars are in the local maven repo, but the tests can be skipped on the second run. assembly:assembly fails unless you increase the available memory to Maven, on windows the following command worked well: set MAVEN_OPTS=-Xmx512m
Type mvn clean to clear old artifacts, and then test and built the source, and report on any errors.
The resulting jars are put in the /target directory from the top level of the project.
As maven builds each module it will install the resulting jars in
the local Maven 2 repository automatically. Where it can be easily used
from other project pom.xml
or copied else where.
The building of the manual is now integrated into the maven build process, and is built by either using the profile (-Ddocumentation) switch or cding into the main directory.
Drools uses Docbook for this manual. Maven is used to build documents and this build produces three different formats, all sharing the same images directory.
The manual can be generated from the project pom.xml by
calling 'mvn package'
in the drools-docs directory or adding the -Ddocumentation switch when you build the sources.
Documentation is generated into each drools-docs subdirectory's 'target/'
directory. Running 'mvn -Ddocumentation package assembly:assembly'
in the Drools project root generates and copies the documentation into a zip file. This zip file is located in the root folders 'target/'
directory.
[trikkola@trikkola trunk]$ mvn -Ddocumentation clean package assembly:assembly [INFO] Scanning for projects... [INFO] Reactor build order: [INFO] Drools [INFO] Drools :: API [INFO] Drools :: Core [INFO] Drools :: Compiler [INFO] Drools :: Templates [INFO] Drools :: Decision Tables [INFO] Drools :: JSR-94 API Module [INFO] Drools :: Pipeline :: Transformer :: Smooks [INFO] Drools :: Pipeline :: Transformer :: JAXB [INFO] Drools :: Pipeline :: Transformer :: XStream [INFO] Drools :: Pipeline :: Transformer :: JXLS [INFO] Drools :: Pipeline :: Messenger :: JMS [INFO] Drools :: Pipeline [INFO] Drools :: Process :: WorkItems [INFO] Drools :: Process :: Task [INFO] Drools :: Process :: BAM [INFO] Drools :: Process [INFO] Drools :: Persistence :: JPA [INFO] Drools :: Server [INFO] Drools :: Verifier [INFO] Drools :: Ant Task [INFO] Drools :: Repository [INFO] Drools :: Guvnor [INFO] Drools :: Microcontainer [INFO] Drools :: Clips [INFO] Drools :: Solver parent [INFO] Drools :: Solver core [INFO] Drools :: Solver examples [INFO] Searching repository for plugin with prefix: 'assembly'. WAGON_VERSION: 1.0-beta-2 [INFO] ------------------------------------------------------------------------ [INFO] Building Drools [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------------ [INFO] [clean:clean] [INFO] [site:attach-descriptor] [INFO] Preparing source:jar [WARNING] Removing: jar from forked lifecycle, to prevent recursive invocation. [INFO] No goals needed for project - skipping [INFO] [source:jar {execution: default}] [INFO] Preparing source:test-jar [WARNING] Removing: jar from forked lifecycle, to prevent recursive invocation. [WARNING] Removing: test-jar from forked lifecycle, to prevent recursive invocation. [INFO] No goals needed for project - skipping [INFO] [source:test-jar {execution: default}] [INFO] ------------------------------------------------------------------------ [INFO] Building Drools :: API [INFO] task-segment: [clean, package] [INFO] ------------------------------------------------------------------------ [INFO] [clean:clean] [INFO] Deleting directory /home/trikkola/jboss-drools/trunk/drools-api/target ...snip ... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] Drools ................................................ SUCCESS [59.889s] [INFO] Drools :: API ......................................... SUCCESS [4.832s] [INFO] Drools :: Core ........................................ SUCCESS [11.027s] [INFO] Drools :: Compiler .................................... SUCCESS [10.400s] [INFO] Drools :: Templates ................................... SUCCESS [1.018s] [INFO] Drools :: Decision Tables ............................. SUCCESS [1.179s] [INFO] Drools :: JSR-94 API Module ........................... SUCCESS [1.001s] [INFO] Drools :: Pipeline :: Transformer :: Smooks ........... SUCCESS [0.651s] [INFO] Drools :: Pipeline :: Transformer :: JAXB ............. SUCCESS [0.711s] [INFO] Drools :: Pipeline :: Transformer :: XStream .......... SUCCESS [0.465s] [INFO] Drools :: Pipeline :: Transformer :: JXLS ............. SUCCESS [0.481s] [INFO] Drools :: Pipeline :: Messenger :: JMS ................ SUCCESS [0.879s] [INFO] Drools :: Pipeline .................................... SUCCESS [0.006s] [INFO] Drools :: Process :: WorkItems ........................ SUCCESS [1.526s] [INFO] Drools :: Process :: Task ............................. SUCCESS [3.104s] [INFO] Drools :: Process :: BAM .............................. SUCCESS [0.580s] [INFO] Drools :: Process ..................................... SUCCESS [0.005s] [INFO] Drools :: Persistence :: JPA .......................... SUCCESS [0.958s] [INFO] Drools :: Server ...................................... SUCCESS [2.216s] [INFO] Drools :: Verifier .................................... SUCCESS [1.836s] [INFO] Drools :: Ant Task .................................... SUCCESS [0.722s] [INFO] Drools :: Repository .................................. SUCCESS [3.925s] [INFO] Drools :: Guvnor ...................................... SUCCESS [19.850s] [INFO] Drools :: Microcontainer .............................. SUCCESS [0.676s] [INFO] Drools :: Clips ....................................... SUCCESS [1.464s] [INFO] Drools :: Solver parent ............................... SUCCESS [0.527s] [INFO] Drools :: Solver core ................................. SUCCESS [2.209s] [INFO] Drools :: Solver examples ............................. SUCCESS [4.689s] [INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2 minutes 24 seconds [INFO] Finished at: Tue Apr 07 15:11:14 EEST 2009 [INFO] Final Memory: 48M/178M [INFO] ------------------------------------------------------------------------>
The generated manual can be found in the
target\drools-docs$VERSION.jar'
file, a compressed archive with all formats.
With the Eclipse project files generated they can now be imported into Eclipse. When starting Eclipse open the workspace in the root of your subversion checkout.
When calling 'mvn install'
all the project
dependencies were downloaded and added to the local Maven repository.
Eclipse cannot find those dependencies unless you tell it where that
repository is. To do this setup an M2_REPO classpath variable.