Dependent Logic: Use Configurable Variable Annotation to Prevent Premature Default Assignment
Use the configurable variable annotation on a target attribute to prevent the engine from assigning a default value before your calculation and preference rules execute.
To ensure preference rules correctly set target attributes based on calculated values, use the @(configurable=false) annotation on the target attribute. This prevents a race condition where the engine assigns a default value during initialization before your calculation and preference rules execute.
When an inline expression is used, CML evaluates the model top-down. If the target attribute is declared before the inline calculation, the engine immediately assigns a default value to the attribute. As a result, any subsequent preference() rules are ignored because the engine treats the existing default value as an established selection and avoids overwriting it with the calculated value. Annotating the target attribute with @(configurable=false)) forces the engine to leave the variable as null until the calculation and preference rules are executed.
In this example, the engine processes ShippingMethod first and immediately assigns the default value “Standard” to it. Later, when the calculation for totalWeight returns a value high enough to require the “Freight” shipping method, the engine ignores this preference rule because the ShippingMethod variable is already bound to “Standard”.
1type Order : LineItem {
2 int quantity = [1..100];
3 int weightPerUnit = [10..50];
4
5 // Problem: Engine assigns "Standard" immediately during initialization
6 @(defaultValue = "Standard")
7 string ShippingMethod = ["Standard", "Freight"];
8
9 // Calculated Attribute via Inline Expression
10
11 // The calculation happens after the default is already set
12 int totalWeight = quantity * weightPerUnit;
13
14 // This rule is ignored because ShippingMethod is already bound to "Standard"
15 preference(totalWeight > 1000 -> ShippingMethod == "Freight");
16}
In this example, using the @(configurable=false) annotation ensures the ShippingMethod attribute remains as null until the calculation completes and the rules execute.
Provide a second preference rule for the fallback condition (else) to ensure a value is always set.
1type Order : LineItem {
2 int quantity = [1..100];
3 int weightPerUnit = [10..50];
4
5 // Solution: Prevent premature default assignment
6 @(configurable=false)
7 string ShippingMethod = ["Standard", "Freight"];
8
9 // Calculated Attribute via Inline Expression
10 int totalWeight = quantity * weightPerUnit;
11
12 // Rule 1: Handle the specific condition (high weight)
13 preference(totalWeight > 1000 -> ShippingMethod == "Freight");
14
15 // Rule 2: Handle the fallback (low weight)
16 preference(totalWeight <= 1000 -> ShippingMethod == "Standard");
17}