-
Notifications
You must be signed in to change notification settings - Fork 93
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
Graphql namespaces #2173
Comments
Can you point to where in the spec this is defined ? |
Hi. I carefully reviewed the specification and did not find a description of this. However, there is a fairly old discussion on this topic. As well as documentation from Apollo on this topic. |
@jmartisk - your call. |
I don't know man, I'm a bit hesitant to go through with this approach to namespaces when there's an open proposal to add namespacing to GraphQL - see graphql/graphql-spec#163 and https://medium.com/@oleg.ilyenko/graphql-namespaces-proposal-2a097ce81d2a - the approach in the second link is quite different as it uses a Btw I can imagine a way to do this with the current typesafe client too: With a query like
you, I think, could do
It's not super clean but I think it should work |
Hi. I tested it now. Yes, it can work. Simple example - namespace-demo.zip These code are, as you say, not super clean. And adds complexity in development. But it works (just need check how subscriptions works). Works while you don't start using federation. And FederationDataFetcher breaks down here, like if using Name on GraphQLApi (I can create simple reproducer of this, based on two services and cosmo gateway if you need) And #2172 fixes it for case Name on GraphQLApi. And for your example, but here need use recursion for deep type checks, becouce required method can be deep nested in GraphQLFieldDefinition. This part of code i can modify more. Just for example, Spring too supports namespaces, but how good it works there I don't know. Just as fact So, maybe it makes sense to allow you to write in any style? Because at a minimum, basic support for Name-based namespaces is already in place, and it works. |
#2172 updated. added recursive traversal to find the required field defenition |
I thought we're talking about the client side; in my eyes, the server side works good enough. I played around with the client side and came up with this: @GraphQLClientApi
interface Api {
@Query("Product") AllProducts products();
@Query("Product") GetProduct products(@NestedParameter("get") int id);
}
record AllProducts(List<Product> all) {}
record GetProduct(Product get) {}
record Product(String name) {}
...
var all = api.products().all;
var product = api.products(1).get; The syntax is not nice, but I didn't get the And the I haven't analyzed the PR, yet, but how would the code look then? |
Hi. Sorry, I guess I didn't set the problems correctly initially. Namespaces Case 1. Server code
Client code
This works without problems. The schema is generated correctly. Everything works fine
Case 2. Adding Name and Description annotations to the GraphQLApi class and GraphQLClientApi
In this case, the types rolesQueries/rolesMutation/rolesSubscription are generated separately. Adding the annotation allows you to split the code in the final schema into different namespaces. And it works out of the box, apparently, for a long time now.
It works. Here, on the server side, one small flaw pops up, that the group description is not correctly entered in the schema. The fix for this is - #2168 As for the client part, adding the Name annotation does not give any result, the query continues to be generated without it.
Query generated like
In my opinion, it would be nice to fix this (done here - #2169), so that inside smallrye it works out of the box.
But still, it would be nice to have the ability to just use Name for such cases and that's it. It seems to me that this is not a bad option. The one who uses smallrye/quarkus should take care of the problems with mutations and know the solutions. Maybe it is worth adding documentation about this, with some warnings - read about possible problems here (link to graphql/apollo). Case 3. Server code
Then you can execute queries like
The code above can also be simplified a bit by using Name (slightly).
And it will work (if you forget about the mutation issues for a while) But with the client it becomes a bit more complicated. you will need something similar like this
It becomes necessary to either strictly adhere to variable names or use annotation Name. There is a severe lack of examples in the documentation for such specific things. Documentation with the NestedParameter example only contains 1 sentence about nesting at the end. Maybe you should expand the documentation a bit with an example? For example, unfortunately, I only realized now that it works like this. while write it. Intermediate result. It all works. But it would be nice to expand the documentation with more examples of different tricks (case 3). Federations The fix for this is here (#2172 ). A full type traversal has been added to find the required method and caching of this information. |
@RoMiRoSSaN: thanks for the extensive explanation. Now it all makes sense 😁 @jmartisk: namespaces are actually relevant for very large models. The article you linked to, is very well thought through, but it requires a change in the spec, and nobody seems to have been working on that for years. OTOH, the "Apollo" solution uses existing schema elements, so they already work and are in use in larger projects. This is what we already support on the server side, so maybe we should stick to that approach for now. If there will be a spec change in the future, maybe it would be possible to just add a configuration option to produce the new kind of schema and queries. (If we have too much time 🤪, we could even add that option now, but use underscores instead of slashes.) Maybe we should add a new annotation For nested namespaces, maybe we could use slashes, i.e.: @GraphQLApi
@Namespace("crm/users")
public class Resource {
@Query("all")
public List<User> findAll() {
//
}
} or even: @GraphQLApi
public class Resource {
@Query("crm/users/all")
public List<User> findAll() {
//
}
} One little detail: the generated schema uses the namespace for the field as well as the type name: type Query {
products: productsQuery
} It would be nice, if the |
So what do you think? If you want, I can try to make a version of the Namespace annotation according to @t1 suggestion. In this case, it will probably be necessary to explicitly prohibit the use of Name over GraphQLApi/GraphQLApiClient (throw an error - use Namespace instead of Name). I can try do this in a few days. For now, I want to try to fix the work with the federation completely - #2110 here is the beginning of the problem and an addition from me. |
Ok I'm fine with adding support for |
I agree that we have to be prepared for a change in the GraphQL spec. The concept of a namespace can be implemented in different ways, and maybe we could support all such possible ways with the same Java code and make the namespace style a configuration option. Something like this: @GraphQLApi
@Namespace("crm/users")
public class Resource {
@Query("all")
public List<User> findAll() {
//
}
} As discussed, by default, we would turn this into grouping types: type Query {
crm: CrmQuery
}
type CrmQuery {
users: UsersQuery
}
type UsersQuery {
all: [User]
} And a query like: query {
crm {
users {
all {
name
}
}
}
} If the standard comes as suggested in the article, we can add a config option like type Query {
crm/users/all: [User]
} and a query like: query {
crm/users/all {
name
}
} Probably, this wouldn't work with the current version of type Query {
crm_users_all: [User]
} and a query like: query {
crm_users_all {
name
}
} Point is: the Java code could stay unchanged! |
We can't say for sure what the spec approach will look like, and trying to create a generic Java API sounds quite dangerous to me. What if you then need to, for example, deal with parameters or directives on the 'namespace' fields.. |
By the way, I found another problem. It is related to subscriptions. If they are inside the namespace, then an error is thrown directly from their graphql-java. This example not working.
As I see from the commit history, support for the Name annotation over GraphQLApi was added by @phillip-kruger in 2020. And in 2021 added subscriptins. So even the solution that has existed for a long time does not seem to work correctly. |
But it works for queries and mutations; subscriptions are by far rarer to be seen, so I think we can live with this limitation. |
I made a draft of how to extend the namespaces suggested by @t1. #2184 If group by parameters from Namespace (by /), then not so many changes are required. This example only replaces Name with Namespace, adds some checks, changes opearionName in the type-safe client. But it’s not up to me to decide =) And maybe this issue can be closed. |
I decided open issues after discussion with @jmartisk in PR #2169
Jan said that using namespaces are not recomended. However grpahql spec allows it
Default behavior of graphql and graphql-client does not raise questions.
Server part allows now using annotation Name for grouping apis. I think it is not bad if someone whant grouping api in same namespaces.
At this moment I found some bugs related with namespaces
May be I can found something else..
So, I want discuss them. What are think about it?
Thanks
The text was updated successfully, but these errors were encountered: