Fluent Commerce Logo
Docs

Fluent Commerce Utility Bundles: An Overview

Essential knowledge

Intended Audience:

Technical User

Authors:

Kirill Gaiduk, Yulia Andreyanova, Ben Harrison

Changed on:

12 June 2025

Overview

Prerequisites

Key points

  • Focus on Business Logic: The libraries handle common, repetitive tasks (like data fetching and JSON conversion), allowing developers to concentrate on writing the business logic that delivers value.
  • Three Specialized Bundles: The utilities are organized into three modules: `util-core` for essential daily tasks, `util-dynamic` for building runtime queries, and `util-test` for simplifying testing.
  • Easy Upgrades: Receive bug fixes and new features from Fluent Commerce by simply updating the dependency version in your `pom.xml`, ensuring your implementation stays current.
  • Built for Extensibility: The utilities are designed to be flexible, allowing you to inject your own custom logic into standard processes.
The Fluent Commerce Utility Bundles are a powerful set of libraries designed to accelerate rule development, reduce boilerplate code, and improve the overall quality of your implementation. They are the cornerstone of writing maintainable, reusable, and easily upgradeable rules on the Fluent platform.

The Design Philosophy: From Source Code to Building Blocks

Historically, customizing Fluent Commerce rules often required partners to modify the rule's source code directly. While this offered flexibility, it made upgrades difficult. A bug fix or performance improvement from Fluent Commerce would require a manual, time-consuming code merge.The Utility Bundles represent a shift in this approach. Instead of providing complex rule source code, Fluent now provides a set of powerful, reusable building blocks. The core logic for common tasks is extracted into these utility libraries.This has two major benefits:
  • Simpler Rules: Your rules become much cleaner and more focused on the business logic, as the overhead of data fetching, transformation, and action creation is handled by the utilities.
  • Effortless Upgrades: You can receive new features, bug fixes, and performance improvements by simply updating the utility dependency version in your `pom.xml`. No more manual merging.

Breaking Down a Rule: How Utilities Help

Most rules follow a similar structure. The utility libraries provide helpers for each step of the process, designed with specific principles in mind.

1. Validation

Utilities help check that inputs are correct so the rule can exit early if there's nothing to do. The key principle is understanding what to validate and when:
  • Rule Properties: These don't change at runtime, so their validation should be handled by workflow unit tests, not runtime checks. `RuleUtils` helps retrieve them safely.
  • Event Attributes: These do change at runtime, so they are excellent candidates for validation within a utility. For rich types, the best approach is to map the attribute directly to a POJO using `JsonUtils`.

2. Data Fetching

Utilities provide helpers for common data-fetching use cases. The goal is not just to expose raw data, but to provide data that is ready to be used.
  • Think Usage: For example, instead of a generic `getOrder(context)` method that would require every rule to then filter out already fulfilled items, a better utility is `getUnfulfilledItems(context)` which does that logic for you.

3. Business Logic

This is where your unique logic lives. The utilities are designed to support this with a key principle in mind: extensibility.
  • Pass in Functions: A powerful pattern used in the utilities is allowing developers to pass in their own functions to override or extend default behavior. For example, a utility that finds the best fulfilment plan might accept a custom scoring function as a parameter. This makes the utilities flexible building blocks rather than rigid, black-box solutions.
  • Identify Archetypes: The utilities are often built to support common rule "archetypes," such as "Flow Control" rules that conditionally send events, or domain-specific ones like "Fulfilment Strategy" rules.

4. Actions

Utilities help build and produce the outcome of the business logic, especially for complex actions like mutations.
  • Convert Logic to Actions: For example, if a business logic utility returns a list of proposed fulfilments, another utility can take that list and turn it into the required set of `updateFulfilment` mutations.

Why Use Utility Bundles?

  • Accelerate Development: Handle common tasks like date formatting, JSON conversion, and event forwarding with single lines of code.
  • Improve Code Quality: Leverage pre-built, tested functions that handle common error scenarios and edge cases.
  • Simplify Maintenance: Update a utility function in one place, and the change is reflected everywhere it's used.
  • Easy Upgrades: Stay current with the latest features and bug fixes from Fluent Commerce by simply updating the dependency version in your `pom.xml`.

The Utility Bundles

The utilities are organized into three distinct modules, each serving a specific purpose. Fluent Commerce will continue to release more utilities over time to cover more common order and inventory functionality.

Core Utilities

The foundational library containing essential helpers for everyday development tasks. If you are building rules on the Fluent platform, you will be using this bundle. It handles common tasks like event creation, setting retrieval, and JSON manipulation so you can focus on business logic.
  • Key Classes`EventUtils``SettingUtils``QueryUtils``RuleUtils``JsonUtils`.

Dynamic Utilities

This package offers utilities to generate GraphQL queries and mutations at runtime. This is crucial for scenarios where the data you need to fetch or update is not known until the rule is executed, enabling more flexible and configurable rule creation across different domains.

  • Key Classes`DynamicUtils`, an advanced `JsonUtils`.

Test Utilities

A dedicated toolkit for writing robust unit and integration tests. It provides mock executors, context generators, and other helpers to simplify and standardize the process of testing your rules, saving you significant time and effort.
  • Key Classes`RuleExecutor``WorkflowExecutor``MockApiClient`.

A Practical Example: Tracking Status History

This example shows how utilities work together to implement a common requirement: tracking how long an entity spends in each status.
1@RuleInfo(name = "UpdateStatusHistory", /*...*/)
2public class UpdateStatusHistory implements Rule {
3
4    // A POJO to represent the entity fields we need
5    // With @Data, 'private' is redundant
6    @Data
7    public static class EntityData {
8        String createdOn;
9        String status;
10        List<Attribute> attributes;
11    }
12
13    @Override
14    public void run(Context context) {
15        // 1. DATA FETCHING: Use DynamicUtils to get only the fields we need
16        EntityData entity = DynamicUtils.query(context, EntityData.class);
17        
18        // Find the existing history attribute from the entity's attributes
19        // (Logic to find attribute by name is omitted for brevity)
20        Optional<Attribute> historyAttribute = findHistoryAttribute(entity.getAttributes());
21        
22        // 2. BUSINESS LOGIC: Deserialize old history, calculate time, add new entry
23        // The list of previous status updates is retrieved from the attribute using JsonUtils
24        List<StatusUpdate> history = getHistoryFromAttribute(historyAttribute);
25        long durationInPreviousStatus = calculateDuration(history, entity.getCreatedOn());
26        history.add(new StatusUpdate(entity.getStatus(), /*...*/));
27        
28        // 3. ACTIONS: Use DynamicUtils to persist the updated attribute list
29        Attribute updatedAttribute = createHistoryAttribute(history);
30        DynamicUtils.mutate(
31            context,
32            ImmutableMap.of("attributes", Collections.singletonList(updatedAttribute))
33        );
34    }
35}