Enigmatis / graphql-java-annotations

GraphQL Annotations for Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for singletons? GraphQLAnnotations.object(mySingleton)

benneq opened this issue · comments

commented

Is it somehow possible to use objects instead of classes?

I want to use graphql-java-annotations with Spring Dependency Injection.

I want to use something like the following code:

@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	@Bean
	public GraphQLSchema schema(MyQueryBean query) {
		GraphQLObjectType queryObject = GraphQLAnnotations.object(query);
		return newSchema().query(queryObject).build();
	}
}

This way I could inject for example a Service into MyQueryBean for Database access:

@Component
public class MyQueryBean {
	@Autowired MyService service;

	@GraphQLField @GraphQLName("myFoo")
	public MyData foo() {
		return service.getData();
	}
}

Is this already possible somehow?

commented

I'm using the annotations library in this particular way in one of my projects (using spring boot).
I don't see any reason why you cannot use it like that.

commented

Can you show me how this works? Some small piece of example code, where you use an @Autowired value / service to return data via GraphQL API.

The tests of this project and the spring boot starter project don't seem to include any examples for this. Or did I overlook something?

@Configuration
public class GraphQLCreateorConfig {
               @Bean
                public GraphQL graphQL() {
                          // create the schema via annotation and then the graphql object
                             return graphql;
               }

If you want to use @Autowired inside your resolvers, you need to do a tiny trick:

  1. Define an abstract class implementing DataFetcher and BeanFactoryAware
public abstract class springDataFetcher<T> implements DataFetcher<T>, BeanFactoryAware {
           private BeanFactory bf;
         
           @Override
            public setBeanFactory(BeanFactory bf1) {bf = bf1}

          @Override
          public T get(DataFetchingEnvironment env) {
                            DataFetcher<T> actualDataFetcher = bf.getBean(this.getClass());
                             return actualDataFetcher.fetch(env);
         }

       public abstract T fetch(DataFetchingEnvironment env);
  1. Every dataFetcher extends the abstract class and overrides the "fetch" function
    Note that the class must be annotated with @Component
@Component
public class MyDataFetcher<SomeDBClass> extends SpringDataFetcher<SomeDBClass> {
                     @Autowired
                      private SomeDBClassRepository repository;

                       @Override
                        public SomeDBClass fetch(DataFetchingEnvironment env) {
                                        //Here you can use the repository
                       }
}

And that way you can use spring stuff inside your dataFetcher

commented

I already thought that you had used BeanFactoryAware.

But the solution is in the end not very "Springish". I know that this is not your graphql-spring project, but the spring project depends on the graphql-annotations project when it comes to collecting and configuring the graphql types.

Though I thought it might be nice, if this library could also work with singleton beans, and not only with classes.

commented

I had this exact problem yesterday. I found this very nicely documented library which already supports these use cases, https://github.com/leangen/graphql-spqr. This is a sample app that shows the whole thing wired up with spring-boot, https://github.com/leangen/graphql-spqr-samples/tree/master/spring-boot-sample. Also note there's a spring-boot-starter which does some of the work for you (although in honesty there's not much to do either way).

Hi @benneq,

We're helping with project maintenance and reviewing the list of opened PRs and Issues.

This issue was created quite a while ago, we were wondering if you were still interested in the outcome, please let us know if this is the case.

Without an answer by July 1st, 2023, this issue will be closed as "inactive" (and can always be re-opened later on if needed).

Thanks,

commented

@Fgerthoffert I haven't looked into this for years. Though if nobody else here is still interested, you may just close this.