leangen / graphql-spqr

Build a GraphQL service in seconds
Apache License 2.0
1.09k stars 181 forks source link

How to scan for custom annotation generation? #456

Open StringKe opened 1 year ago

StringKe commented 1 year ago

I'm using spring-graphql and have a HttpAction annotation defined in the project to implement both http and graphql functionality, I currently want to scan the HttpAction annotation to generate schema.graphqls via graphql-spqr

import org.springframework.core.annotation.AliasFor;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping
@SchemaMapping
public @interface HttpAction {
    @AliasFor(annotation = SchemaMapping.class, attribute = "field")
    String name() default "";

    @AliasFor(annotation = SchemaMapping.class, attribute = "typeName")
    String typeName() default "Query";

    @AliasFor(annotation = RequestMapping.class, attribute = "method")
    RequestMethod[] method() default {RequestMethod.GET, RequestMethod.POST};

    @AliasFor(annotation = RequestMapping.class, attribute = "path")
    String[] path() default {};
}

What should I do to generate graphql schema for the type of the method tagged with @HttpAction?

kaqqao commented 1 year ago

I think you're confusing GraphQL SPQR with Spring GraphQL. While these 2 can be made to work together, you won't be getting any benefit from doing so, and neither is aware of the other.

SPQR doesn't understand @SchemaMapping, as those annotations don't really map well to what SPQR is doing. Neither does SPQR generate schema files (schema.graphqls) at any point, because it doesn't need to. It instead generates an executable schema directly in memory.

With all that said, you could make a composite annotation that acts as both @RequestMapping and e.g. @GraphQLQuery, or other SPQR annotations. Or configure SPQR to recognize any other annotation. For that you'd have to provide custom implementations of (at least) ResolverBuilder and InputFieldBuilder to the GraphQLSchemaGenerator:

generator
        .withResolverBuilders(new CustomResolverBuilder())
        .withInputFieldBuilders(new CustomInputFieldBuilder())

There's a lot you could reuse from the existing implementations, so your customizations should be pretty simple. I can help you further in doing so if you get stuck. But. Before you attempt any of that, make triple sure this is really what you want to do, because it seems you currently have wrong expectations from SPQR. So please first get a cleaner understanding of what each tool in your toolchain does for you. SPQR Spring Boot starter is intended to be used by itself (e.g. using SPQR's annotations), and not to be mixed with Spring GraphQL's schema mapping features, as they work drastically differently on the conceptual level.

StringKe commented 1 year ago

I envision using spring-graphq as a code-first-schema approach.

So I want to borrow the power of sqpr to generate schema, because spring-graphql must have a definition of grpahql.schema.

Since we have some other services that still need to be implemented using resetful (some hardware systems, we don't have the ability to modify it)

kaqqao commented 1 year ago

But why not use SPQR Spring starter directly? It gives you exactly what you want, right?

StringKe commented 1 year ago

The annotations in spqr don't exist in a separate package.

My overall project is a microservice.

I don't use graphql in microservices but dubbo (an RPC protocol), and when my POJO needs to use sqpr's annotations I need to bring it in all my projects.

So instead of using sqpr, I'm currently using spring-graphql in gateway and publishing both graphql and restful api with custom annotations

kaqqao commented 1 year ago

Ok, it's easy enough to configure SPQR to scan for your custom annotations. I'd make an example, but I'm traveling and don't have a computer with me. I'll be back in a couple of days. In the meantime, look at AnnotatedResolverBuilder and AnnotatedInputFieldBuilder. You can extend those 2 and change the annotations they're looking for.

StringKe commented 1 year ago

Thank you for your reply, I will try this way.

StringKe commented 1 year ago

any updates?