Friday, November 21, 2014

Red Hat JBoss BRMS and BPMS Rich Client Framework demonstrating Polyglot Integration with GWT/Errai/UberFire and AngularJS

Last week I published a blog highlighting a presentation I gave showing our rich client platform that has resulted from the work we have done within the BRMS and BPMS platforms, the productised versions of the Drools and jBPM projects. The presentation is all screenshots and videos, you can find the blog and the link to the slideshare here:
"Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology"

The presentation highlighted the wider scope of our UI efforts; demonstrating what we've done within the BRMS and BPMS platform and the flexibility and adaptability provided by our UI technology. It provides a great testimony for the power of GWTErrai and UberFire, the three technologies driving all of this. We can't wait for the GWT 2.7 upgrade :)

As mentioned in the last blog the UberFire website is just a placeholder and there is no release yet. The plan is first to publish our 0.5 release, but that is more for our BRMS and BPMS platforms. We will then move it to GWT 2.7 and work towards a UF 1.0, which will be suitable for wider consumption.  With 1.0 we will add examples and documentation and work on making things more easily understood and consumable for end users. Of course there is nothing to stop the adventurous trying 0.5, the code is robust and already productized within BRMS and BPMS - we are always on irc to help, Freenode #uberfire.

That presentation itself built on the early video's showing our new Apps framework:
The Drools and jBPM KIE Apps Framework

The above video already demonstrates our polyglot capabilities, building AngularJS components and using them within the UF environments. It also shows of our spiffy new JSFiddle inspired RAD environment.

I'd now like to share with you the work we've done on the other side of polyglot development - this time using GWT and UF from within AngularJS. It was important we allow for an AngularJS first approach, that worked with the tool chain that AngularJS people are familiar with. By AngularJS first, I mean that AngularJS is the outer most container. Where as in the above video UF is already running and is the outer container in which individual AngularJS components can be used.

Before I detail the work we've done it's first best to cover the concepts of Screens and Perspectives, our two main components that provide our polyglot interoprability - there are others, but this is enough to understand the videos and examples that come next. A Screen is our simplest component, it is a DIV plus optional life cycle callbacks. A Perspective is also a DIV, but it contains a composition of 1..n Screen with different possible layout managers and persistence of the layout.

Screen
  • CDI discovery, or programmatically registered.
  • DIV on a page.
  • Life cycle callbacks.
    • OnStart, OnClose, OnFocus, OnLostFocus, OnMayClose, OnReveal.
  • Decoupling via Errai Bus.
    • Components do not invoke each other, all communication handled by a bus.
  • Editors extend screens, are associated with resource types and provide the additional life cycles
    • onSave, isDirty.
Perspective
  • CDI discovery, or programmatically registered.
  • Composition of 1..n Screens, but is itself a DIV.
  • Supports pluggable window management of Screens.
    • North, East, South West (NESW).
      • Drag and Drop docking capabilities.
    • Bootstrap Grid Views.
      • Separate design time and runtime.
    • Templates (ErraiUI or AngularJS).
      • Absolute control of Perspective content and layout.
  • Supports persistence of Perspective layout, should the user re-design it.
    • Only applicable to NESW and Bootstrap Grid views.

A picture is worth a thousands words, so here is a screenshot of the Perspective Builder in action. Here it uses the Bootstrap Grid View layout manager. Within each grid cell is a Screen. The Perspective is saved and then available from within the application. If the NESW layout manager was used there is no separate design time, and all dragging is done in-place and persistence happens in the background after each change. Although it's not shown in the screenshot below we also support  both list (drop list) and tab stacks for Screens.



Now back to what an AngularJS first approach means. 6 different points were identified as necessary to demonstrate that this is possible.
  1. UF Screens and Perspectives should be available seamlessly as AngularJS Directives.
  2. Bower packaging for a pre-compiled UFJS. UFJS is the pre-compile client only version of UF.
  3. UFJS can work standalone, file:// for example. UFJS can optionally work with an UF war backend, allowing persistence of perspectives and other optional places that UFJS might need to save state as well as access to our full range of provided services, like identity management.
  4. Support live refresh during development.
  5. Nested Controllers.
  6. Persistence and routing.
  7. Work with tools such as Yeoman, Grunt and Karma.
Eder has produced a number of examples, that you can run yourself. These demonstrate all of the points have been solved. You can find the code here, along with the README to get you started. We did not provide video's for point 7, as I believe the video's for points 1 to 6 show that this would not be a problem.

Eder has also created several short videos running the examples, for each of the use cases, and put them into a YouTube playlist. He has added text and callouts to make it clear what's going on:
AngularJS + UF PlayList
  1. Overview explaining what each video demonstrates (33s).
  2. AngularJS App + UFJS, client only, distribution using Bower. (2m30s).
    • Install and play with UFJS through Bower
    • Create a Native AngularJS App
    • Integrate this app with UFJS
      • Show UF Screen Directives
      • Show UF Perspective Directives
  3. AngularJS App + UFJS client and UF Server.
    • 1 of 2 (3m58s).
      • Download UF War
      • Install and run on EAP
      • Download and run our Angular demo on Apache
      • Show AngularJS Routes + UF Integration
    • 2 of 2 (4m06s).
      • Use UF to create Dynamic Screens and Perspectives
      • Encapsulate an AngularJS template in a UF Screen
      • Show an AngularJS App (inside a UF screen) nested in a parent controller.
        • Demonstrated multiple levels of controller nesting.
  4. KIE UF Workbench RAD environment with AngularJS component.
  5. Uberfire Editor working seamlessly as an Eclipse editor.
For completeness the original video's showing the JSFiddle inspired RAD environment, which demonstrates an UF first polyglot environment, have been added to the playlist. See point 4. above

Finally just to show of, and because we can, we added a bonus video demonstrating a UF editor component running seamlessly in Eclipse. This demonstrates the power of our component model - which has been designed to allow our components to work standalone in any environment. We use Errai to intercept all the RPC calls and bridge them to Eclipse. Because the virtual file system our editors use, like other services, is decoupled and abstracted we can adapt it to the Eclipse File io. For the end user the result is a seamless editor, that appears native. This allows the development of components that can work on the web and in Eclipse, or even IntelliJ. We'll work on making this example public at a later date.

Here are some screenshots taken from the video's

(click image to enlarge)

(click image to enlarge)

(click image to enlarge)

(click image to enlarge)


(click image to enlarge)


(click image to enlarge)


(click image to enlarge)


(click image to enlarge)



Finally to all those that said it couldn't be done!!!!


Wednesday, November 05, 2014

Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology

Last week I did a blog highlighting the recent R&D we are doing to make our web platform easily extensible and allow the development of a self service apps platform. The blog had two video links showing progress.

Today I gave a presentation that highlighted the wider scope of our UI efforts; demonstrating what we've done within the BRMS and BPMS platform and the flexibility and adaptability provided by our UI technology. It provides a great testimony for the power of GWTErrai and UberFire, the three technologies driving all of this. We can't wait for the GWT 2.7 upgrade :)



As mentioned in the last blog the UberFire website is just a placeholder and there is no release yet, we'll be working on that over xmas, along with documention to make things more easily understandable and consumerable for end users.

The presentation is now live up on Slideshare and I've taken time to embed all the video's within it.
http://www.slideshare.net/MarkProctor/red-hat-jboss-brms-and-bpms-workbench-as-a-platform

The presentation is mostly self explanatory screenshots with headers with videos scattered throughout - many of which are previous video's you might have seen before. It provides a very good over, using scatter gun approach, of what we have done, what we are doing and where we are going. Two of the videos around the extensible workbench and the technical web ide have audio commentary.

It starts by showing the existing BRMS and BPMS stuff before moving onto the new extensibility efforts. Finally it covers a new demo we've done with the workbench reskinned for a more technical audience. It also shows ACE integration for java and xml editing, as well as real time provisioning and running of Spring Pet Clinic application within the workbench.

Thursday, October 30, 2014

The Drools and jBPM KIE Apps Framework

With the Drools and jBPM (KIE) 6 series came a new workbench, with the promise of eventual end user extensibility. I finally have some teaser videos to show this working and what's in store. Make sure you select 1080p and go full screen to see them at their best.
(click to enlarge)

(click to enlarge)

What you seen in these videos is the same workbench available on the Drools video's page. Once this stuff is released you'll be able to extend an existing Drools or JBPM (KIE) installation or make a new one from scratch that doesn't have Drools or jBPM in it - i.e. the workbench and it's extension stuff is available standalone, and you get to chose which plugins you do or don't want.

Here is demo showing the new Bootstrap dynamic grid view builder used to build a perspective, which now doubles as an app. It uses the new RAD, JSFiddle inspired, environment to author a simple AngularJS plugin extension. This all writes to a GIT backend, so you could author these with Intellij or Eclipse and just push it back into the GIT repo. It then demonstrates the creation of a dynamic menu and registers our app there. It then also demonstrates the new app directory. Apps are given labels and can then be discovered in the apps directory - instead, or as well as, top menu entries. Over 2015 we'll be building a case management system which will compliment this perfect as the domain front end - all creating a fantastic Self Service Software platform.
http://youtu.be/KoJ5A5g7y4E

Here is a slightly early video showing our app builder working with DashBuilder,
http://youtu.be/Yhg31m4kRsM

Other components such as our Human Tasks and Forms will be available too. We Also have some cool infrastructure coming event publication and capture and timeline reporting, so you visualise social activity within your organization - you'll be able to place time timeline components you see in this blog, on your app pages:
http://blog.athico.com/2014/09/activity-insight-coming-in-drools-jbpm.html

All this is driven by our new project UberFire, which provides the workbench infrastructure for all of this. The project is not yet announced or released, but will do so soon - the website is currently just a placeholder, we'll blog as soon as there is something to see  :)

Wednesday, October 29, 2014

The next version of GMail at Google written in GWT

http://www.theverge.com/2014/10/22/7039391/google-inbox




Friday, October 24, 2014

Red Hat Job Opening - Software Sustaining Engineer

We are looking to hire someone to help improve the quality of BRMS and BPMS platforms. These are the productised versions of the Drools and jBPM open source projects.

The role will involve improving our test coverage, diagnosis problems, creating reproducers for problems as well as helping fix them. You’ll also be responsible for helping to setup and maintain our continue integration environment to help streamline the various aspects involved in getting timely high quality releases out.

So if you love Drools and jBPM, and want to help make them even better and even more robust - then this is the job for you :)

The role is remote, so you can be based almost anywhere.

URL to apply now http://jobs.redhat.com/jobs/descriptions/software-engineer-brno-jihomoravsky-kraj-czech-republic-job-1-4759718

Mark

Tuesday, October 14, 2014

Decision Camp - 2014 - What you are missing out on

Here is the Decision Camp 2014 agenda, so you can see what you are missing out on, if you aren't there :)

Tuesday

9:30 - 10:00 am
Registration
10 - 11 am
11 am - 12 pm
CTO Panel
Mark Proctor, Red Hat
Dr. Jacob Feldman, OpenRules
Carlos Serrano-Morales, Sparkling Logic
Moderated by James Taylor
12 - 1 pm
Lunch

General Sessions

We will host Best Practices sessions all day, presented by fellow practitioners or technology providers
General sessions will have break out tracks for rules writers and software architects
1 - 2 pm
An Intelligence Led Approach to Decision Management in Tax AdministrationDr. Marcia Gottgtroy, Inland Revenue New Zealand
Decision Tables as a Programming tool
Howard Rogers, RapidGen Software
Are Business Rules Obsolete?
Kenny Shi, UBER Technologies
2 - 3 pm
Customer Support Process AutomationErwin De Ley, iSencia Belgium
Building Domain-Specific Decision ModelsDr. Jacob Feldman, OpenRules
4 - 5 pm
Explanation-based E-Learning for Business Decision Making and Education 
Benjamin Grosof & Janine Bloomfield, Coherent Knowledge Systems

Wednesday

9:30 - 10 am
Registration

Vertical Day
Healthcare

Davide Sottara is our chair for the Healthcare day 

Vertical Day
Financial Services

10 - 11 am
TBA
Dr. Davide Sottara, PhD
11 am - 12 pm
Preparing for Exceptional Behavior
Carole-Ann Matignon, Sparkling Logic
12 - 1 pm
Lunch & Networking
1 - 2 pm
Cloud-based CEP in Healthcare 
Mariano Nicolas De Maio, PlugTree
Analytics for Payment Fraud
Carlos Serrano-Morales, Sparkling Logic
4 - 5 pm
Speaker Panel
All Speakers

Classic Games Development with Drools

I realised I didn't upload my slides from Decision Camp 2013, where I talked about using Games to learn Rule Based Programming. Sorry about that, here they are better late than never:
Learning Rule Based Programming Using Games

The talk provides a gentle introduction into rule engines and then covers a number of different games, all of which are available to run from the drools examples project.
  • Number Guess
  • Adventure Game
  • Space Invaders
  • Pong
  • Wumpus World
While there is no video for the presentation I gave, I have made videos for some of these games in the past. Although beware some of them may be a little out of date now, compared to the version that is in our current examples project.

Friday, October 10, 2014

3 Days until Decision Camp 2014, San Jose (13-15 Oct)

Only 3 days to go until Decision Camp 2014 arrives, a free conference in the San Jose area for business rules and decision management practictioners. The conference is multi-track with 3 concurrent tracks at same time. The Decision Camp full agenda can be found here.

Like last year  RuleML will be participating and presenting, such as Dr. Benjamin Grosof. Which is a great opportunity to catch up on the latest happenings in the rules standards industry.

Last year I did a games talk, this year I'm doing something a little more technical, to reflect my current research. Here is my title and abstract.
Demystifying Truth Maintenance and Belief Systems
Basic Truth Maintenance is a common feature, available in many production rule systems, but it one that is not generally well understood. This talk will start by introducing the mechanics of rule engines and how that is extended for the common TMS implementation. It will discuss the limitations of these systems and introduce Justification based Truth Maintenance (JTMS) as a way to add contradictions, to trigger retractions. This will lead onto Defeasible Logic, which while sounding complex, facilitates the resolving of conflicting rules of premisses and contradictions, in a way that follows typical argumentation theory. Finally we will demonstrate how the core of this can be abstracted to allow pluggable beliefs, so that JTMS and Defeasible can be swapped in and out, along other systems such as Bayesian Belief Systems.




Friday, October 03, 2014

10 Days until Decision Camp 2014, San Jose (13-15 Oct)

Only 10 days to go until Decision Camp 2014 arrives, a free conference in the San Jose area for business rules and decision management practictioners. The conference is multi-track with 3 concurrent tracks at same time. The Decision Camp full agenda can be found here.

Like last year  RuleML will be participating and presenting, such as Dr. Benjamin Grosof. Which is a great opportunity to catch up on the latest happenings in the rules standards industry.

Last year I did a games talk, this year I'm doing something a little more technical, to reflect my current research. Here is my title and abstract.
Demystifying Truth Maintenance and Belief Systems
Basic Truth Maintenance is a common feature, available in many production rule systems, but it one that is not generally well understood. This talk will start by introducing the mechanics of rule engines and how that is extended for the common TMS implementation. It will discuss the limitations of these systems and introduce Justification based Truth Maintenance (JTMS) as a way to add contradictions, to trigger retractions. This will lead onto Defeasible Logic, which while sounding complex, facilitates the resolving of conflicting rules of premisses and contradictions, in a way that follows typical argumentation theory. Finally we will demonstrate how the core of this can be abstracted to allow pluggable beliefs, so that JTMS and Defeasible can be swapped in and out, along other systems such as Bayesian Belief Systems.




Thursday, October 02, 2014

Trace output with Drools

Drools 6 includes a trace output that can help get an idea of what is going on in your system,  and how often things are getting executed, and with how much data.

It can also help to understand that Drools 6 is now a goal based algorithm, using a linking mechanism to link in rules for evaluation. More details on that here:
http://blog.athico.com/2013/11/rip-rete-time-to-get-phreaky.html

The first thing to do is set your slf4j logger to trace mode:
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <!-- %l lowers performance -->
      <!--<pattern>%d [%t] %-5p %l%n  %m%n</pattern>-->
      <pattern>%d [%t] %-5p %m%n</pattern>
    </encoder>
  </appender>

  <logger name="org.drools" level="trace"/>

  <root level="info"><!-- TODO We probably want to set default level to warn instead -->
    <appender-ref ref="consoleAppender" />
  </root>
</configuration>

Let's take the shopping example, you can find the Java and Drl files for this here:
https://github.com/droolsjbpm/drools/blob/master/drools-examples/src/main/resources/org/drools/examples/shopping/Shopping.drl
https://github.com/droolsjbpm/drools/blob/master/drools-examples/src/main/java/org/drools/examples/shopping/ShoppingExample.java


Running the example will give output a very detailed and long log of execution. Initially you'll see objects being inserted, which causes linking. Linking of nodes and rules is explained in the Drools 6 algorithm link. In summary 1..n nodes link in a segment, when object are are inserted.
2014-10-02 02:35:09,009 [main] TRACE Insert [fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac]
2014-10-02 02:35:09,020 [main] TRACE LinkNode notify=false nmask=1 smask=1 spos=0 rules=

Then 1..n segments link in a rule. When a Rule is linked in it's schedule on the agenda for evaluation.
2014-10-02 02:35:09,043 [main] TRACE  LinkRule name=Discount removed notification
2014-10-02 02:35:09,043 [main] TRACE Queue RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,043 [main] TRACE Queue Added 1 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]

When it eventually evaluates a rule it will indent as it visits each node, as it evaluate from root to tip. Each node will attempt to tell you how much data is being inserted, updated or deleted at that point.
2014-10-02 02:35:09,046 [main] TRACE Rule[name=Apply 10% discount if total purchases is over 100] segments=2 TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,047 [main] TRACE      1 [ AccumulateNode(12) ] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,047 [main] TRACE      Segment 1
2014-10-02 02:35:09,047 [main] TRACE      1 [ AccumulateNode(12) ] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,047 [main] TRACE      rightTuples TupleSets[insertSize=2, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,056 [main] TRACE        2 [RuleTerminalNode(13): rule=Apply 10% discount if total purchases is over 100] TupleSets[insertSize=1, deleteSize=0, updateSize=0]

You can use this information to see how often rules evaluate, how much linking and unlinking happens, how much data propagates and more important how much wasted work is done.  Here is the full log:
2014-10-02 02:35:08,889 [main] DEBUG Starting Engine in PHREAK mode
2014-10-02 02:35:08,927 [main] TRACE Adding Rule Purchase notification
2014-10-02 02:35:08,929 [main] TRACE Adding Rule Discount removed notification
2014-10-02 02:35:08,931 [main] TRACE Adding Rule Discount awarded notification
2014-10-02 02:35:08,933 [main] TRACE Adding Rule Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,009 [main] TRACE Insert [fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac]
2014-10-02 02:35:09,020 [main] TRACE LinkNode notify=false nmask=1 smask=1 spos=0 rules=
2014-10-02 02:35:09,020 [main] TRACE   LinkSegment smask=2 rmask=2 name=Discount removed notification
2014-10-02 02:35:09,025 [main] TRACE   LinkSegment smask=2 rmask=2 name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,028 [main] TRACE LinkNode notify=true nmask=1 smask=1 spos=0 rules=[RuleMem Purchase notification], [RuleMem Discount removed notification], [RuleMem Discount awarded notification], [RuleMem Apply 10% discount if total purchases is over 100]
2014-10-02 02:35:09,028 [main] TRACE   LinkSegment smask=1 rmask=1 name=Purchase notification
2014-10-02 02:35:09,028 [main] TRACE   LinkSegment smask=1 rmask=3 name=Discount removed notification
2014-10-02 02:35:09,043 [main] TRACE  LinkRule name=Discount removed notification
2014-10-02 02:35:09,043 [main] TRACE Queue RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,043 [main] TRACE Queue Added 1 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,043 [main] TRACE   LinkSegment smask=1 rmask=1 name=Discount awarded notification
2014-10-02 02:35:09,043 [main] TRACE   LinkSegment smask=1 rmask=3 name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,043 [main] TRACE  LinkRule name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,043 [main] TRACE Queue RuleAgendaItem [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,043 [main] TRACE Queue Added 2 [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,043 [main] TRACE Added Apply 10% discount if total purchases is over 100 to eager evaluation list.
2014-10-02 02:35:09,044 [main] TRACE Insert [fact 0:2:14633842:14633842:2:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Product@df4b72]
2014-10-02 02:35:09,044 [main] TRACE Insert [fact 0:3:732189840:732189840:3:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Product@2ba45490]
2014-10-02 02:35:09,044 [main] TRACE Insert [fact 0:4:939475028:939475028:4:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Purchase@37ff4054]
2014-10-02 02:35:09,045 [main] TRACE BetaNode insert=1 stagedInsertWasEmpty=true
2014-10-02 02:35:09,045 [main] TRACE LinkNode notify=true nmask=1 smask=1 spos=1 rules=[RuleMem Purchase notification]
2014-10-02 02:35:09,045 [main] TRACE   LinkSegment smask=2 rmask=3 name=Purchase notification
2014-10-02 02:35:09,045 [main] TRACE  LinkRule name=Purchase notification
2014-10-02 02:35:09,046 [main] TRACE Queue RuleAgendaItem [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,046 [main] TRACE Queue Added 1 [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,046 [main] TRACE BetaNode insert=1 stagedInsertWasEmpty=true
2014-10-02 02:35:09,046 [main] TRACE LinkNode notify=true nmask=1 smask=1 spos=1 rules=[RuleMem Apply 10% discount if total purchases is over 100]
2014-10-02 02:35:09,046 [main] TRACE   LinkSegment smask=2 rmask=3 name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,046 [main] TRACE  LinkRule name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,046 [main] TRACE Added Apply 10% discount if total purchases is over 100 to eager evaluation list.
2014-10-02 02:35:09,046 [main] TRACE Insert [fact 0:5:8996952:8996952:5:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Purchase@894858]
2014-10-02 02:35:09,046 [main] TRACE BetaNode insert=2 stagedInsertWasEmpty=false
2014-10-02 02:35:09,046 [main] TRACE BetaNode insert=2 stagedInsertWasEmpty=false
2014-10-02 02:35:09,046 [main] TRACE Rule[name=Apply 10% discount if total purchases is over 100] segments=2 TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,047 [main] TRACE      1 [ AccumulateNode(12) ] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,047 [main] TRACE      Segment 1
2014-10-02 02:35:09,047 [main] TRACE      1 [ AccumulateNode(12) ] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,047 [main] TRACE      rightTuples TupleSets[insertSize=2, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,056 [main] TRACE        2 [RuleTerminalNode(13): rule=Apply 10% discount if total purchases is over 100] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,057 [main] TRACE        Segment 1
2014-10-02 02:35:09,057 [main] TRACE        2 [RuleTerminalNode(13): rule=Apply 10% discount if total purchases is over 100] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,057 [main] TRACE Rule[name=Apply 10% discount if total purchases is over 100] segments=2 TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,057 [main] TRACE      3 [ AccumulateNode(12) ] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,057 [main] TRACE Rule[name=Purchase notification] segments=2 TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,057 [main] TRACE      4 [JoinNode(5) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Purchase]] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,057 [main] TRACE      Segment 1
2014-10-02 02:35:09,057 [main] TRACE      4 [JoinNode(5) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Purchase]] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,058 [main] TRACE      rightTuples TupleSets[insertSize=2, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,058 [main] TRACE        5 [RuleTerminalNode(6): rule=Purchase notification] TupleSets[insertSize=2, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,058 [main] TRACE        Segment 1
2014-10-02 02:35:09,058 [main] TRACE        5 [RuleTerminalNode(6): rule=Purchase notification] TupleSets[insertSize=2, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,058 [main] TRACE Fire "Purchase notification" 
[[ Purchase notification active=false ] [ [fact 0:4:939475028:939475028:4:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Purchase@37ff4054]
[fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac] ] ]
Customer mark just purchased shoes
2014-10-02 02:35:09,060 [main] TRACE Fire "Purchase notification" 
[[ Purchase notification active=false ] [ [fact 0:5:8996952:8996952:5:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Purchase@894858]
[fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac] ] ]
Customer mark just purchased hat
2014-10-02 02:35:09,061 [main] TRACE Removing RuleAgendaItem [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,061 [main] TRACE Queue Removed 1 [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,061 [main] TRACE Rule[name=Discount removed notification] segments=2 TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,061 [main] TRACE      6 [NotNode(8) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,061 [main] TRACE      Segment 1
2014-10-02 02:35:09,061 [main] TRACE      6 [NotNode(8) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,061 [main] TRACE      rightTuples TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,061 [main] TRACE        7 [RuleTerminalNode(9): rule=Discount removed notification] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,061 [main] TRACE        Segment 1
2014-10-02 02:35:09,061 [main] TRACE        7 [RuleTerminalNode(9): rule=Discount removed notification] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,061 [main] TRACE Fire "Discount removed notification" 
[[ Discount removed notification active=false ] [ null
[fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac] ] ]
Customer mark now has a discount of 0
2014-10-02 02:35:09,063 [main] TRACE Removing RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,063 [main] TRACE Queue Removed 1 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,063 [main] TRACE Fire "Apply 10% discount if total purchases is over 100" 
[[ Apply 10% discount if total purchases is over 100 active=false ] [ [fact 0:6:2063009760:1079902208:6:null:NON_TRAIT:120.0]
[fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac] ] ]
2014-10-02 02:35:09,071 [main] TRACE Insert [fact 0:7:874153561:874153561:7:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Discount@341a8659]
2014-10-02 02:35:09,071 [main] TRACE   LinkSegment smask=2 rmask=3 name=Discount removed notification
2014-10-02 02:35:09,071 [main] TRACE  LinkRule name=Discount removed notification
2014-10-02 02:35:09,071 [main] TRACE Queue RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,071 [main] TRACE Queue Added 1 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,071 [main] TRACE BetaNode insert=1 stagedInsertWasEmpty=true
2014-10-02 02:35:09,071 [main] TRACE LinkNode notify=true nmask=1 smask=1 spos=1 rules=[RuleMem Discount awarded notification]
2014-10-02 02:35:09,071 [main] TRACE   LinkSegment smask=2 rmask=3 name=Discount awarded notification
2014-10-02 02:35:09,071 [main] TRACE  LinkRule name=Discount awarded notification
2014-10-02 02:35:09,071 [main] TRACE Queue RuleAgendaItem [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,071 [main] TRACE Queue Added 3 [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
Customer mark now has a shopping total of 120.0
2014-10-02 02:35:09,071 [main] TRACE Removing RuleAgendaItem [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,071 [main] TRACE Queue Removed 2 [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,071 [main] TRACE Rule[name=Discount removed notification] segments=2 TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,072 [main] TRACE      8 [NotNode(8) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,072 [main] TRACE      Segment 1
2014-10-02 02:35:09,072 [main] TRACE      8 [NotNode(8) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,072 [main] TRACE      rightTuples TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,073 [main] TRACE        9 [RuleTerminalNode(9): rule=Discount removed notification] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,073 [main] TRACE        Segment 1
2014-10-02 02:35:09,073 [main] TRACE        9 [RuleTerminalNode(9): rule=Discount removed notification] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,073 [main] TRACE Removing RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,073 [main] TRACE Queue Removed 1 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,073 [main] TRACE Rule[name=Discount awarded notification] segments=2 TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,073 [main] TRACE      10 [JoinNode(10) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,073 [main] TRACE      Segment 1
2014-10-02 02:35:09,073 [main] TRACE      10 [JoinNode(10) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,074 [main] TRACE      rightTuples TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,074 [main] TRACE        11 [RuleTerminalNode(11): rule=Discount awarded notification] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,074 [main] TRACE        Segment 1
2014-10-02 02:35:09,074 [main] TRACE        11 [RuleTerminalNode(11): rule=Discount awarded notification] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,074 [main] TRACE Fire "Discount awarded notification" 
[[ Discount awarded notification active=false ] [ [fact 0:7:874153561:874153561:7:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Discount@341a8659]
[fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac] ] ]
Customer mark now has a discount of 10
2014-10-02 02:35:09,074 [main] TRACE Removing RuleAgendaItem [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,074 [main] TRACE Queue Removed 1 [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,074 [main] TRACE Delete [fact 0:5:8996952:8996952:5:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Purchase@894858]
2014-10-02 02:35:09,074 [main] TRACE   LinkSegment smask=2 rmask=3 name=Purchase notification
2014-10-02 02:35:09,074 [main] TRACE  LinkRule name=Purchase notification
2014-10-02 02:35:09,074 [main] TRACE Queue RuleAgendaItem [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,074 [main] TRACE Queue Added 1 [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,075 [main] TRACE   LinkSegment smask=2 rmask=3 name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,075 [main] TRACE  LinkRule name=Apply 10% discount if total purchases is over 100
2014-10-02 02:35:09,075 [main] TRACE Queue RuleAgendaItem [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,075 [main] TRACE Queue Added 2 [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,075 [main] TRACE Added Apply 10% discount if total purchases is over 100 to eager evaluation list.
Customer mark has returned the hat
2014-10-02 02:35:09,075 [main] TRACE Rule[name=Apply 10% discount if total purchases is over 100] segments=2 TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,075 [main] TRACE      12 [ AccumulateNode(12) ] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,075 [main] TRACE      Segment 1
2014-10-02 02:35:09,075 [main] TRACE      12 [ AccumulateNode(12) ] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,075 [main] TRACE      rightTuples TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,075 [main] TRACE        13 [RuleTerminalNode(13): rule=Apply 10% discount if total purchases is over 100] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,075 [main] TRACE        Segment 1
2014-10-02 02:35:09,075 [main] TRACE        13 [RuleTerminalNode(13): rule=Apply 10% discount if total purchases is over 100] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,075 [main] TRACE Delete [fact 0:7:874153561:874153561:7:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Discount@341a8659]
2014-10-02 02:35:09,075 [main] TRACE   LinkSegment smask=2 rmask=3 name=Discount removed notification
2014-10-02 02:35:09,075 [main] TRACE  LinkRule name=Discount removed notification
2014-10-02 02:35:09,075 [main] TRACE Queue RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,075 [main] TRACE Queue Added 3 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,075 [main] TRACE UnlinkNode notify=true nmask=1 smask=0 spos=1 rules=[RuleMem Discount awarded notification]
2014-10-02 02:35:09,076 [main] TRACE   UnlinkSegment smask=2 rmask=1 name=[RuleMem Discount awarded notification]
2014-10-02 02:35:09,076 [main] TRACE     UnlinkRule name=Discount awarded notification
2014-10-02 02:35:09,076 [main] TRACE Queue RuleAgendaItem [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,076 [main] TRACE Queue Added 2 [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,076 [main] TRACE Rule[name=Purchase notification] segments=2 TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE      14 [JoinNode(5) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Purchase]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE      Segment 1
2014-10-02 02:35:09,076 [main] TRACE      14 [JoinNode(5) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Purchase]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE      rightTuples TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE        15 [RuleTerminalNode(6): rule=Purchase notification] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE        Segment 1
2014-10-02 02:35:09,076 [main] TRACE        15 [RuleTerminalNode(6): rule=Purchase notification] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE Removing RuleAgendaItem [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,076 [main] TRACE Queue Removed 1 [Activation rule=Purchase notification, act#=2, salience=10, tuple=null]
2014-10-02 02:35:09,076 [main] TRACE Rule[name=Discount removed notification] segments=2 TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE      16 [NotNode(8) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE      Segment 1
2014-10-02 02:35:09,076 [main] TRACE      16 [NotNode(8) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,076 [main] TRACE      rightTuples TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE        17 [RuleTerminalNode(9): rule=Discount removed notification] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE        Segment 1
2014-10-02 02:35:09,077 [main] TRACE        17 [RuleTerminalNode(9): rule=Discount removed notification] TupleSets[insertSize=1, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE Fire "Discount removed notification" 
[[ Discount removed notification active=false ] [ null
[fact 0:1:1455177644:1455177644:1:DEFAULT:NON_TRAIT:org.drools.examples.shopping.ShoppingExample$Customer@56bc3fac] ] ]
Customer mark now has a discount of 0
2014-10-02 02:35:09,077 [main] TRACE Removing RuleAgendaItem [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,077 [main] TRACE Queue Removed 1 [Activation rule=Discount removed notification, act#=0, salience=0, tuple=null]
2014-10-02 02:35:09,077 [main] TRACE Rule[name=Discount awarded notification] segments=2 TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE      18 [JoinNode(10) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE      Segment 1
2014-10-02 02:35:09,077 [main] TRACE      18 [JoinNode(10) - [ClassObjectType class=org.drools.examples.shopping.ShoppingExample$Discount]] TupleSets[insertSize=0, deleteSize=0, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE      rightTuples TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE        19 [RuleTerminalNode(11): rule=Discount awarded notification] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE        Segment 1
2014-10-02 02:35:09,077 [main] TRACE        19 [RuleTerminalNode(11): rule=Discount awarded notification] TupleSets[insertSize=0, deleteSize=1, updateSize=0]
2014-10-02 02:35:09,077 [main] TRACE Removing RuleAgendaItem [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,077 [main] TRACE Queue Removed 1 [Activation rule=Discount awarded notification, act#=7, salience=0, tuple=null]
2014-10-02 02:35:09,077 [main] TRACE Removing RuleAgendaItem [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]
2014-10-02 02:35:09,077 [main] TRACE Queue Removed 1 [Activation rule=Apply 10% discount if total purchases is over 100, act#=1, salience=0, tuple=null]