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:
- 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.
- 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:
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.
No Logic is dependent on this change, so logic / SQLs are pruned - a 1 row update proceeds.
product for Line Item
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
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
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:
- Constraint: balance < creditLimit
- balance = sum(orders.total where paid = false)
- order.total = sum(lineitems.amount)
- lineitem.amount = quantity * partPrice
- lineitem.partPrice = copy(part.price)
The User Interface above obligates us to build the following Use Cases (or Function Points):
- Add Order and Items
- Delete Order
- Delete Order Item
- Change Item Quantity
- Change Item Part
- Change Order Customer (reassign Order to a different customer)
- Pay the Order
The database for illustration is a familiar Customer, Order, Item and Product database, described here.
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:
- It's a lot of code
- It's not just a lot of code: we also need to address several non-trivial design issues
- The resultant code presents a number of maintenance challenges
- Database integrity is dependent on programmers directly invoking our service code. Every time.
- 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.
||Derive attribute value using other attributes in that class, or parent class (changes are propagated), including
old values. You can invoke
lineitem.amount = lineitem.partPrice *
| Parent Copy
||Derive child attribute value from parent attribute value (changes not propagated)
lineitem.partPrice = @ParentCopy(product.price)
// existing orders unaffected by Price changes
||Derive parent attribute value by summing designated child attribute, with optional Child Qualification Condition
where paid = false")
|Derive parent attribute value by counting designated child rows, with optional Child Qualification Condition.
purchaseorder.itemCount = @Count(lineitems)
||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.creditLimitor
purchaseorder.itemCount > 0
||Invoke Java/Groovy action (typically from a library of extended rules); can execute during or after row processing
BusinessLogic.insertChildFrom( // auditing
| Allocation||Allocates a |
provider amount to designated
allocation objects (a Provider/Recipient Junction) for each such allocation
amountUnDisbursed = BusinessLogic.allocateFromTo(
it.amountUnPaid > 0},
| InsertInto|| Copy one or more |
source rows to a
target class. Useful for auditing, deep copy
If (employee.baseSalary != employee_old.baseSalary)
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.
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.
customer.balance = sum(
paid = false)
purchaseorder.amountTotal = sum(
lineitem.quantity * lineitem.partPrice
lineitem.partPrice = copy(
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:
- The Constraint (balance > creditLimit)
(note: you can simplify the syntax by using Groovy to build Business Logic Components)
- 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:
- IDE tooling: you get all the benefits of IDE tooling, such as javadoc, syntax coloring, code completion shown above, etc
- 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
- 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
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:
- Running the rules in a dependency-based order
- 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
, this triggers an adjustment of the
, which in turn triggers the adjustment of the
Constraint. Enterprise performance
is critical, so we prune
the logic for updates where the aggregate is not
affected (such as changing
), and use adjustment logic
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:
The system determines the following dependencies (list truncated to only those of interest here)
|| Depends On (bold items indicate actual changes)
|purchaseorder.total, purchaseorder.paid, purchaseorder.customer
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.
- Lineitem logic recomputes lineitem.amount, per its formula dependency on the changed
- 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...
- Purchaseorder logic adjusts the customer.balance, per its sum dependence. The system reads the
Customer, adjusts its
balance, and runs its logic...
- Customer logic verifies the adjusted
balance is within the
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:
- Insertions and Deletions (balance is incremented / decremented)
- Change to
Purchaseorder Foreign Key (reassigning a PO decrements the old Customer's balance, and increments the new Customer's balance)
- Changes to the summed attribute (
- Changes to the qualification condition (marking a Purchaseorder as paid reduces the customer
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
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"
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.
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.
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.
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.
- 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
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
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):
- Register the session manager, by add a line to our Hibernate Config file as shown below for
- 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
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:
- Stop Tomcat
- Modify your logic (e.g., change the error message for the Constraint, as shown in the screen shot below)
- Redeploy the artifacts to the Tomcat server
- Restart the server and run the application to observe the effects
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:
- 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).
- 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.
All of the above processing is repeated every time you make a change:
Since you don't directly invoke the logic, it automatically applies to all client code
Unlike manual systems where you must re-order your logic, this is performed automatically through Logic Analysis
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.
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