spring-graphql: No ConnectionAdapter IllegalArgumentException for existing Java Connection type

I had been following the development of pagination support in #103.

In my setup, I already had types like PuzzleConnection. Upon updating to the release of spring-graphql that added pagination support, I am now getting exceptions like:

java.lang.IllegalArgumentException: No ConnectionAdapter for: foo.bar.models.puzzles.connections.PuzzleConnection

I looked through the reference and even a bit of the code (the starter/autoconfigure-er) but couldn’t see anything about opting out either entirely or on a case-by-case basis via graphql annotations, or even implicitly opting out such as when it detects that the Edge and Connection types already exist (which might be something worthwhile to add?).

Should I just pin to the prior version until something is implemented? Do you recommend that I do something to prevent ConnectionTypeDefinitionConfigurer from being registered?

Thanks for all your work on spring-graphql!

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@mzvankovich yes that is supported.

The snapshot seems to work without changes to our current connection implementations 👍

@blaenk I’ve set the release date for 1.2.1 for June 20. We could decide to release sooner depending on the issues that come in, but it’s good to allow some additional time for feedback, and would be timed with the Boot 3.1.1 release on June 22.

In the mean time, looking at the Boot auto-configuration that installs the ConnectionAdapter, it’s triggered by the presence of ScrollPosition from spring-data-commons. That’s probably on the classpath to get this issue. You could define your own EncodingCursorStrategy<?> cursorStrategy() bean with a custom, no-op CursorStrategy (as long as it doesn’t support ScrollPosition).

Thanks for confirming the fix!

As for adapting my code, it seems like I would need to implement graphql.relay.Connection, graphql.relay.PageInfo, graphql.relay.ConnectionCursor, and graphql.relay.Edge.

The idea with our pagination support is that you don’t have to implement these types. Instead, you would return the actual result items however they may be represented in your underlying service/data layer, and then configure a ConnectionAdapter along with a CursorStrategy to help us turn that transparently to graphql.relay.Connection.

For example if using Spring Data repositories, you would naturally have Page or Window from paginated requests, and we support returning those directly from the controller method. They are then transparently adapted to graphql.relay.Connection with our built-in support, but you can also write a ConnectionAdapter for any other paginated type, essentially some kind of simple container of a List of items along with boolean flags about hasNext and hasPrevious. The benefit is to use simpler (or any) pagination type, and use ConnectionAdapter to produce the expected, complete paginated response.

This does mean that you would need to change your schema to match the GraphQL Cursor Connection spec, which might not be an option, and this is why we make sure your exiting pagination can continue to work as it did before.

This is just to give you an idea, but have a look around the documentation for more details.

I’ve made a couple of updates, 1) to check the complete structure of a Connection schema type before deciding to apply a DataFetcher decorator to adapt its return values to graphql.relay.Connection, and 2) at runtime to ignore return values with a name that ends on Connection. This double protection I expect will go pretty far. If you could give those a try with 1.2.1-SNAPSHOT and confirm, that would be much appreciated.

maybe we would benefit from some explicit opt-out support

It could be opt-in or opt-out, but it makes sense to strengthen checks first, and exhaust our options. In the end, my sense is that we will be able to do without that.