home‎ > ‎

Bus Logic Demo

The multi-table derivation / constraint business logic often represents half the effort in an application.  Even our simple example resulted in 500 lines of traditional code, when you consider the dependency management (what changed?  what depends on that?) across all the Use Cases that touch the data.  And yet, the requirements can be clearly stated in 5 rules on the venerable cocktail napkin.

By contrast, here is all you do to completely replace those 500 lines of business logic code:
  1. Enable the Business Logic Engine with the configuration shown (upper right).  It is not necessary to recode the calling application, which continues to use existing Hibernate/JPA APIs.

  2. Enter your requirements as methods in Domain Logic Classes that correspond to your Domain Objects.  The logic is expressed in the annotation.  More complex logic can be expressed in Java or Groovy methods.

There is nothing omitted from this diagram - this is the sum total of all that required to address all the Use Cases listed below.  

With this logic in place, the logic engine now listens for Hibernate commit events, and processes typical transactions as follows:

  • Change Order Paid
Since customer balance depends on this, the engine adjusts it with a 1 row update (not a SQL sum).  If the resultant balance exceeds the creditLimit, the transaction is not committed.
  • Change Order Note
No Logic is dependent on this change, so logic / SQLs are pruned - a 1 row update proceeds.
  • Change product for Line Item
The Orders' amountTotal is adjusted by the new Products' amount (derived by accessing the product.price) minus the old Products' amount with a single row update.  This chains to trigger an adjustment to the customer balance, and a creditLimit check.




Want to know more?  You can use this page to:

  • Contrast how a simple - and typical - problem is implemented with hundreds of lines of conventional manual code, vs. 5 rules with Automated Business Logic

  • Understand the basics of Automated Business Logic operation

  • See how Business Logic can provide Agility, Transparency, and Power, with an Architecture than does not require recoding, delivers Enterprise class performance, and automates re-use

The Problem

This describes a very small sample problem, used to contrast implementing our Requirements (described below) with a Conventional Implementation, and an Automated Business Logic Implementation.

The User Interface

We have developed a (lowest common denominator) JSP user interface shown at the top of this page.  Since Business Logic presents no change to the Hibernate API, we could use any Hibernate-compatible tool or framework.


The Business Logic Requirements

The Tutorial shows how you might uncover requirements in a project, but we will short-circuit that portion of the project and simply list them here:

The Business Requirement is that we assure that the customer's balance (computed from the rollup of the Lineitems and Orders) does not exceed the credit limit.  Specifically:
  1. Constraint: balance < creditLimit
  2. balance = sum(orders.total where paid = false)
  3. order.total = sum(lineitems.amount)
  4. lineitem.amount = quantity * partPrice
  5. lineitem.partPrice = copy(part.price)

The User Interface above obligates us to build the following Use Cases (or Function Points):
  1. Add Order and Items
  2. Delete Order
  3. Delete Order Item
  4. Change Item Quantity
  5. Change Item Part
  6. Change Order Customer (reassign Order to a different customer)
  7. Pay the Order

The Database

The database for illustration is a familiar Customer, Order, Item and Product database, described here.

Conventional Implementation

This investigates a conventional approach to the Business Logic for our JSP application that meets the requirements noted above.

Caution: you may think this is a simple problem.  And it should be.  But a quick look may surprise you:
  1. It's a lot of code
  2. It's not just a lot of code: we also need to address several non-trivial design issues
  3. The resultant code presents a number of maintenance challenges
  4. Database integrity is dependent on programmers directly invoking our service code.  Every time.
  5. It's a lot of code

Automated Business Logic Implementation


The Business Logic "Language" - @Logic

Before stating the rules, we need to understand the "language" in which they are specified.  This is not a full language like Java or Groovy.  Nor is it a 4GL.

Instead, you provide @Logic Java/Groovy Annotations, using an expression language for declaring the rules above.  You form expressions as follows:
  • Nouns are your domain Objects
Your logic is declared in terms of the Entities (Domain Objects), Attributes and Relationships of your data model.  These are simply the Hibernate-based Domain Objects as you would provide for any Hibernate project.
  • Verbs are rules (pre-defined, extensible)
You form rule declarations with verbs pre-supplied by Automated Business Logic, shown below.  Your Business Logic expressions (e.g., a formula) can invoke Java methods, enabling you to extend the Business Logic system as explained here.


 Rule        Description  Example

 Formula Derive attribute value using other attributes in that class, or parent class (changes are propagated), including old values.  You can invoke Java/Groovy methods. lineitem.amount = lineitem.partPrice * 
                  lineitem.qtyOrdered
 Parent Copy Derive child attribute value from parent attribute value (changes not propagated)

lineitem.partPrice = @ParentCopy(product.price)

  // existing orders unaffected by Price changes
 Sum Derive parent attribute value by summing designated child attribute, with optional Child Qualification Condition customer.balance = @Sum("purchaseorders.totalAmount
                   where paid = false")

 Count

 
Derive parent attribute value by counting designated child rows, with optional Child Qualification Condition.  purchaseorder.itemCount = @Count(lineitems)
 Constraint Multi-attribute expression of class/parent attributes that must be met for a transaction to succeed (else exception is thrown); can execute as transaction rows are processed, or at commit time after all rows are processed.

customer.balance < customer.creditLimit

             
              
or


purchaseorder.itemCount > 0
 Action Invoke Java/Groovy action (typically from a library of extended rules); can execute during or after row processing

if (employee.baseSalary != employee_old.baseSalary

BusinessLogic.insertChildFrom(  // auditing
    EmployeeAudit.
class
    logicContext)


 AllocationAllocates a provider amount to designated recipients, creating allocation objects (a Provider/Recipient Junction) for each such allocationamountUnDisbursed = BusinessLogic.allocateFromTo(
logicContext,
payment.customer.purchaseorders.findAll{
    it.amountUnPaid > 0},
PaymentPurchaseorderAllocation.class)
 InsertInto Copy one or more source rows to a target class.  Useful for auditing, deep copyIf (employee.baseSalary != employee_old.baseSalary)
BusinessLogic.insertChildFrom(EmployeeAudit.class,
   logicContext) 




The rule language is conceptually similar to a spreadsheet.  Instead of (named) cells, your nouns are your Domain Objects.  Instead of operating in memory, it operates on the disk through Hibernate.  The core concept is that you declare behavior by defining expressions (logic rules), which are "kept true" by the engine.  

Expression Operation

Given rules A = B+C and B = X+Y,

changing X recomputes B
which recomputes A


Conceptually: Business Logic Declarations

We restate here the rules from the Home Page.  The pre-defined rule types are denoted with hyper links (click them to read about the rule).  The code font represents nouns from our domain objects.

  1. Constraint: customer.balance < customer.creditLimit

  2. customer.balance = sum(orders.amountTotal where paid = false)

  3. purchaseorder.amountTotal = sum(lineitems.amount)

  4. Formula: lineitem.amount = lineitem.quantity * lineitem.partPrice

  5. lineitem.partPrice = copy(part.price)

Actual: Business Logic Components / Rules

We build 3 Business Logic Components.  These are classes with a method for each rule.  The classes are named the same as the Domain Class, appended with "Logic", and typically placed in a suitable package:


The screen shot above depicts 2 rules, identified by their annotations:
  1. The Constraint (balance > creditLimit)
          (note: you can simplify the syntax by using Groovy to build Business Logic Components)

  2. the Customer balance 
(note: there is no method code - the rule is entirely expressed in the annotation, which is later executed by the runtime as further described below)


You may wonder how "declarative" logic can be expressed in a procedural language like Java or Groovy.  First, consider the benefits of this approach:

  1. IDE tooling: you get all the benefits of IDE tooling, such as javadoc, syntax coloring, code completion shown above, etc

  2. Extensibility: your Logic methods can invoke Java, so using the IDE enables you to develop, find and manage these in a familiar and consistent manner

  3. Runtime: you have full access to logging and debugging services
As attractive as these benefits are, the real advantage is that your logic is declarative, as described below.



Automated Business Logic Operation

Runtime Engine

Architecture: no recoding

  • No generated code to manage

  • No model to integrate (the model is the class + annotations)

  • No API changes
The Business Logic Architecture is strictly runtime.  There is no code generation, and no model.  It is not dependent on your IDE.

Once you create the Business Logic Component shown above, you simply issue normal Hibernate update commands as illustrated in the sample JSP application.  The Business Logic Engine registers as a Hibernate event, and operates as described in the sub-sections below.  You do not need to alter your code (or framework) - just introduce the Business Logic Components and execute.


Logic Analysis: dependency detection

On first access, the runtime system loads your Business Logic Component and uses byte code analysis to determine rule dependencies, both within the current Domain Object and to related Domain Objects (such as a Sum or Count). 

Transaction Analysis: what really changed

The Business Logic Engine compares your submitted changes to the existing database rows, and determines which attributes are actually changed.  It uses this information during Logic Execution to prune rules that do not need to be fired, thus eliminating any associated SQL overhead.

Logic Execution: execute required logic, Forward Chaining

The relevant (non-pruned) logic relevant to your real changes is executed by:
  1. Running the rules in a dependency-based order

  2. Adjustment / Cascade logic: Forward Chain to related objects
The Logic Analysis "knows" what attributes are referenced by rules in other Domain Objects, so that it can invoke such dependent logic.  Sometimes called Forward Chaining, this enables the automation of multi-table transactions.  While the technology is of course totally different, this is rather spreadsheet-like -- in concept, and in transparency to Business Users.

For example, when you alter the Lineitem.quantity, this triggers an adjustment of the Order.total, which in turn triggers the adjustment of the Customer.balance and the creditLimit Constraint.  Enterprise performance is critical, so we prune the logic for updates where the aggregate is not affected (such as changing notes), and use adjustment logic when Order.total is affected.  

Example: Change Lineitem Quantity

The Business Logic Demo screen at the top provides a good example of logic execution.  If you change a Lineitem Quantity (from 1 to 2), the system processes it as shown below:


  • Logic Analysis

The system determines the following dependencies (list truncated to only those of interest here)

 Attribute  Depends On (bold items indicate actual changes)
lineitem.amount lineitem.quantity, lineitem.partPrice
purchaseorder.amountTotal lineitem.amount, lineitem.purchaseorder
customer.balance purchaseorder.total, purchaseorder.paid, purchaseorder.customer
  • Transaction Analysis

The system determines that the lineitem.amount has changed.  That means that only logic dependent on this (and its effects) needs to be executed.  So, for example, we do not need to retrieve the Product Price - that logic (and its SQL overhead) is pruned.

  • Logic Execution
  1. Lineitem logic recomputes lineitem.amount, per its formula dependency on the changed quantity
  2. Lineitem logic adjusts purchaseorder.amountTotal, per its sum dependency on lineitem.amount. The system now Forward Chains: reads the Purchaseorder, adjusts its amountTotal, and runs its logic...
    1. Purchaseorder logic adjusts the customer.balance, per its sum dependence.  The system reads the Customer, adjusts its balance, and runs its logic...
      1. Customer logic verifies the adjusted balance is within the creditLimit

Key Concept: Multi-Table Forward Chaining

The real key here is step 2.1.  Just as in a spreadsheet, the system Forward Chains any change to dependent derivations.  The critical point here is that this applies to dependencies between Domain Objects.  

Consider the diagram below, depicting the Customer.balance rule.  This depends on all the Purchaseorder attributes noted by the vertical red dotted arrows.  So, any change to any of these Use Cases triggers a change to the Customer's balance:
  1. Insertions and Deletions (balance is incremented / decremented)
  2. Change to Purchaseorder Foreign Key (reassigning a PO decrements the old Customer's balance, and increments the new Customer's balance)
  3. Changes to the summed attribute (amountTotal)
  4. Changes to the qualification condition (marking a Purchaseorder as paid reduces the customer balance)
And it chains: as in a spreadsheet, one derivation can depend on another.  In our example,
  • Customer.balance is dependent on Purchaseorder.amountTotal
  • Purchaseorder.amountTotal is further dependent on Lineitem attributes; changes to them affect the amountTotal, which in turn affects the Customer.balance.
All of this is completely automatic, and is responsive to subsequent changes in your logic dependencies.  This accounts for a substantial portion of the code reduction, and a dramatic reduction in complexity management.




Open Declarative Business Logic: "What", not "how"

Transparency

Business Users can read spreadsheet-like logic, facilitating collaboration with IT.

Unlike Procedural code, Business Logic is declarative.  It is un-code: you don't call it, optimize it, or order it - all these become the systems responsibility.  Not only does this supplant a large amount coding, the Business Logic Engine automates these design activities.

Instead of coding how to do something, you declare what you want to achieve.  As we saw in the example above, you simply specify balance as the sum(purchaseorders.amountUnPaid where isReady = true).  The sub-sections below further investigate the key characteristics of Open Declarative Business Logic.  


Business Logic Power

Open Extensibility enables you to address complex problems.

Open and Extensible

The example above illustrates a simple solution to a simple problem.  While this automation a good start, automation is of little value if it imposes limitations on solving complex problems.

Automated Business Logic is therefore designed to be open and extensible.  Your business logic - formulas, constrains, actions - can invoke Java/Groovy methods.  

We pre-supply several extensions that automated more complex problems (e.g., a Bill of Materials explosion, an allocation of a Payment to a set of Orders, etc), which you can review the Tutorial.  While intended for training, you can simply browse the examples to get an idea of what you can do with these seemingly simple rules.

These examples illustrate how to add your own services to extend the automation of business logic.


Business Agility

Automatic ordering eliminates delays due to manual design/coding effort.
Automatic Ordering

Logic can be chained: 1 rule can depend on another, even across tables.  For example, the Customer balance is a chained aggregate: derivation that sums (refers to) the Purchase Order totalAmount, itself a derivation that sum Line Item amounts.  And, it must be evaluated before the Credit Limit Check.  So these must all be executed in the proper order to produce the correct result.

When your Business Logic Component is first loaded, the Business Logic Engine invokes the Dependency Analyzer to determine a proper order of execution. Your rules can be specified in any order within your Business Logic Component.


Re-use

Automatic re-use guarantees integrity.

Re-use is not just code, but logic.

Automatic Re-use

Re-use is rightly regarded as a high-priority design goal, since it can minimize code and (in the case of business logic) promote integrity.  It often requires substantial design effort, and in many cases requires explicit calls (e.g, to Service Routines).

By contrast, your business logic is re-used automatically when you issue normal Hibernate updates (recall the Business Logic Engine operates as a Hibernate Event).  Moreover, this re-use is not at the level of code (there really isn't any), but at the level of design intent.

As we saw above for the Customer.balance rule, you supply no code, merely a declarative end-condition.  And while it may have been conceived for the Place Order Use Case, it is automatically applied to all the Use Cases listed above.  

This is a much higher level of re-use than code.  It is a dramatic increase in the level of abstraction: powerful enough to solve complex problems, yet transparent to Business Users.  It eliminates an entire class of coding and design error.


Architecture: Performance

Automatic optimizations eliminate / reduce SQL access.

Automatic Optimization

The Business Logic Engine is architected to Minimize/Eliminate SQL overhead.

    • Pruning: the Business Logic Engine Transaction Analyzer analyzes updates, and avoids parent access, adjustment and cascade when the referenced data is not changed 

    • Adjustment Logic: maintains aggregates with a single-row update SQL
Unlike Rete Business Rule Engines that load all the data into memory, or issue aggregate Select sum queries, this assures optimal performance. This is particularly important when there are chained aggregates



Using Automated Business Logic





The following video provides an overview of the architecture and use of Automated Business Logic.

See the sub-sections below for further information.








Activating Business Logic - no code changes required

Recall BusLogicDemo was first developed using a Traditional Approach.  You will find the manual logic code in buslogicdemo.data.manual.

Activating / altering Business Logic did not require changes to our JSP code for retrieving and updating data.  The only requirements are shown in the screen shot below (use this same procedure to add business logic to your own projects):
  1. Register the session manager, by add a line to our Hibernate Config file as shown below for buslogicdemo.cfg.xml 

  2. Define 3 the Business Logic Component classes (CustomerLogic shown below)




The rest of the application is standard Java, Hibernate and JSP.


Changing and Debugging Business Logic


Explore / Modify Bus Logic Demo

Utilizing Business Logic

We did not have to alter our JSP code.  The only requirements were 
  • define 3 the logic classes

  • add a line to our Hibernate Config file
BusLogicDemo is provided so you can explore - and alter - business logic.  The screen shot below shows the 3 Business Logic Components that declare the logic.  (Note that we are using the Navigator view -- activate this view via Window > Show View > Navigator).

It is easy to alter the logic: 
  1. Stop Tomcat

  2. Modify your logic (e.g., change the error message for the Constraint, as shown in the screen shot below)

  3. Redeploy the artifacts to the Tomcat server

  4. Restart the server and run the application to observe the effects


Exploring

This video uses this sample to investigate: 
  • How to configure Hibernate to activate Business Logic

  • System architecture and operation

  • How you can declare and debug logic



Changing Logic; Logic debugging and logging


You may have noticed you can alter lineitems in orders that are already paid.  A good example of adding logic would be to prevent this.  Let's see how.

Using the change procedure used above, make the change shown at right (click the image for full screen view):

  1. Making the change:
  2. Logic Debugging - the screen shot illustrates:
  • Debugger: observe setting a breakpoint (line 28) enables us to stop in our logic, and inspect our data (see the upper right display for old/new order data)

  • Logging: note the last line in the log (very bottom) illustrates our current logic execution, where we can also see our old/new values (highlighted areas) as they will be seen by our logic.  The logging is quite extensive (it can of course be suppressed).
The log shown in the screen shot reveals much about how Business Logic works.  First, let's review the context:

In this transaction, the End User has altered a Lineitem.qtyOrdered for a paid Purchaseorder.  The system detects that this is a change to the summed attribute Purchaseorder.amountTotal, so it adjusts the parent Purchaseorder object (where we are stopped now).

Salient points:
  • Forward Chaining (where the Lineitem changes result in Purchaseorder Logic execution) are the key in automating sophisticated multi-row transactions

  • Performs well since it avoids aggregate queries, or bringing all the child data into memory. 



Maintenance Automation

Maintenance Automation




All of the above processing is repeated every time you make a change:
  • re-use
Since you don't directly invoke the logic, it automatically applies to all client code
  • re-ordering
Unlike manual systems where you must re-order your logic, this is performed automatically through Logic Analysis
  • re-optimization
Unlike manual systems that often degrade over time due to the costs of re-optimization, Business Logic is automatically re-optimized on each change, so performance remains high.  So, for example, you can alter the "stored vs computed" decision instantly, in contrast to the quandary incumbent in the procedural approach.



Next Steps

We hope this has shown how you use business logic, and how it works.  We also hope it has shed some light on how this delivers value:
  • Agility - by dramatic code reduction, and automation of design elements such as re-use and optimization

  • Transparency - declarative logic is expressed in spreadsheet-like expressions, understandable to Business Users

  • Power - logic is extensible via Java/Groovy you can add

  • Architecture - runtime services automate performance to reduce/eliminate SQL, automate re-use for integrity, and is easy to adopt since it requires no programming changes, generated code or IDE support

We suggest you download a version.  It works on a PC, Mac or Unix, runs in Eclipse (or your favorite IDE), and is bundled with a version of HSQL (so you don't need to download/install a database).  You can:
  • Run the demo shown here

  • Review its code, and tweak it

  • Build your own Business Logic for the demo (simulating a project)

  • And proceed to build Business Logic for your own projects to show your team

You can also review this site to understand the capabilities / operation of Automated Business Logic:
  • Demo - contrasts simple problem solution (manual vs. automated), with basic of system operation

  • FAQ - common questions

  • Architecture - the pieces and how they fit

  • Tutorial - browse this to see how typical / complex problems can be automated

  • Overview - summarizes the product

  • Downloads - explains how to install, run the sample, alter the sample, and add logic to your own project