Skip to content

Support custom argument resolvers for @SchemaMapping methods #259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
marceloverdijk opened this issue Jan 15, 2022 · 6 comments
Closed

Support custom argument resolvers for @SchemaMapping methods #259

marceloverdijk opened this issue Jan 15, 2022 · 6 comments
Labels
status: superseded Issue is superseded by another type: enhancement A general enhancement

Comments

@marceloverdijk
Copy link
Contributor

As discussed in #250 this is feature request for support of custom argument resolvers in GraphQL controllers.

E.g. to support

@QueryMapping
public Page<Season> seasons(Pageable pageable) {
    int first = pageable.getFirst();
    int offset = pageable.getOffset();
    ..
}

The plain example as above could already be implemented using a @ProjectedPayload

@ProjectedPayload
public interface Pageable {

    int getFirst();
    int getOffset();
}

(Note: using the @Argument annotation for above case does not work me, see #258)

But supporting custom argument resolvers could offer more flexibility I was looking for like the ability to use a custom @interface to provide defaults , e.g.

@QueryMapping
public Page<Season> seasons(@PageableDefault(first=10, offset=0) Pageable pageable) {
    ..
}

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 15, 2022
@rstoyanchev rstoyanchev added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 17, 2022
@rstoyanchev rstoyanchev added this to the 1.0 Backlog milestone Jan 17, 2022
@rstoyanchev rstoyanchev changed the title Add support for custom argument resolvers in GraphQL controllers Support custom argument resolvers for @SchemaMapping methods Jan 17, 2022
@rstoyanchev
Copy link
Contributor

rstoyanchev commented Mar 24, 2022

@marceloverdijk I'm wondering if the changes for #258 addressed the case here with Pageable or do you have another use case in mind?

Generally, both @SchemaMapping and @BatchMapping methods could have custom resolvers but they resolve from different contexts, DataFetchingEnvironment vs BatchLoaderEnvironment, and can't share the same contract. I'm also not certain what this would be used for, considering that we expose more or less everything there is.

@marceloverdijk
Copy link
Contributor Author

Hi @rstoyanchev #258 already helps a lot to be honest.

Having support for custom argument resolvers - like in e.g. MVC - I could do even more.

Besides binding the arguments to an object I could also apply some login when binding, like defining default values as can be seen in the example below. The idea below is build upon Spring Data's PageableHandlerMethodArgumentResolver.

@QueryMapping
public Page<Season> seasons(@PageableDefault(first=10, offset=0) Pageable pageable) {
    ..
}

@rstoyanchev
Copy link
Contributor

Thanks for clarifying. For the Pageable example, isn't the logic within it and hence orthogonal to the instantiation or is there something specific about the instantiation?

Of course it makes perfect sense to have such resolvers but for now it doesn't seem to be holding anything up, and with the two different types of handler methods and resolver contracts, I'd rather give this more time, before we find the best way to proceed.

@marceloverdijk
Copy link
Contributor Author

I understand.

For me it's about having more control to which default value to set in the argument resolver; it's coming from #250

@benneq
Copy link

benneq commented Jun 9, 2022

I'm having a similar issue, but I'm not sure if a custom argument resolver can help:

Schema:

scalar ConnectionCursor

type Query {
    books(after: ConnectionCursor): [Book]
    authors(after: ConnectionCursor): [Author]
}

Controller:

@Controller
public class MyController{
    @QueryMapping
    Flux<Book> books(@Argument BookConnectionCursor after) {
        return Flux.empty();
    }

    @QueryMapping
    Flux<Author> authors(@Argument AuthorConnectionCursor after) {
        return Flux.empty();
    }
}

As you can see, in the schema there's only a generic ConnectionCursor scalar, but inside the controller code each @Argument should be able to use its ows specialized version.

When creating custom ConnectionCursor scalar with RuntimeWiringConfigurer it is easy to serialize, because I have type information. But with parseValue and parseLiteral I don't have any type information and no access to controller method and parameter, though I can't figure out if I should create a BookConnectionCursor or a AuthorConnectionCursor object.

Can a custom argument resolver solve this issue? (I guess there I should have the class type of the controller method argument)


EDIT: I just figured out that I can register org.springframework.core.convert.converter.Converter<String, BookConnectionCursor> and Converter<String, AuthorConnectionCursor> @Beans and then register the scalar as String Scalar:

@Bean
RuntimeWiringConfigurer configurer() {
    return builder -> builder
                .scalar(GraphQLScalarType.newScalar(Scalars.GraphQLString).name("ConnectionCursor").build());

}

Works as intended 😸 First the registered scalar creates a String from the input value, and then the GraphQlArgumentBinder looks for the matching Converter. Nice!

@rstoyanchev
Copy link
Contributor

I'm closing this as superseded by #325.

@rstoyanchev rstoyanchev removed this from the 1.1 Backlog milestone Oct 24, 2022
@rstoyanchev rstoyanchev added the status: superseded Issue is superseded by another label Oct 24, 2022
@rstoyanchev rstoyanchev closed this as not planned Won't fix, can't repro, duplicate, stale Oct 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded Issue is superseded by another type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants