Control Utils
Essential knowledge
Intended Audience:
Technical User
Authors:
Holger Lierse, Kirill Gaiduk
Changed on:
24 Aug 2026
Overview
`ControlUtils` is the entry point of the Controls Utilities bundle. This page is the API reference for applying controls to a position from a rule.For the underlying concepts (control, control group, bulk vs position-level control) see Controls Utilities Overview. For the order in which the `ControlUtils` resolves and applies controls, and the behavior of the caches, see the Detailed Technical Description on the Controls Utilities package page.Key points
- Specificity-aware: position/product/variant-level controls take precedence over group-level (bulk) controls
- Auditable:
`ControlUtils`records every applied control with a before/after snapshot - Extensible: the position source and the set of control functions are both parameters you can supply
Applying Controls to a Position
`applyControls(context, inventoryCatalogueRef, inventoryPositionRef)`
The convenience overload. Loads the position with the default position supplier and applies the default set of control functions. Use this when the position maps one-to-one to the triggering event.1// applyControls (convenience)
2ControlUtils.PositionUpdateResult result =
3 ControlUtils.applyControls(context, inventoryCatalogueRef, inventoryPositionRef);`applyControls(context, positionSupplier, controlFunctions)`
Applies the given control functions to the position produced by `positionSupplier`. Use this to control where the position comes from (for example, an aggregate across locations) and which control functions run.1// applyControls (custom supplier and functions)
2ControlUtils.PositionUpdateResult result = ControlUtils.applyControls(
3 context,
4 ControlUtils.defaultPositionSupplier(context, inventoryCatalogueRef, inventoryPositionRef),
5 ControlTypes.buildControlFunctions()
6);`applyControls(context, positionSupplier, controlFunctions, defaultControls)`
Like the previous overload, but the `ControlUtils` adds `defaultControls` to the loaded controls where a control of that type is not already present. Use this to guarantee a baseline of behavior when no matching control exists.`applyControlsWithDefaultBehavior(context, positionSupplier, controlFunctions)`
A shorthand for the overload above that supplies `ControlTypes.DEFAULT_THRESHOLD_CONTROL_ACTIVE` as the default control, so a position with no matching threshold control defaults to `ACTIVE`.1// applyControlsWithDefaultBehavior
2ControlUtils.PositionUpdateResult result = ControlUtils.applyControlsWithDefaultBehavior(context,
3 ControlUtils.defaultPositionSupplier(context, inventoryCatalogueRef, inventoryPositionRef),
4 ImmutableList.of(ControlTypes.CONTROL_FUNCTION_THRESHOLD));Position Suppliers
A position supplier is a`Supplier<Position>` that tells `applyControls` which position to operate on. `ControlUtils` provides two.`defaultPositionSupplier(context, inventoryCatalogueRef, inventoryPositionRef)`
Loads a single inventory position and enriches it with the standard related product and location information.`aggregatePositionSupplier(...)`
Produces a single position whose `quantity` is the sum of on-hand across multiple locations, for a product. `ControlUtils` provides three variants:`aggregatePositionSupplier(context, inventoryCatalogueRef, productRef, activeStatuses)`
aggregates the positions passed to it, counting only those whose status is in`activeStatuses`.`aggregatePositionSupplier(context, inventoryCatalogueRef, productRef, networkRef, activeStatuses)`
aggregates across every location in the given network.`aggregatePositionSupplier(context, inventoryCatalogueRef, productRef, locationSupplier, activeStatuses)`
aggregates across the locations returned by a custom`locationSupplier`.
1// applyControls with an aggregate supplier
2ControlUtils.PositionUpdateResult result = ControlUtils.applyControls(context,
3 ControlUtils.aggregatePositionSupplier(
4 context,
5 inventoryCatalogueRef,
6 productRef,
7 ImmutableList.of("ACTIVE")
8 ),
9 ControlTypes.buildControlFunctions()
10);`locationsByNetworkSupplier(context, networkRef)`
Returns a `Supplier<List<LocationReference>>` of the locations in a network. Pass it to the `locationSupplier` variant of `aggregatePositionSupplier` when you want to aggregate over a network but supply the locations yourself.Supplying Custom Control Functions
The control functions passed to`applyControls` determine which control types `ControlUtils` recognizes and how each applies. `ControlTypes.buildControlFunctions()` returns the standard set; pass your own list to add or override behavior. The example below assumes you have statically imported the relevant members of `ControlTypes` (`ControlFunction`, `CONTROL_FUNCTION_*`, `appliesToPosition`, `EXCLUSION_TYPE`):1// applyControls with custom control functions
2ControlUtils.applyControls(context,
3 ControlUtils.defaultPositionSupplier(context, inventoryCatalogueRef, inventoryPositionRef),
4 ImmutableList.of(
5 CONTROL_FUNCTION_INCLUSION,
6 // Override the default EXCLUSION control function
7 new ControlFunction(20,
8 (position, control) -> control.getType().endsWith(EXCLUSION_TYPE) && appliesToPosition(position, control),
9 (position, control) -> position.update("INACTIVE").update(0)
10 ),
11 CONTROL_FUNCTION_BUFFER
12 // Optionally add more here
13 )
14);The Result: `PositionUpdateResult`
Every overload returns a `PositionUpdateResult`:`getPosition()`- the updated position (`status`and`quantity`after all controls were applied).`getPositionBefore()`- the original position, before any control was applied.`getAudit()`- an ordered list of`PositionUpdate`entries, one per applied control.`getMessage()`- a human-readable summary, for example`"2 controls were applied"`.
`PositionUpdate` in the audit exposes `getBefore()`, `getAfter()` and `getControl()`, giving the position on either side of that single control and the control that applied the change.