Doc Center‎ > ‎Samples‎ > ‎

Samples - XML Logic Manager

This sample consists of a Logic Manager that reads the business logic from XML files instead of Java class files.

This logic manager parses the XML files, generates a Java file on the fly, compiles it, and feeds it to ABL.

If any XML files are created, updated or deleted while the ABL engine is running, all the logic is automatically reloaded.

Installation

Installation simply requires that the jar for this sample be available in the class path, and that the following be set in ABLConfig.properties:

logicClassManager1 = com.autobizlogic.dynlog.XMLLogicClassManager
logicClassManager1_directory = /Users/jdoe/MyApp/logic

The first line is the name of the logic manager, and should not be changed (unless you subclass it).
The second line is the directory where the XML files can be found (not required if you use file-less logic loading -- see below). Note that the names of the XML files is actually not important -- they can be named anything, as long as the name ends in .xml

Each XML file should follow the following syntax:

<?xml version="1.0" encoding="UTF-8"?>
<LogicUnit entityName="com.acme.data.Customer">
    <!-- One or more logic definitions here -->
</LogicUnit>

The logic definitions are as follows:

Sum, Minimum and Maximum

<Sum 
beanAttributeName="balance"
roleName="purchaseorders"
childAttributeName="amountTotal"
qualification="paid = false"
/>

Replace Sum with Minimum or Maximum as needed. 
The beanAttributeName is the name of the attribute in the persistent class that should be computed by this aggregate.
The qualification attribute is optional.

Count

<Count
beanAttributeName="numUnpaidOrders"
roleName="purchaseorders"
qualification="paid = false"
/>

The qualification attribute is also optional here.

Formula

<Formula 
beanAttributeName="amount"
expression="productPrice * qtyOrdered"
/>

ParentCopy

<ParentCopy
beanAttributeName="productPrice"
roleName="product"
copiedAttributeName="price"
/>

Constraint

<Constraint
expression="balance &lt;= creditLimit"
errorMessage="Balance {balance} exceeds credit limit for customer {name}"
name="checkCreditLimit"
>
<ProblemAttribute>balance</ProblemAttribute>
<ProblemAttribute>creditLimit</ProblemAttribute>
</Constraint>

The errorMessage attribute is optional, as are the ProblemAttribute sub-elements.
The name attribute is also optional but recommended -- if not specified, the constraint method will be assigned a generated name.

Class path

When running in a managed environment (like Tomcat), it is common for the compiler's classpath to not include the classes used in the application, such as the ABL classes. The symptom for this is an error such as:

null:3: package com.autobizlogic.abl.annotations does not exist
import com.autobizlogic.abl.annotations.*;
^
null:6: cannot find symbol
symbol  : class Formula
location: class com.autobizlogic.dynlog.generated.LineitemLogic
@Formula("productPrice * qtyOrdered")
^

This indicates that the ABL classes must be added to the compilation classpath. To do so, you can simply edit your ABLConfig.properties file to look like:

logicClassManager1 = com.autobizlogic.dynlog.XMLLogicClassManager
logicClassManager1_directory = /Users/jdoe/MyApp/logic
logicClassManager1_classpath = /Users/jdoe/MyProject/jars/autobizlogic-2.1.10.jar

Note that the classpath is passed directly to the compiler; you could therefore add more entries to it, as long as they're separated by the proper delimiter for your platform (colon : on Unix/Mac, and semicolon ; on Windows).

Loading logic without files

As of version 2.1.12, it is also possible to load logic into this logic class manager without the use of files.

The first step requires you to get a hold of the XML logic manager, for instance:

LogicEngine engine = LogicEngineManager.getEngineForEntityManager(em);
List<LogicClassManager> lcms = engine.getClassLoaderManager().getLogicClassManagers();
XMLLogicClassManager xmlLcm = null;
for (LogicClassManager lcm: lcms) {
if (lcm instanceof XMLLogicClassManager) {
xmlLcm = (XMLLogicClassManager)lcm;
break;
}
}
if (xmlLcm == null)
throw new RuntimeException("Unable to find XML logic class manager");

You can then feed some new logic into it using code like:

String code = ...   // Can be generated, retrieved from a file, etc...
xmlLcm.addXmlLogic("com.acme.data.Customer", code);
// Keep adding logic as required, then...
xmlLcm.commitLogic();

Note that the code supplied to addXmlLogic() must be a properly formatted LogicUnit chunk of XML.

When logic is loaded this way, it is first staged when you call addXmlLogic(), but it does not take effect until you call commitLogic().

Logic added using addXmlLogic() is cached for the lifetime of the XML logic manager. This means that, if you call LogicEngine.reset(), the logic previously added using addXmlLogic() will be re-activated as soon as you call commitLogic().

You can remove this logic by calling removeXmlLogic(), e.g.:

xmlLcm.removeXmlLogic("com.acme.data.Customer");


Comments