@@ -571,28 +571,25 @@ to send to the client.
571
571
[[execution.pagination]]
572
572
=== Pagination
573
573
574
- The https://relay.dev/graphql/connections.htm[GraphQL Cursor Connection specification]
574
+ The GraphQL Cursor Connection https://relay.dev/graphql/connections.htm[specification]
575
575
defines a mechanism for efficient navigation of large result sets by returning a limited
576
- subset of items at a time. Each item is assigned a unique cursor that a client can use to
577
- request the next items after or the previous items before the cursor reference, as a way of
578
- navigating forward or backward.
576
+ set of items at a time. Each item is paired with a cursor that a client can use to request
577
+ the items after or before the cursor, providing a way to navigate forward and backward.
579
578
580
- The spec calls this pattern "Connections", and each schema type whose name ends on
581
- "Connection" is considered a _Connection Type_ and represents a paginated result set.
582
- Each `Connection` contains "edges" where an `EdgeType` is a wrapper around the actual item
583
- and its cursor. There is also a `PageInfo` object with flags for whether you can navigate
584
- further forward and backward and the cursors of the start and end items in the set.
579
+ The spec calls the pattern "Connections". A schema type whose name ends on "Connection"
580
+ is considered a _Connection Type_ and represents a paginated result set. A `Connection`
581
+ contains "edges" where an `Edge` is a wrapper around the actual item and its cursor.
582
+ There is also a `PageInfo` to indicate whether there are more items forward and backward.
585
583
586
584
587
- [[execution.pagination.type.definitions ]]
588
- ==== Connection Type Definitions
585
+ [[execution.pagination.types ]]
586
+ ==== Connection Types
589
587
590
588
`Connection` type definitions must be repeated for every type that needs pagination, adding
591
- boilerplate and noise to the schema. To address this, Spring for GraphQL provides the
592
- `ConnectionTypeDefinitionConfigurer` that adds these types on startup, if not already
593
- present in the parsed schema files.
594
-
595
- That means you can declare `Connection` fields, but leave out their declaration:
589
+ boilerplate and noise to the schema. Spring for GraphQL provides
590
+ `ConnectionTypeDefinitionConfigurer` to generate these types on startup, if not already
591
+ present in the parsed schema files. That means you can have a `Connection` field without
592
+ a type declaration as follows:
596
593
597
594
[source,graphql,indent=0,subs="verbatim,quotes"]
598
595
----
@@ -606,7 +603,7 @@ That means you can declare `Connection` fields, but leave out their declaration:
606
603
}
607
604
----
608
605
609
- Then configure the `ConnectionTypeDefinitionConfigurer`:
606
+ Configure `ConnectionTypeDefinitionConfigurer` as follows :
610
607
611
608
[source,java,indent=0,subs="verbatim,quotes"]
612
609
----
@@ -615,7 +612,7 @@ GraphQlSource.schemaResourceBuilder()
615
612
.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer)
616
613
----
617
614
618
- The following type definitions are added on startup to the schema:
615
+ The following type definitions will be added to the schema on startup :
619
616
620
617
[source,graphql,indent=0,subs="verbatim,quotes"]
621
618
----
@@ -637,25 +634,25 @@ The following type definitions are added on startup to the schema:
637
634
}
638
635
----
639
636
637
+ The <<boot-starter>> registers `ConnectionTypeDefinitionConfigurer` by default.
638
+
640
639
641
640
[[execution.pagination.adapters]]
642
- ==== Connection Adapters
641
+ ==== `ConnectionAdapter`
643
642
644
- Once <<execution.pagination.type.definitions >> are available in the schema, you also need
643
+ Once <<execution.pagination.types >> are available in the schema, you also need
645
644
equivalent Java types. GraphQL Java provides those, including generic `Connection` and
646
- `Edge` types , as well as `PageInfo`.
645
+ `Edge`, as well as a `PageInfo`.
647
646
648
- One option is to populate and return `Connection` directly from your controller method or
649
- `DataFetcher`. However, this is boilerplate work, to wrap each item, create cursors, and
650
- so on. Moreover, you may already have an underlying pagination mechanism such as when
651
- using Spring Data repositories.
647
+ One option is to populate a `Connection` and return it from your controller method or
648
+ `DataFetcher`. However, this requires boilerplate code to create the `Connection`,
649
+ creating cursors, wrapping each item as an `Edge`, and creating the `PageInfo`.
650
+ Moreover, you may already have an underlying pagination mechanism such as when using
651
+ Spring Data repositories.
652
652
653
- To make this transparent, Spring for GraphQL has a `ConnectionAdapter` contract to adapt
654
- any container of items to `Connection`. This is applied through a
655
- `ConnectionFieldTypeVisitor` that looks for any `Connection` field, decorates the
656
- registered `DataFetcher`, and adapts its return values.
657
-
658
- For example:
653
+ Spring for GraphQL defines the `ConnectionAdapter` contract to adapt a container of items
654
+ to `Connection`. Adapters are applied through a `DataFetcher` decorator that is in turn
655
+ installed through a `ConnectionFieldTypeVisitor`. You can configure it as follows:
659
656
660
657
[source,java,indent=0,subs="verbatim,quotes"]
661
658
----
@@ -668,54 +665,56 @@ GraphQlSource.schemaResourceBuilder()
668
665
.typeVisitors(List.of(visitor)) // <2>
669
666
----
670
667
671
- <1> Create type visitor with one or more `Connection` adapters .
668
+ <1> Create type visitor with one or more ``ConnectionAdapter``s .
672
669
<2> Resister the type visitor.
673
670
674
- There are <<data.scroll.sort,built-in>> ``ConnectionAdapter``s for the Spring Data
675
- pagination types `Window` and `Slice`. You can also create your own custom adapter.
676
-
677
- `ConnectionAdapter` implementations rely on a <<execution.pagination.cursor. strategy>> to create a cursor for
678
- each returned item. , and the same strategy is also used subsequently to decode the cursor
679
- to support the <<controllers.schema-mapping.subrange>> controller method argument .
671
+ There are <<data.scroll.sort,built-in>> ``ConnectionAdapter``s for Spring Data's
672
+ `Window` and `Slice`. You can also create your own custom adapter. `ConnectionAdapter`
673
+ implementations rely on a <<execution.pagination.cursor.strategy>> to
674
+ create cursors for returned items. The same strategy is also used to support the
675
+ <<controllers.schema-mapping.subrange>> controller method argument that contains
676
+ pagination input .
680
677
681
678
682
679
[[execution.pagination.cursor.strategy]]
683
- ==== Cursor Strategy
680
+ ==== `CursorStrategy`
684
681
685
682
`CursorStrategy` is a contract to create a String cursor for an item to reflect its
686
683
position within a large result set, e.g. based on an offset or key set.
687
- <<execution.pagination.adapters>> use this to create a cursor for returned items.
684
+ <<execution.pagination.adapters>> implementations use this to create cursors for returned
685
+ items.
688
686
689
- The strategy also helps to decode a cursor back to an item position. For this to work,
690
- you need to declare a `CursorStrategy` bean, and ensure that annotated controllers are
691
- <<controllers-declaration, enabled>> .
687
+ The strategy also supports the <<controllers.schema-mapping.subrange>> controller
688
+ method argument. For this to work, you need to declare a `CursorStrategy` bean, and also
689
+ ensure that annotated controllers are <<controllers-declaration, configured>> for use .
692
690
693
691
`CursorEncoder` is a related, supporting strategy to encode and decode cursors to make
694
692
them opaque to clients. `EncodingCursorStrategy` combines `CursorStrategy` with a
695
- `CursorEncoder`. There is a built-in `Base64CursorEncoder`.
693
+ `CursorEncoder`. You can use `Base64CursorEncoder`, `NoOpEncoder` or create your own .
696
694
697
- There is a <<data.scroll.sort,built-in>> `CursorStrategy` for the Spring Data `ScrollPosition`.
695
+ There is a <<data.scroll.sort,built-in>> `CursorStrategy` for the Spring Data
696
+ `ScrollPosition`. The <<boot-starter>> registers a `ScrollPositionCursorStrategy` with
697
+ `Base64Encoder` when Spring Data is present.
698
698
699
699
700
700
[[execution.pagination.arguments]]
701
701
==== Arguments
702
702
703
703
Controller methods can declare a <<controllers.schema-mapping.subrange>>, or a
704
- `ScrollSubange` method argument, to handle requests for forward or backward pagination.
705
- The method argument resolver is configured for use when a
706
- <<execution.pagination.cursor.strategy>> bean is declared in Spring configuration.
704
+ `ScrollSubange` method argument when Spring Data is present, for pagination requests .
705
+ The argument resolver is added when a <<execution.pagination.cursor.strategy>> bean is
706
+ present in Spring configuration.
707
707
708
708
709
709
[[execution.pagination.sort.strategy]]
710
710
==== Sort
711
711
712
- Pagination depends on a stable sort order. There is no standard for how to declare sort
713
- related GraphQL input arguments. You can keep it as an internal detail with a default
714
- sort, or if it you need to expose it, then you'll need to extract the sort details from
715
- GraphQL arguments.
712
+ There is no standard way to provide sort information in a GraphQL request. However,
713
+ pagination depends on a stable sort order. You can use a default order or extract, and
714
+ keep it as an internal detail, or extract sort details from GraphQL arguments.
716
715
717
- There is partial, <<data.scroll.sort,built-in>> support for to create a Spring Data
718
- `Sort`, with the help of a `SortStrategy`, and inject that into a controller method .
716
+ There is <<data.scroll.sort,built-in>> support for Spring Data's `Sort` as a controller
717
+ method argument. For this to work, you need to have a `SortStrategy` bean .
719
718
720
719
721
720
[[execution.batching]]
0 commit comments