Dynamic Queries and Utils
Intended Audience:
Technical User
Authors:
Kirill Gaiduk, Valery Kornilovich
Changed on:
19 Mar 2026
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: