Fluent Commerce Logo
Docs

How Dynamic Utilities work

Topic

Author:

Kirill Gaiduk

Changed on:

10 July 2025

Overview

The articles below will walk you through the Dynamic Utilities (`dynamic-core`), designed to simplify rule development and reduce repetitive code.PrerequisitesBefore diving in, make sure you have:

Dynamic Utilities Overview

Author:

Kirill Gaiduk

Changed on:

11 Nov 2025

Overview

The `util-dynamic` library is a collection of utility functions that allow you to generate GraphQL queries and mutations at runtime. This enables the creation of highly configurable and reusable rules that can adapt to different needs without requiring code changes.PrerequisitesThese articles assumes you're familiar with:
  • Java
  • Maven
  • JUnit

Key points

  • Dynamic Queries: Fetch any field from an entity at runtime by providing a POJO class that defines the desired data structure, eliminating the need for pre-compiled queries.
  • Dynamic Mutations: Update any field on an entity by passing a simple `Map` of key-value pairs, allowing for the creation of generic "field setter" rules.
  • Dynamic Connections: Easily query and iterate over paginated one-to-many relationships (like `order.items`), as the utility handles all the pagination logic for you.
  • Advanced JSON Path: A powerful `getJsonPath` method that can retrieve data from either the event or the entity itself, automatically determining the correct source.
  • Enhanced JSON Utilities: This bundle includes a more advanced `JsonUtils` with powerful methods for navigating and transforming complex JSON structures.

Value Proposition

The primary value of the Dynamic Utilities is flexibility.
  • Configurable Rules: Workflow designers can change what data a Rule fetches or updates by modifying Rule properties, without needing a developer to write and deploy new code.
  • Reusable Logic: You can create a single, generic rule (e.g., "SetEntityField") that can be used across many different entity types and scenarios, reducing code duplication.
  • Adaptive Workflows: Build workflows that can adapt to different conditions at runtime by dynamically querying or updating the data that matters most in a given context.

Apollo Android Context

The Fluent Rules SDK relies on Apollo Android to execute GraphQL queries. Apollo's method of pre-compiling queries into Java classes:
  • Enhances type safety 
  • And boosts performance
However, it also has drawbacks: 
  • Pre-compiled queries restrict Workflow designers from dynamically accessing or updating data, as they require new queries to be developed and compiled each time. 
  • Additionally, the pre-compilation process limits the ability to create universal Rules that apply similar logic across different entity types. 
The Dynamic Utilities work around these limitations and enhance Rule configurability.

Explanation through an Example

Here's how Dynamic Utilities solve the Apollo limitation by creating a single, reusable rule that can update any field on any entity:

Dynamic Queries and Utils

Author:

Kirill Gaiduk

Changed on:

12 Nov 2025

Overview

`DynamicEntityQuery`, with the help of the `DynamicUtils` class, automatically derives the correct GraphQL query operation for the primary Entity from the `RulesetContext`. It dynamically retrieves fields related to that Entity, removing the need for pre-compiled queries while preserving type safety and performance.

Key points

  • Runtime Query Generation: Automatically builds GraphQL queries at runtime based on entity context, eliminating pre-compiled queries.
  • Dual Usage Patterns: Type-based mapping with POJO classes for strong typing, or path-based queries for maximum flexibility.
  • Universal & Validated: Works across different entity types with automatic schema validation and connection pattern handling.
  • Flexible Access: Results accessible as typed objects, JsonNode, or flattened maps with Lombok integration.
  • Connection Handling: Built-in support for paginated connections with automatic pagination handling via `queryList()` methods.
  • Dynamic Mutations: Update entity properties dynamically using key-value pairs without pre-compiled mutation queries.
  • Unified Data Access: `getJsonPath()` method provides unified access to both event and entity data using consistent path syntax.

Key Advantages Over Traditional Apollo Queries

  • One Query, Many Types
    `DynamicEntityQuery` allows a single query to be applied across different entities, especially those with common interfaces, removing the need for individual, pre-compiled queries for each entity type. This flexibility reduces the need for branching logic within rules, which can be a major source of inefficiency.
    For example, the `ChangeStateGQL` rule became outdated quickly whenever new entity types were introduced. Therefore the `SetState` was introduced which is entity type agnostic and therefore provides more flexibility.
  • Runtime Query Building
    `DynamicEntityQuery` supports building queries at runtime rather than relying solely on pre-compilation. This means that a rule can dynamically determine which data it requires based on parameters or other runtime information.
  • Reduced Maintenance
    No need for individual pre-compiled queries for each entity type, eliminating the overhead of maintaining separate query files and reducing the risk of inconsistencies.

Core Components

  • `DynamicUtils`: The main utility class that provides a simplified API for all dynamic operations:
    • Query Operations: Type-based and path-based querying
    • Connection Handling: Paginated data retrieval
    • Mutations: Dynamic entity updates
    • Data Access: Unified event and entity data access
  • `DynamicEntityQuery`: The underlying query builder that generates GraphQL queries from:
    • POJO class definitions (type-based)
    • Path specifications (path-based)
    • Query parameters and filters
  • `DynamicDataTypes`: Provides the response handling mechanisms:
    • `QueryDynamicData`: Wrapper for query results with type conversion
    • `QueryDynamicVariables`: Variable handling for parameterized queries

Here is a collection of common scenarios for the Dynamic Queries usage:

Type-based usage

To generate a dynamic query from a strongly typed Java class, `DynamicUtils.query()` recursively derives a query based on the fields defined within the class and then executes the query. The resulting object is automatically marshaled back into the same class.

Example 1: Entity Fetching Query

Example 2: Fulfillment Fetching Query

Benefits:
  • Type Safety: Strongly typed results with automatic marshaling
  • Lombok Integration: Use Lombok to reduce boilerplate code
  • Field Mapping: Only the fields within the class are used for marshaling
  • Simplified API: `DynamicUtils.query()` handles the complexity of query execution and type conversion

Alternative Direct API Usage

If you need more control over the query execution, you can use the direct API:

Path-based usage

Path-based queries allow you to define your query as a series of strings, where each string represents a dot-separated path through the data graph. This approach is highly flexible and enables the creation of rules that adapt seamlessly to multiple entity types and fields.

Example 1: Multiple-Fields Query

These paths would generate a GraphQL query that retrieves only the specified fields:The library uses GraphQL schema introspection to ensure that each generated path aligns with valid schema fields; any invalid or mismatched paths are automatically excluded, ensuring that only valid data is queried.The resulting `DynamicEntityQuery.DynamicData` object can be accessed either as a Jackson `JsonNode` for structured JSON handling or flattened into a map of graph selectors to `JsonNode` values for quick lookup.

Example 2: Single-Field Query

You can also use `DynamicUtils.query` to retrieve a single field value directly from the entity:Benefits:
  • Automatic Connection Handling`items.product.name` automatically expands to `items.edges.node.product.name`
  • Schema Validation: Uses GraphQL introspection to ensure valid paths
  • Flexible Access: Results can be accessed as `JsonNode` or flattened map
  • Error Prevention: Invalid paths are automatically excluded

Connection Queries (Pagination)

For handling paginated connections like `items`, `fulfilments`, etc., use the `queryList()` methods:

Example 1: Specific Fulfillments Loading

Example 2: Order Fulfillments Loading

Example 3: Fulfillment Articles Loading

Dynamic Mutations

The `DynamicUtils.mutate()` method allows you to update entity properties dynamically:

JSON Path Access

The `getJsonPath()` method allows you to access data from either the event or entity using a unified path syntax:

Complete Examples

Example 1: Attribute Checking Rule

This rule loads attributes associated with an order and checks if a specified attribute exists:

Example 2: Flexible Property Comparison

This rule compares a parameter value against an arbitrary field of the primary entity:


Dynamic Mutations

Author:

Kirill Gaiduk

Changed on:

10 July 2025

Overview

`DynamicUpdateMutation` automatically derives the correct update Mutation for the primary Entity based on the `RulesetContext` and then performs the update on one or more fields.

Key points

  • Automatic Mutation Selection: GraphQL mutations are automatically selected from the `RulesetContext` based on entity type.
  • Flexible Field Updates: Update single fields or multiple fields in bulk using simple key-value pairs.
  • Type-Based Safety: Use POJO classes for strongly-typed updates with automatic field derivation.
  • Runtime Validation: Built-in validation ensures only valid fields are included in mutations.
  • Universal Application: Works across different entity types without requiring entity-specific mutation code.
Here is a collection of common scenarios for the Dynamic Mutations usage:

Field-based Updates

Fields can be updated directly by name. You can:
  • Update a single field 
  • Provide multiple fields in a `Map<String, Object>` for bulk updates

Type-based Update

For improved type safety, `DynamicUpdateMutation` can also recursively derive update fields from a defined POJO. This allows you to work with strongly typed objects while still benefiting from dynamic field updates, ensuring both flexibility and safety in your Rule logic.

Error Handling

The `DynamicUpdateMutation` provides built-in error handling:This ensures that your mutations are robust and handle edge cases gracefully.

Complete Examples

Example 1: Generic Field Setter Rule

This rule demonstrates how to create a reusable field setter that works for any entity type:

Example 2: Complex Object Update

This example shows how to update complex nested objects using type-based mutations:


Dynamic Pagination

Author:

Kirill Gaiduk

Changed on:

24 June 2025

Overview

`DynamicConnectionQuery` automatically derives the Connection fields (arrays) for the primary Entity based on the `RulesetContext` and can dynamically load all connection items, with pagination handled internally.

Key points

  • Automatic Pagination`DynamicUtils.queryList` completely automates fetching paginated data from a GraphQL connection. You get a simple `Iterable`, and the library handles fetching subsequent pages in the background as you iterate.
  • Lazy Loading: The utility is highly efficient because it uses a "lazy loading" approach. It only fetches the next page of data when you have iterated through the current one.
  • POJO-Driven: You define the data you need by creating a simple POJO class. The utility dynamically builds the GraphQL query to fetch only the fields defined in your POJO.
  • Server-Side Filtering: You can pass a `Map` of parameters to `queryList` to filter the connection on the server. This is much more efficient than fetching all the data and filtering it in your rule.
Here is a collection of common scenarios for the Dynamic Pagination usage:

Query from Context usage

The simplest approach is to let the system automatically select the appropriate GraphQL query based on the entity type from the `RulesetContext`.

Explanation through an Example

The rule loads the attributes associated with an order and checks if attribute with specified name exists. If the condition is met, the rule sends an event.

Query from Parameter usage 

Alternatively, you can explicitly specify the GraphQL query within the method, giving you more control over the query selection. This approach allows for greater flexibility when you need to handle different types of queries within the same rule.