Skip to content
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

Unable to generate Federation schema with no @Query functions #2110

Open
nicholassmith opened this issue May 16, 2024 · 3 comments
Open

Unable to generate Federation schema with no @Query functions #2110

nicholassmith opened this issue May 16, 2024 · 3 comments

Comments

@nicholassmith
Copy link

Maybe this is a bit edge case but it's valid for federation and I can't quite figure out how to achieve it. I would like to generate a schema like:

union _Entity = Shelf

type Books {
   name: String!
   shelf: Shelf
....

"Query root"
type Query {
   _entities(representations: [_Any!]!): [_Entity]!
   _service: _Service!
}

...

However with smallrye-graphql I need at least 1 query for it to build the schema and then invoke the Federation transformer to add the additional entities query that allows for this usecase. The only thing I can think of is that when it checks schema.hasOperations()) in Bootstrap.java it should also check to see if it will generate the entities query.

@RoMiRoSSaN
Copy link
Contributor

@jmartisk
Hi Jan, I tagged you, becouse you created PR before.

I have encountered this problem too. At the moment samllrye graphql does not support working with federations in full.
The solution #2113 does not work, because the schema is validated before its transformation.
I came up with a slightly strange solution to get around this, but it definitely works and does not break anything.
Only at the moment it makes no sense, because, as it seems to me, support for federation is not fully implemented.

An example of a schema using federation (maybe not entirely correct, but it reflects the essence)

schema {
    query: Query
}

union _Entity = Role

type Query {
    _entities(representations: [_Any!]!): [_Entity]!
    _service: _Service
}

type _Service {
    sdl: String!
}

type Role @extends @key(fields : "id") {
    id: String @external
    nameFromOtherService: String
}

scalar _Any

The option when only id information is returned in this type definitely works. When Role is a field of another type, from the request.

However, according to the federation specification, the schema may not contain any requests. But it can extend types, such as Role.

At the moment, this can be done a little incorrectly. For example, add an explicit request.

// User service
@GraphQLApi
public class Resource {
    @Query
    public User byId(Long id){
        ///
    }
    
    // This query should not exist
    @Query
    public Role findExtendedRole(Long id) {
        // get role by id
        // set needed fields
        // return
    }
}

Most likely, this type of variant will not work

type Role @extends @key(fields : "id") {
    id: String @external
    name: String @exteranl
    .... more external provides required
    nameFromOtherService: String
}

Or there is nothing about this in the documentation and I just did not find / did not understand how it works. Or it really is not implemented.
This variant definitely does not work. Information about the Role type does not get into the schema, fetcher is not created.

// User service
@GraphQLApi
public class Resource {
    public Role findExtendedRole(@Source Role role) {
        // role has all needed external fields
        // set needed fields
        // return
    }
}

The main problem here is that with federation I can get a Role with many external fields received from different services and provide additional fields based on them. At the same time, without revealing information about how this will be done (without creating queries).

While someone reads and responds to this comment, I will try to either figure it out or prepare a fix in some form.

@RoMiRoSSaN
Copy link
Contributor

RoMiRoSSaN commented Sep 4, 2024

@jmartisk @t1 @phillip-kruger I need your opinion.

Here is an example of how federation works from Apollo written in NodeJs
https://github.com/apollographql/federation-demo

Here is an example of a situation where there are no explicit requests, but the scheme is valid and fulfills its role. Essentially these are 4 different services, but have only two endpoints.

Now smallrye graphql (or rather graphql-java) does not allow building a schema if there are no queries.
I was able to get around this problem, it works.
Another feature is that federation requests require explicitly creating Query methods. And there can be many of them.
This point can also be bypassed.

Please look at the PR #2180 and the code I attached (quarkus-federation-demo.zip).
There are short instructions inside (writing such code in java is a pain=))

What do you think about this? Is this necessary or not? This is the first version, without tests, documentation and other things. If necessary, I'll add it.

@phillip-kruger
Copy link
Member

I'll leave this for @jmartisk and @t1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants