How Dynamic Utilities work
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:- A basic understanding of the Utility Bundles and Dynamic Bundles
- Familiarity with writing Rules using the Rules SDK
- Completed the Getting Started with the Utility Bundles guide
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
- 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.
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:Related content
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:Related content
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.
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:Related content
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.
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`.