Fluent Commerce Logo
Docs
Sign In

Query Utilities

Essential knowledge

Author:

Kirill Gaiduk

Changed on:

10 July 2025

Overview

The `QueryUtils` class in the `util-core` bundle offers a set of functions to simplify GraphQL queries from within your Rules. These helpers make it easier to work with query results and handle common data structures like paginated connections.

Key points

  • Type-Safe Queries: The `query` method is a wrapper that eliminates the need to manually cast GraphQL responses to the correct type, making your code cleaner and safer.
  • Simplified Connections`connectionToList` is a powerful helper that converts a standard GraphQL "connection" (with its `edges` and `nodes`) into a simple `List` of objects, removing a significant amount of boilerplate code.
  • Inline Transformation`connectionToList` can also accept a function, allowing you to transform the list of GraphQL nodes into a list of your own domain objects (POJOs) in a single operation.

Core Methods

`query`

This method is a wrapper around the standard `context.api().query()` method. Its main advantage is that it is properly generified, meaning you don't need to manually cast the response to the correct `Operation.Data` type.

1import static com.fluentcommerce.util.core.QueryUtils.query;
2
3// ...
4
5// The 'query' helper automatically returns the correct response type,
6// so no casting is needed.
7GetMyEntityQuery.Data response = query(
8    context, 
9    GetMyEntityQuery.builder()
10        .id(context.getEvent().getEntityId())
11        .build()
12);
13
14// You can now access the response data directly
15String status = response.entity().status();
`connectionToList`

This utility is designed to solve a common problem when working with GraphQL: converting a paginated "connection" into a `List`. A connection is a standard GraphQL pattern for representing one-to-many relationships (like an order having multiple items) that includes pagination cursors and edges.

The `connectionToList` method automatically extracts the `node` from each `edge` in the connection and returns an `ImmutableList` of nodes.

When using this method, make sure that the GraphQL query aliases for the connection fields are correctly named or suffixed with "edge" and "node." If you have multiple connections in a single query, Apollo might automatically name them as `Node1`, `Node2`, and so on, which can cause issues. To prevent this, explicitly alias each connection with meaningful names like `itemNode` or `fulfilmentNode`.

An overloaded method provides a second boolean which controls error handling: 

  • `true` will throw an exception if the connection is invalid 
  • `false` will simply return an empty list in those cases.

Example

Imagine a `GetOrderByIdQuery` that returns an order with a connection of `items`. The response structure might look like this:

1{
2  "data": {
3    "order": {
4      "id": "123",
5      "items": {
6        "edges": [
7          { "node": { "id": "item-A", "ref": "SKU-A" } },
8          { "node": { "id": "item-B", "ref": "SKU-B" } }
9        ]
10      }
11    }
12  }
13}

Without the utility, you would need to write nested loops and null checks to get a list of items. With `QueryUtils`, it's a single line:

1import com.fluentcommerce.util.core.QueryUtils;
2import com.google.common.collect.ImmutableList;
3
4// ...
5
6// Assume 'response' is the result from the GetOrderByIdQuery
7GetOrderByIdQuery.Items itemsConnection = response.order().items();
8
9// Convert the entire connection to a simple list of item nodes
10ImmutableList<GetOrderByIdQuery.Node> items = QueryUtils.connectionToList(itemsConnection);
11
12// You now have a simple list to work with
13for (GetOrderByIdQuery.Node item : items) {
14    context.action().log("Item ref: " + item.ref());
15}
`connectionToList` (using a converter)

An overloaded version of `connectionToList` accepts a `Function` to convert the nodes into a different type. This is useful for mapping GraphQL response objects to your own domain models.

This variant not only extracts the "node" elements from the "edge" structure but also applies a converter function (from type `T` to type `R`) to each node. As a result, it returns a list where each item is the result of applying the converter function to the original nodes.

1// Convert the connection directly to a list of MyItem domain objects
2ImmutableList<MyItem> myItems = QueryUtils.connectionToList(
3    itemsConnection,
4    itemNode -> new MyItem(itemNode.id(), itemNode.ref())
5);