graphql-java-codegen icon indicating copy to clipboard operation
graphql-java-codegen copied to clipboard

Make your GraphQL Java application schema-driven.

Results 142 graphql-java-codegen issues
Sort by recently updated
recently updated
newest added

Can the plugin support getFields() in GraphQLResponseProjection?

[{"_id":"63507653ea01ec786e748bd9","body":"If you don't care about to get all the values, you can use `all$`. Otherwise, it can't now.\r\n\r\n","issue_id":1660627226099,"origin_id":1192094269,"user_origin_id":29496873,"create_time":1658454110,"update_time":1658454163,"id":1666217555086,"updated_at":"2022-10-19T22:12:35.086000Z","created_at":"2022-10-19T22:12:35.086000Z"},{"_id":"63507653ea01ec786e748bda","body":"@ruipliu if I understand correctly your problem statement, you want the ability to create a new instance of GraphQLResponseProjection out of another instance of GraphQLResponseProjection.\r\nIs that true?\r\nIf yes, then this is a fairly simple feature to implement.","issue_id":1660627226099,"origin_id":1194409486,"user_origin_id":2664706,"create_time":1658771334,"update_time":1658771334,"id":1666217555091,"updated_at":"2022-10-19T22:12:35.091000Z","created_at":"2022-10-19T22:12:35.091000Z"},{"_id":"63507653ea01ec786e748bdb","body":"@kobylynskyi Yes correct.\r\nBased on my knowledge of the source code, the only change is to add getFields() in GraphQLResponseProjection.java","issue_id":1660627226099,"origin_id":1194897768,"user_origin_id":48465727,"create_time":1658801981,"update_time":1658801981,"id":1666217555094,"updated_at":"2022-10-19T22:12:35.094000Z","created_at":"2022-10-19T22:12:35.094000Z"},{"_id":"63507653ea01ec786e748bdc","body":"Unfortunately adding `getFields()` method might be a breaking change for the clients who have a type with field `getFields` - because `getFields()` method will already be present in the `TypeResponseProjection`.\r\n\r\nSo the approach of creating an additional \"copy\" constructor would be better, what do you think?\r\n```java\r\nType1ResponseProjection type1 = new Type1ResponseProjection();\r\nType1ResponseProjection type1Copy = new Type1ResponseProjection(type1);\r\n```\r\n","issue_id":1660627226099,"origin_id":1196167466,"user_origin_id":2664706,"create_time":1658885333,"update_time":1658885333,"id":1666217555097,"updated_at":"2022-10-19T22:12:35.097000Z","created_at":"2022-10-19T22:12:35.097000Z"},{"_id":"63507653ea01ec786e748bdd","body":"Sorry for the late reply.\r\nThe \"copy\" constructor may not work. As the aim of creating from existed one is to get the fields from a projection so that the field tree can be modified when or after creating.\r\n\r\nFor example, if we want to add `price` of a product in a projection having `user.order.product.name` field tree, we could get the `product` field and add accordingly.\r\n\r\nHere are some alternative solutions, could you give some comments?\r\n1. add special character in getFields(), like getFields$()\r\n2. make 'fields' public","issue_id":1660627226099,"origin_id":1198838951,"user_origin_id":48465727,"create_time":1659064817,"update_time":1659064817,"id":1666217555101,"updated_at":"2022-10-19T22:12:35.100000Z","created_at":"2022-10-19T22:12:35.100000Z"},{"_id":"63507653ea01ec786e748bde","body":"We should not modify the original `getFields`.","issue_id":1660627226099,"origin_id":1198842147,"user_origin_id":29496873,"create_time":1659065266,"update_time":1659065266,"id":1666217555103,"updated_at":"2022-10-19T22:12:35.102000Z","created_at":"2022-10-19T22:12:35.102000Z"},{"_id":"63507653ea01ec786e748bdf","body":"> We should not modify the original `getFields`\r\n\r\nThere is no getFields() in current Graph l response projection. We are thinking of adding this methods to access and modify the `fields`.\r\n\r\nDo you mean the `field` attribute should not be modified?","issue_id":1660627226099,"origin_id":1198843522,"user_origin_id":48465727,"create_time":1659065487,"update_time":1659065487,"id":1666217555105,"updated_at":"2022-10-19T22:12:35.105000Z","created_at":"2022-10-19T22:12:35.105000Z"},{"_id":"63507653ea01ec786e748be0","body":"> Do you mean the `field` attribute should not be modified?\r\n\r\nwe should only modify it by response projection method. If the returned by getField is mutable that will break this.\r\n\r\n\r\n> The \"copy\" constructor may not work. As the aim of creating from existed one is to get the fields from a projection so that the field tree can be modified when or after creating.\r\n\r\nIf the internal fields can be modified after creating object, it may lead to insecurity.","issue_id":1660627226099,"origin_id":1198900781,"user_origin_id":29496873,"create_time":1659073284,"update_time":1659073284,"id":1666217555107,"updated_at":"2022-10-19T22:12:35.107000Z","created_at":"2022-10-19T22:12:35.107000Z"},{"_id":"63507653ea01ec786e748be1","body":"> If the internal fields can be modified after creating object, it may lead to insecurity.\r\n\r\nCould you explain the insecurity case a bit more? about what scenario and what kind of security problem. Thanks!\r\n\r\nMy feeling is the `ResponseProjection` is only a tool for client side building GraphQL query and it would be better to provide more convenience and accessibility. Client side could make effort to assure the security when using this class.","issue_id":1660627226099,"origin_id":1198959238,"user_origin_id":48465727,"create_time":1659079172,"update_time":1659079172,"id":1666217555110,"updated_at":"2022-10-19T22:12:35.109000Z","created_at":"2022-10-19T22:12:35.109000Z"},{"_id":"63507653ea01ec786e748be2","body":"When a projection needs to be defined and subsequently used multiple times. Some times it may be modified, which results in multiple calls not having the same result.","issue_id":1660627226099,"origin_id":1199034316,"user_origin_id":29496873,"create_time":1659084661,"update_time":1659084661,"id":1666217555112,"updated_at":"2022-10-19T22:12:35.112000Z","created_at":"2022-10-19T22:12:35.112000Z"},{"_id":"63507653ea01ec786e748be3","body":"@ruipliu, \r\nI would really prefer not to expose `fields` outside. This would be breaking the encapsulation principle. So let's keep it \"safe\" inside the class so that users don't accidentally shoot themselves in the foot.\r\n\r\nLet's take your case as an example:\r\n> if we want to add `price` of a product in a projection having `user.order.product.name` field tree, we could get the `product` field and add accordingly.\r\n\r\nWe could still solve it with the copy-constructor thing:\r\n```java\r\nParentResponseProjection proj1 = new ParentResponseProjection()\r\n .user(new UserResponseProjection()\r\n .id()\r\n .order(new OrderResponseProjection()\r\n .total()\r\n .product(new ProductResponseProjection()\r\n .name()\r\n )\r\n )\r\n )\r\n\r\nParentResponseProjection proj2 = new ParentResponseProjection(proj1) \/\/ resuing all projection from proj1\r\n .user(new UserResponseProjection()\r\n .order(new OrderResponseProjection()\r\n .product(new ProductResponseProjection()\r\n .price() \/\/ this will add price to an existing projection which already has name\r\n )\r\n )\r\n )\r\n\r\nParentResponseProjection proj3 = new ParentResponseProjection(proj1) \/\/ resuing all projection from proj1\r\n .user(new UserResponseProjection()\r\n .order(new OrderResponseProjection()\r\n .product(new ProductResponseProjection()\r\n .none$() \/\/ this will clean up all projected fields that might already exist\r\n .id()\r\n )\r\n )\r\n )\r\n\r\n\/\/ proj1 will have { user { id order { total product { name } } } }\r\n\/\/ proj2 will have { user { id order { total product { name price } } } }\r\n\/\/ proj3 will have { user { id order { total product { id } } } }\r\n```\r\n\r\nHow does this sound to you?","issue_id":1660627226099,"origin_id":1200314194,"user_origin_id":2664706,"create_time":1659224858,"update_time":1659272668,"id":1666217555115,"updated_at":"2022-10-19T22:12:35.114000Z","created_at":"2022-10-19T22:12:35.114000Z"},{"_id":"63507653ea01ec786e748be4","body":"Hi @kobylynskyi , \r\n\r\nThere are two comments on your idea:\r\n\r\n1. The current response projection class does not support deduplication of fields. If we take your idea, the fields addition mechanism would be complex, as we need to deduplicate the field tree when we add a new field.\r\n2. I am fine with making the response projections immutable. But from your idea, if we want to build a response projection on top of another, we still need to hard code adding every fields. Shall we create a constructor or factory method that take in a list of response projection and internally combine into one? If so, we could reach an optimal position that we could maintain a response projection for each business requirement, and merge them if having multiple requirements.\r\n\r\nPlease let me know your comment. Thanks.","issue_id":1660627226099,"origin_id":1203836518,"user_origin_id":48465727,"create_time":1659526673,"update_time":1659526673,"id":1666217555117,"updated_at":"2022-10-19T22:12:35.117000Z","created_at":"2022-10-19T22:12:35.117000Z"},{"_id":"63507653ea01ec786e748be5","body":"@ruipliu, thanks for your response.\r\n\r\nTo your 1st point:\r\n> The current response projection class does not support deduplication of fields. If we take your idea, the fields addition mechanism would be complex, as we need to deduplicate the field tree when we add a new field.\r\n\r\nThis should not be a problem. I think we can use a `LinkedHashMap` instead of a `List` for storing response projection fields (for deduplication purposes):\r\nhttps:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/blob\/7364f7dd7d5696f73667f713e3a8e30a526d2326\/src\/main\/java\/com\/kobylynskyi\/graphql\/codegen\/model\/graphql\/GraphQLResponseProjection.java#L13\r\n\r\n\r\nTo your 2nd point:\r\n> I am fine with making the response projections immutable. But from your idea, if we want to build a response projection on top of another, we still need to hard code adding every fields. Shall we create a constructor or factory method that take in a list of response projection and internally combine into one? If so, we could reach an optimal position that we could maintain a response projection for each business requirement, and merge them if having multiple requirements.\r\n\r\nWhat do you mean by `hard code adding every fields`? \r\nAlso `take in a list of response projection and internally combine into one` - how does this become beneficial? Can you provide an example?\r\nAlso, note that even today you can do the following:\r\n```java\r\nProductRespProj minimalProductDetails = new ProductRespProj()\r\n .id().name())\r\nProductRespProj extendedProductDetails = new ProductRespProj()\r\n .id().name().price().sku())\r\n\r\nParentRespProj proj1WithMinimalProductDetails = new ParentRespProj()\r\n .user(new UserRespProj()\r\n .id()\r\n .order(new OrderRespProj()\r\n .total()\r\n .product(minimalProductDetails)\r\n )\r\n )\r\nParentRespProj proj2WithExtendedProductDetails = new ParentRespProj()\r\n .user(new UserRespProj()\r\n .id()\r\n .order(new OrderRespProj()\r\n .total()\r\n .product(extendedProductDetails)\r\n )\r\n )\r\n```\r\nAnd with a \"constructor\" thing it will make a code cleaner by extending `proj2` by reusing `proj1`:\r\n```java\r\nParentRespProj proj2WithExtendedProductDetails = new ParentRespProj(proj1WithMinimalProductDetails)\r\n .user(new UserRespProj()\r\n .order(new OrderRespProj()\r\n .product(extendedProductDetails)\r\n )\r\n )\r\n```\r\nDo you see how we can make projections more reusable? Please provide code samples if you can.","issue_id":1660627226099,"origin_id":1204575734,"user_origin_id":2664706,"create_time":1659568802,"update_time":1659735336,"id":1666217555120,"updated_at":"2022-10-19T22:12:35.120000Z","created_at":"2022-10-19T22:12:35.120000Z"},{"_id":"664a898c4ecfda50de15d46f","body":"Hi @kobylynskyi , sorry for the late reply. I've\u00a0consolidated the idea and let's take the below example:\r\n\r\n#### Suppose we have a GQL model\r\n```\r\naccount: Account\r\n\tuser: Person\r\n\t\tname: PersonName\r\n\t\t\tfirst_name: string\r\n\t\t\tlast_name: string\r\n\torder: Order\r\n\t\tproduct: Product\r\n\t\t\tname: string\r\n\t\trecipient: Person\r\n\t\t\tname: PersonName\r\n\t\t\t\tfirst_name: string\r\n\t\t\t\tlast_name: string\t\r\n```\r\n#### And a Java Application\r\nThe Java application is designed to listen and orchestrate data loading requirements and combine a GraphQL request. And the GraphQL service is used to load data from different data storages.\r\n \r\n#### Consider the Java application supports two data loading requirements, which allows clients to select:\r\n\r\n- A. To load names of all product purchased by this account (`account.product.name`)\r\n- B. To load all person names occurred in this account (`account.user.name` and `account.product.recipient.name`)\r\n\r\nSome of the clients needs requirement A, some needs B, while some needs A + B. They could specify their requirements through a parameter when invoking the Java application.\r\n\r\nIn the application, we need to maintain `projectionA`, `projectionB` and `projectionAB` like below:\r\n```java\r\nAccountResponseProjection projectionA = new AccountProjection().order(\r\n\t\tnew OrderResponseProjection().product(\r\n\t\t\t\tnew ProductResponseProjection().name()));\r\n\r\nPersonNameResponseProjection personNameFragment = \r\n\t\tnew PersonNameResponseProjection().firstName().lastName();\r\n\r\nAccountResponseProjection projectionB = new AccountProjection()\r\n\t\t.user(new PersonResponseProjection().name(personNameFragment))\r\n\t\t.order(new OrderResponseProjection()\r\n\t\t\t\t.recipient(new PersonResponseProjection().name(personNameFragment)));\r\n\r\nAccountResponseProjection projectionAB = new AccountProjection()\r\n\t\t.user(new PersonResponseProjection().name(personNameFragment))\r\n\t\t.order(new OrderResponseProjection()\r\n\t\t\t\t.recipient(new PersonResponseProjection().name(personNameFragment))\r\n\t\t\t\t.product(new ProductResponseProjection().name()));\r\n```\r\n\r\nConsider if we have tens of requirements, we should list out all combinations of requirements to make GQL call, which creates quite a lot of redundant codes.\r\n\r\n#### Two possible options that could both make the response projection reusable and keep it immutable:\r\n\r\n##### Option 1: Make constructor accept list of response projections\r\n\r\n```java\r\nAccountResponseProjection projectionAB = new AccountProjection(Arrays.asList(projectionA, projectionB));\r\n```\r\n\r\n##### Option 2: Factory method to build response projections\r\n```java\r\nAccountResponseProjection projectionAB = AccountResponseProjectionFactory.combine(projectionA, projectionB);\r\n```\r\n\r\n> Please note that the below approach is not feasible as `ResponseProjection.field` is immutable.\r\n> ```java\r\n> AccountResponseProjection projectionAB = new AccountProjection(projectionB)\r\n> \t\t.order(new OrderResponseProjection().product(new ProductResponseProjection().name());\r\n> \/*\r\n> output has duplicate fields:\r\n> account {\r\n> \tuser { name { firstName lastName } }\r\n> \torder { recipient { name { firstName lastName } } }\r\n> \torder { product { name } }\r\n> }\r\n> *\/\r\n> ```\r\n\r\n#### Tree iteration and field combination logic have to be implemented.\r\nNo matter which option we take, we need to add response projection combining logic. \r\nApproaches:\r\n1. Print out the field trees from projections\r\n2. Iterate through trees\r\n3. Construct a new projection\r\n\r\n**Advantage:** The logic is independent to the existing response projection code, so it would not have any impact on the existing code base.\r\n\r\n**Challenge:** The combination logic should be written in generic way and apply to the auto-generated projection classes.\r\n\r\n@kobylynskyi Is my explanation clear to understand? Any comments on this approach?","issue_id":1660627226099,"origin_id":1418820325,"user_origin_id":48465727,"create_time":1675677876,"update_time":1675677876,"id":1716160908705,"updated_at":"2024-05-19T23:21:48.705000Z","created_at":"2024-05-19T23:21:48.705000Z"},{"_id":"664a898c4ecfda50de15d470","body":"@ruipliu I like the approach with combining multiple projections!","issue_id":1660627226099,"origin_id":1435829351,"user_origin_id":2664706,"create_time":1676775699,"update_time":1676775699,"id":1716160908710,"updated_at":"2024-05-19T23:21:48.709000Z","created_at":"2024-05-19T23:21:48.709000Z"},{"_id":"664a898c4ecfda50de15d471","body":"@kobylynskyi \r\nMay I know if you have any plan to make code change and add this feature?\r\notherwise I think I can contribute with a PR.","issue_id":1660627226099,"origin_id":1436011020,"user_origin_id":48465727,"create_time":1676818779,"update_time":1676818779,"id":1716160908713,"updated_at":"2024-05-19T23:21:48.712000Z","created_at":"2024-05-19T23:21:48.712000Z"},{"_id":"664a898c4ecfda50de15d472","body":"Yes, I am planning to work on this in the nearest days. Will keep you posted.","issue_id":1660627226099,"origin_id":1436073871,"user_origin_id":2664706,"create_time":1676835515,"update_time":1676835515,"id":1716160908716,"updated_at":"2024-05-19T23:21:48.716000Z","created_at":"2024-05-19T23:21:48.716000Z"},{"_id":"664a898c4ecfda50de15d473","body":"@ruipliu, plz check the initial version of the \"combining\" logic.\r\nSample unit-test that might be helpful to understand the usage and output of the joined projection:\r\nhttps:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/pull\/1031\/files#diff-bfa4c44db3c448e71ef40d93665210a3fcbbfa17cddea25bb1e4fb3cb1f71262R73-R74\r\n\r\nI am open to your suggestions on how to set alias \/ input parameters if provided values in the incoming projection objects are different. For example: `{ ids1: id(from: 1 to: 10) }` + `{ ids2: id(from: 11 to: 20) }`. Ideally such situations should not happen, but maybe you have any idea on which alias \/ input parameters we should put in the resulting projection.\r\n\r\n_Also, TBD for this feature: Kotlin and Scala support._","issue_id":1660627226099,"origin_id":1436199740,"user_origin_id":2664706,"create_time":1676859034,"update_time":1676920947,"id":1716160908729,"updated_at":"2024-05-19T23:21:48.728000Z","created_at":"2024-05-19T23:21:48.728000Z"},{"_id":"664a898c4ecfda50de15d474","body":"@kobylynskyi Thanks. I checked the code change.\r\n\r\nFrom my knowledge, GraphQL service could support duplicate field with different alias. For example, this query is supported, as the alias are different:\r\n```graphql\r\nquery { \r\n query: {\r\n ids1: id (from: 1 to: 10)\r\n ids2: id (from: 11 to: 20)\r\n }\r\n}\r\n```\r\nThe result would be `query { ids1: [ xxx ], ids2: [xxx] }`.\r\n\r\nHowever, I'm not too sure whether field with the same alias and different parameters is supported by GraphQL service, but it is definitely a bad practice.\r\n\r\n### So my conclusion is:\r\n- duplicate field with different alias should be kept, no matter if the parameters are the same or different\r\n- duplicate field with same or no alias should not be acceptable, merge is needed. If parameter is different, it could not be merged and will cause problem. \r\n\r\nPossible solution\r\n1. make the key of `LinkedHashMap<key, value> fields` a pair: `Pair<fieldName, alias>`\r\n2. may throw exception when field with same name and alia but different parameter is added to the `fields`. In other words, projection combination ability can choose not to support duplicate field with same alias and different parameters.\r\n","issue_id":1660627226099,"origin_id":1436964160,"user_origin_id":48465727,"create_time":1676897451,"update_time":1676897451,"id":1716160908733,"updated_at":"2024-05-19T23:21:48.732000Z","created_at":"2024-05-19T23:21:48.732000Z"},{"_id":"664a898c4ecfda50de15d475","body":"Thanks for the heads-up.\r\nI confirm that if the field has the same (null or non-null) alias **and different parameters** then it leads to a problem when executing a query and the library can throw some kind of `IllegalArgumentException` because we know in advance that this is an invalid response projection.","issue_id":1660627226099,"origin_id":1437455367,"user_origin_id":2664706,"create_time":1676921030,"update_time":1676921030,"id":1716160908738,"updated_at":"2024-05-19T23:21:48.737000Z","created_at":"2024-05-19T23:21:48.737000Z"},{"_id":"664a898c4ecfda50de15d476","body":"Will include the feature in the upcoming release. Stay tuned","issue_id":1660627226099,"origin_id":1439925355,"user_origin_id":2664706,"create_time":1677068242,"update_time":1677068242,"id":1716160908742,"updated_at":"2024-05-19T23:21:48.742000Z","created_at":"2024-05-19T23:21:48.742000Z"}] comment

### Discussed in https://github.com/kobylynskyi/graphql-java-codegen/discussions/984 Originally posted by **ruipliu** July 22, 2022 This is to support complex use cases from client side building queries. Now the response projections only have builder...

enhancement
good-first-issue

spring-graphql compatible code generation

[{"_id":"63507917cecf4e081a195e9e","body":"The custom annotations mapping you provided works well for me too.\r\n\r\nThe main issue for me is not being able to annotate the arguments with @Argument.\r\n\r\nMaybe a customResolverArgumentAnnotations option would be good? It could just take a list of annotations to be applied to all arguments. But not the DataFetchingEnvironment etc","issue_id":1660627226102,"origin_id":1175263565,"user_origin_id":2249693,"create_time":1657039132,"update_time":1657039132,"id":1666218263393,"updated_at":"2022-10-19T22:24:23.393000Z","created_at":"2022-10-19T22:24:23.393000Z"},{"_id":"63507917cecf4e081a195e9f","body":"We recently adopted [Spring for GraphQL](https:\/\/docs.spring.io\/spring-graphql\/docs\/current\/reference\/html\/) and set up _graphql-java-codegen_ today.\r\n\r\nThanks to the comment of @msl-at-fcb we've got up and running relatively easy. \r\n\r\nIn addition to using _customAnnotationsMapping_ for the root types `Query`, `Mutation` and `Subscription`, we also added `@SchemaMapping` for every field declared in `fieldsWithResolvers`.\r\n\r\n```kotlin\r\ntasks {\r\n named<GraphQLCodegenGradleTask>(\"graphqlCodegen\") {\r\n \/\/ ...\r\n\r\n fieldsWithResolvers = setOf(\"Foo.bar\")\r\n val customResolverMappings = fieldsWithResolvers.associateWith { field ->\r\n val type = field.substringBefore('.')\r\n listOf(\"\"\"org.springframework.graphql.data.method.annotation.SchemaMapping(typeName = \"$type\")\"\"\")\r\n }\r\n customAnnotationsMapping.addAll(customResolverMappings)\r\n }\r\n}\r\n```\r\n\r\nThis works fine but involves quite some boilerplate which is likely to to be duplicated for other projects as well. Thus I would love to see explicit support for Spring for GraphQL being part of _graphql-java-codegen_.\r\n\r\nBeside the aforementioned annotations I would like to see support for [@BatchMapping](https:\/\/docs.spring.io\/spring-graphql\/docs\/current-SNAPSHOT\/reference\/html\/#controllers-batch-mapping). This however we did not get to work as I don't see any way to tell _graphql-java-codegen_ to generate a mapping of e.g. `List<T>` to `List<R>` (or one of the other supported types) instead of `T` to `R`. If that's possible today I would love to hear how.\r\n\r\n-----\r\n\r\nDisclaimer: There might be some typos in the code above, as I'm writing this on my phone right now. But I assume one gets the idea.","issue_id":1660627226102,"origin_id":1179313251,"user_origin_id":16666115,"create_time":1657309787,"update_time":1657309921,"id":1666218263397,"updated_at":"2022-10-19T22:24:23.397000Z","created_at":"2022-10-19T22:24:23.397000Z"},{"_id":"63507917cecf4e081a195ea0","body":"Added support of 2 configs: `resolverArgumentAnnotations` and `parametrizedResolverAnnotations` which should solve abovementioned problems:\r\n\r\n### `resolverArgumentAnnotations`\r\n```groovy\r\n \"resolverArgumentAnnotations\": [\"org.springframework.graphql.data.method.annotation.Argument\"]\r\n```\r\nThis will add the specified annotation to every argument in every method in each Query\/Mutation\/Subscription resolver:\r\n```java\r\npublic interface QueryResolver {\r\n String version(graphql.schema.DataFetchingEnvironment env) throws Exception;\r\n\r\n java.util.List<Event> eventsByCategoryAndStatus(@javax.validation.constraints.NotNull @org.springframework.graphql.data.method.annotation.Argument String categoryId, @org.springframework.graphql.data.method.annotation.Argument EventStatus status, graphql.schema.DataFetchingEnvironment env) throws Exception;\r\n\r\n Event eventById(@javax.validation.constraints.NotNull @org.springframework.graphql.data.method.annotation.Argument String id, graphql.schema.DataFetchingEnvironment env) throws Exception;\r\n}\r\n```\r\n\r\n### `parametrizedResolverAnnotations`\r\n```groovy\r\n \"parametrizedResolverAnnotations\": [\"org.springframework.graphql.data.method.annotation.SchemaMapping(typeName=\"{{TYPE_NAME}}\")\"]\r\n```\r\nThis will add the specified annotation to every field resolver method:\r\n```java\r\npublic interface EventPropertyResolver {\r\n @org.springframework.graphql.data.method.annotation.SchemaMapping(typeName=\"EventProperty\")\r\n int intVal(EventPropertyTO eventProperty) throws Exception;\r\n\r\n @org.springframework.graphql.data.method.annotation.SchemaMapping(typeName=\"EventProperty\")\r\n java.util.List<EventPropertyTO> child(EventPropertyTO eventProperty, Integer first, Integer last) throws Exception;\r\n}\r\n```\r\nLet me know what you think.","issue_id":1660627226102,"origin_id":1200496176,"user_origin_id":2664706,"create_time":1659300028,"update_time":1659300028,"id":1666218263401,"updated_at":"2022-10-19T22:24:23.400000Z","created_at":"2022-10-19T22:24:23.400000Z"},{"_id":"63507917cecf4e081a195ea1","body":"Very nice, thanks for adding this @kobylynskyi! We'll migrate as soon as it's available.\r\n\r\nAny chance for adding `@BatchMapping` support somehow? That would complete the fundamental Spring support from my point of view. ","issue_id":1660627226102,"origin_id":1200499698,"user_origin_id":16666115,"create_time":1659301337,"update_time":1659301337,"id":1666218263404,"updated_at":"2022-10-19T22:24:23.404000Z","created_at":"2022-10-19T22:24:23.404000Z"},{"_id":"63507917cecf4e081a195ea2","body":"@EndzeitBegins the problem with supporting `@BatchMapping` is that the method signature is completely off from the field resolver that we already generate today:\r\n```java\r\nFieldType field(Type type); \/\/ that's what we generate today\r\nMono<Map<Type, FieldType>> field(List<Type> types); \/\/ that's what should be generated to support @BatchMapping\r\n```","issue_id":1660627226102,"origin_id":1200504875,"user_origin_id":2664706,"create_time":1659303399,"update_time":1659303399,"id":1666218263407,"updated_at":"2022-10-19T22:24:23.406000Z","created_at":"2022-10-19T22:24:23.406000Z"},{"_id":"63507917cecf4e081a195ea3","body":"This looks perfect, will also give it a try as soon as it's available, thanks!","issue_id":1660627226102,"origin_id":1200874186,"user_origin_id":2249693,"create_time":1659341892,"update_time":1659341892,"id":1666218263413,"updated_at":"2022-10-19T22:24:23.412000Z","created_at":"2022-10-19T22:24:23.412000Z"},{"_id":"63507917cecf4e081a195ea4","body":"> @EndzeitBegins the problem with supporting `@BatchMapping` is that the method signature is completely off from the field resolver that we already generate today:\r\n> \r\n> ```java\r\n> FieldType field(Type type); \/\/ that's what we generate today\r\n> Mono<Map<Type, FieldType>> field(List<Type> types); \/\/ that's what should be generated to support @BatchMapping\r\n> ```\r\n\r\nI'm aware of that. Actually, there are multiple type signatures supported by Spring for GraphQL, e.g. `List<Type> -> List<FieldType>`. I was just hoping one might be able to configure which fields should be resolved using a batch mapping, similar to the existing `fieldsWithResolvers`, e.g. `fieldsWithBatchResolvers`. Additionally being able to configure which type signature to generate would be nice. \r\n\r\nBut I can understand if that's a lot more difficult to support than just adding additional annotations. ","issue_id":1660627226102,"origin_id":1201380171,"user_origin_id":16666115,"create_time":1659368970,"update_time":1659368970,"id":1666218263416,"updated_at":"2022-10-19T22:24:23.415000Z","created_at":"2022-10-19T22:24:23.415000Z"},{"_id":"63507917cecf4e081a195ea5","body":"Given @kobylynskyi's other helpful commits for the other annotations, is it implied that for `@QueryMapping`, `@MutationMapping`, and `@SubscriptionMapping` we will be doing it the way @msl-at-fcb described, i.e. `customAnnotationsMapping`?\r\n\r\nIs that configuration expressible with the Maven plugin?\r\n\r\n```groovy\r\n \"customAnnotationsMapping\": {\r\n \"^Query\\\\.\\\\w+$\": [\"org.springframework.graphql.data.method.annotation.QueryMapping\"],\r\n \"^Mutation\\\\.\\\\w+$\": [\"org.springframework.graphql.data.method.annotation.MutationMapping\"],\r\n \"^Subscription\\\\.\\\\w+$\": [\"org.springframework.graphql.data.method.annotation.SubscriptionMapping\"]\r\n }\r\n```\r\n\r\nMy understanding was this would have to map to something like:\r\n\r\n```xml\r\n<customAnnotationsMapping>\r\n <^Query\\\\.\\\\w+$>\r\n <annotation>org.springframework.graphql.data.method.annotation.QueryMapping<\/annotation>\r\n <\/^Query\\\\.\\\\w+$>\r\n<\/customAnnotationsMapping>\r\n```\r\n\r\nWhich I don't believe is expressible in xml unless I'm missing some way of escaping it.\r\n\r\nIf I understand correctly it is these lines which allow the key to be a pattern, which would appear to explain how the configuration@msl-at-fcb provided works, I'm just not sure how to express it in maven.\r\n\r\nhttps:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/blob\/9a64c33bedbff81ce849f253a7a7644eab00cc9d\/src\/main\/java\/com\/kobylynskyi\/graphql\/codegen\/mapper\/AnnotationsMapper.java#L134-L139\r\n\r\nIf it's not currently expressible as-is, I wonder if it can be passed as a tag attribute instead? e.g.\r\n\r\n```xml\r\n<Query pattern=\"^Query\\\\.\\\\w+$\">\r\n```\r\n\r\nI'm not sure if that's possible with Maven though since it would appear that the code already receives the tag as a string, but I admit I know nothing about maven plugins:\r\n\r\nhttps:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/blob\/0198f41aacfd8dc19e5322f8436d4d923d4b7737\/plugins\/maven\/graphql-java-codegen-maven-plugin\/src\/main\/java\/io\/github\/kobylynskyi\/graphql\/codegen\/GraphQLCodegenMojo.java#L671","issue_id":1660627226102,"origin_id":1206212289,"user_origin_id":84680,"create_time":1659689776,"update_time":1659689776,"id":1666218263419,"updated_at":"2022-10-19T22:24:23.419000Z","created_at":"2022-10-19T22:24:23.419000Z"},{"_id":"63507917cecf4e081a195ea6","body":"@blaenk Yeah I'm not sure it is possible directly in your pom but you can just use the .json config instead so your json config would include this:\r\n```\r\n\"customAnnotationsMapping\": {\r\n \"^Query\\\\.\\\\w+$\" : [\"org.springframework.graphql.data.method.annotation.QueryMapping\"],\r\n \"^Mutation\\\\.\\\\w+$\" : [\"org.springframework.graphql.data.method.annotation.MutationMapping\"],\r\n \"^Subscription\\\\.\\\\w+$\" : [\"org.springframework.graphql.data.method.annotation.SubscriptionMapping\"]\r\n }\r\n```\r\n\r\nAnd in your pom:\r\n\r\n```\r\n <configuration>\r\n <configurationFiles>\r\n <configurationFile>${project.basedir}\/codegenConfig.json<\/configurationFile>\r\n <\/configurationFiles>\r\n <!-- all config options:\r\n https:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/blob\/master\/docs\/codegen-options.md\r\n -->\r\n <graphqlSchemas>\r\n <rootDir>${project.basedir}\/src\/main\/resources\/graphql<\/rootDir>\r\n <\/graphqlSchemas>\r\n <outputDir>${project.build.directory}\/generated-sources\/graphql<\/outputDir>\r\n <\/configuration>\r\n```\r\n\r\nUsing the json config makes your pom way less cluttered too","issue_id":1660627226102,"origin_id":1206221291,"user_origin_id":2249693,"create_time":1659690366,"update_time":1659690366,"id":1666218263422,"updated_at":"2022-10-19T22:24:23.422000Z","created_at":"2022-10-19T22:24:23.422000Z"},{"_id":"63507917cecf4e081a195ea7","body":"Thank you @JamesPeters98 I completely missed that a JSON config was even possible. It did seem like that's what that code snippet was (JSON) but I thought for sure there couldn't be a JSON config mechanism and assumed it to be Groovy\/Gradle!\r\n\r\nThanks again I appreciate it!","issue_id":1660627226102,"origin_id":1206223558,"user_origin_id":84680,"create_time":1659690515,"update_time":1659690515,"id":1666218263425,"updated_at":"2022-10-19T22:24:23.424000Z","created_at":"2022-10-19T22:24:23.424000Z"},{"_id":"63507917cecf4e081a195ea8","body":"A bit off topic, but...\r\n\r\n> Using the json config makes your pom way less cluttered too\r\n\r\nYep, that's pretty much our setup. Anything that needs to know about maven goes in pom.xml (eg `<rootDir>${project.basedir}...<\/rootDir>` but then the rest goes into dedicated configuration files (graphql-codegen.json) - try to keep the two as separate as we can.","issue_id":1660627226102,"origin_id":1206270243,"user_origin_id":96451448,"create_time":1659693519,"update_time":1659693519,"id":1666218263427,"updated_at":"2022-10-19T22:24:23.427000Z","created_at":"2022-10-19T22:24:23.427000Z"},{"_id":"63507917cecf4e081a195ea9","body":"\ud83d\ude80 Released version 5.5.0 today which contains new configs: `resolverArgumentAnnotations` and `parametrizedResolverAnnotations`\r\nFor usage please refer to my previous comment: https:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/issues\/983#issuecomment-1200496176\r\n\r\nSupport for `@BatchMapping` will be addressed in future releases once we come up with a way of defining the desired method signature.","issue_id":1660627226102,"origin_id":1242980310,"user_origin_id":2664706,"create_time":1662907559,"update_time":1662907559,"id":1666218263431,"updated_at":"2022-10-19T22:24:23.431000Z","created_at":"2022-10-19T22:24:23.431000Z"},{"_id":"63507917cecf4e081a195eaa","body":"@kobylynskyi , can we also add a configuration to add arbitrary parameters in generated resolvers? With this, we could provide a list of additional parameter names\/types and also do not need `generateDataFetchingEnvironmentArgumentInApis` anymore.\r\n\r\nBest,\r\nPhilipp","issue_id":1660627226102,"origin_id":1275742796,"user_origin_id":11447121,"create_time":1665561178,"update_time":1665561178,"id":1666218263435,"updated_at":"2022-10-19T22:24:23.434000Z","created_at":"2022-10-19T22:24:23.434000Z"}] comment

Now that spring-graphql is 1.0 and reasonably stable, it would be good to provide first class support for their structures. Currently @QueryMapping, @MutationMapping and @SubscriptionMapping can be shoe-horned in via...

enhancement
help-wanted

Add annotations to JavaBean getters

[{"_id":"6350735d8041c95dfb0ed728","body":"Does this need any more changes? Not sure why the sonar build failed?","issue_id":1660627226106,"origin_id":1195243838,"user_origin_id":2249693,"create_time":1658827770,"update_time":1658827770,"id":1666216797743,"updated_at":"2022-10-19T21:59:57.742000Z","created_at":"2022-10-19T21:59:57.742000Z"}] comment

--- ### Description Related to #958 Fixes the test failures in the last PR --- Changes were made to: - [x] Codegen library - Java - [ ] Codegen library...

question
needs-work

Java Time types cannot be used when serialising GraphQlRequest

[{"_id":"635070063056137e26570108","body":"Hi @chusmc\r\nThanks for providing such detailed information.\r\nWhat if you manually register required modules during the application init\/startup phase in the following way:\r\n`GraphQLRequestSerializer.OBJECT_MAPPER.registerModule(new SimpleModule().addSerializer(new OffsetTimeSerializer()));`\r\nThe working test case for `java.time` classes can be found here:\r\nhttps:\/\/github.com\/kobylynskyi\/graphql-java-codegen\/blob\/f291209d204376881e886473c22bf4fdbc3af5ad\/src\/test\/java\/com\/kobylynskyi\/graphql\/codegen\/model\/graphql\/GraphQLRequestSerializerTest.java#L303-L317\r\n\r\nPlease let me know how it goes.\r\nAlso, I've added the description of `useObjectMapperForRequestSerialization` to the documentation. Thanks for pointing this out!","issue_id":1660627226109,"origin_id":985131181,"user_origin_id":2664706,"create_time":1638493980,"update_time":1638494055,"id":1666215942256,"updated_at":"2022-10-19T21:45:42.256000Z","created_at":"2022-10-19T21:45:42.256000Z"},{"_id":"635070063056137e26570109","body":"Ok. Thanks\r\nwe weren't sure we should reconfigure the internal OBJECT_MAPPER \r\n\r\nWe will give it a go, as its just some unit tests,\r\n\r\nIs it possible to suggest, that GraphQLRequestSerializer could be configured with an external injected ObjectMaper also?\r\n\r\nRegards","issue_id":1660627226109,"origin_id":986716579,"user_origin_id":32822021,"create_time":1638792561,"update_time":1638792561,"id":1666215942260,"updated_at":"2022-10-19T21:45:42.259000Z","created_at":"2022-10-19T21:45:42.259000Z"},{"_id":"635070063056137e2657010b","body":"I am bumping into same problem as well and have created a sample repo [here](https:\/\/github.com\/mparthasarathi\/demo)\r\ncould you please check and advise?\r\nWe're expecting the serialised query like below\r\n```\r\nquery reviews { reviews: reviews(searchInput: { submittedDate: \"2022-07-15\" }){ starScore } }\r\n```\r\nbut the date is unquoted","issue_id":1660627226109,"origin_id":1185319483,"user_origin_id":30927255,"create_time":1657874552,"update_time":1657874552,"id":1666215942264,"updated_at":"2022-10-19T21:45:42.264000Z","created_at":"2022-10-19T21:45:42.264000Z"},{"_id":"635070063056137e2657010d","body":"> \r\n`use <useObjectMapperForRequestSerialization>Date<\/useObjectMapperForRequestSerialization>`\r\n","issue_id":1660627226109,"origin_id":1235662457,"user_origin_id":27200563,"create_time":1662134105,"update_time":1662134135,"id":1666215942271,"updated_at":"2022-10-19T21:45:42.271000Z","created_at":"2022-10-19T21:45:42.271000Z"},{"_id":"635070063056137e2657010e","body":"Thanks @jay3047 \r\nNow I am getting below error\r\n\r\n`Java 8 date\/time type `java.time.LocalDate` not supported by default: add Module \"com.fasterxml.jackson.datatype:jackson-datatype-jsr310\" to enable handling`\r\n\r\nHow to customize the ObjectMapper thats being created in `com.kobylynskyi.graphql.codegen.utils.Utils.OBJECT_MAPPER`\r\n","issue_id":1660627226109,"origin_id":1236725251,"user_origin_id":30927255,"create_time":1662368259,"update_time":1662368259,"id":1666215942274,"updated_at":"2022-10-19T21:45:42.274000Z","created_at":"2022-10-19T21:45:42.274000Z"},{"_id":"635070063056137e2657010f","body":"> Thanks @jay3047 Now I am getting below error\r\n> \r\n> `Java 8 date\/time type `java.time.LocalDate` not supported by default: add Module \"com.fasterxml.jackson.datatype:jackson-datatype-jsr310\" to enable handling`\r\n> \r\n> How to customize the ObjectMapper thats being created in `com.kobylynskyi.graphql.codegen.utils.Utils.OBJECT_MAPPER`\r\n\r\n GraphQLRequestSerializer.OBJECT_MAPPER.registerModule(\r\n new SimpleModule().addSerializer(new ZonedDateTimeSerializer()));\r\n\r\n\r\n UpdateDateMutationRequest updateDateMutationRequest = new UpdateDateMutationRequest();\r\n DateInput input = new DateInput();\r\n input.setDateTime(ZonedDateTime.parse(\"2020-07-30T22:17:17.884-05:00[America\/Chicago]\"));\r\n updateDateMutationRequest.setInput(input);\r\n GraphQLRequest graphQLRequest = new GraphQLRequest(updateDateMutationRequest);","issue_id":1660627226109,"origin_id":1236750183,"user_origin_id":29496873,"create_time":1662369673,"update_time":1662369673,"id":1666215942278,"updated_at":"2022-10-19T21:45:42.277000Z","created_at":"2022-10-19T21:45:42.277000Z"},{"_id":"635070063056137e26570110","body":"One mentioned by @jxnu-liguobin does work , but \r\nI created custom Deserializer something like below and it worked \r\n\r\n`GraphQLRequestSerializer.OBJECT_MAPPER.registerModule(\r\n SimpleModule().addSerializer(\r\n DateSerializerKotlin()\r\n )\r\n )\r\n`\r\n\r\n`class DateSerializerKotlin : JsonSerializer<LocalDate>() {\r\n override fun serialize(\r\n localDate: LocalDate,\r\n gen: JsonGenerator?,\r\n serializers: SerializerProvider\r\n ) {\r\n val formatter = DateTimeFormatter.ofPattern(\"yyyy-MM-dd\")\r\n val formattedString: String = localDate?.format(formatter)\r\n gen!!.writeString(formattedString)\r\n }\r\n\r\n override fun handledType(): Class<LocalDate>? {\r\n return LocalDate::class.java\r\n }\r\n\r\n}`\r\n\r\n\r\n","issue_id":1660627226109,"origin_id":1236759213,"user_origin_id":27200563,"create_time":1662370149,"update_time":1662371361,"id":1666215942281,"updated_at":"2022-10-19T21:45:42.280000Z","created_at":"2022-10-19T21:45:42.280000Z"},{"_id":"635070063056137e26570111","body":"> One mentioned by @jxnu-liguobin does work , but I created custom Deserializer something like below and it worked\r\n> \r\n> GraphQLRequestSerializer.OBJECT_MAPPER.registerModule( SimpleModule().addSerializer( DateSerializerKotlin() ) )\r\n> \r\n> class DateSerializerKotlin : JsonSerializer() { override fun serialize( localDate: LocalDate, gen: JsonGenerator?, serializers: SerializerProvider ) { val formatter = DateTimeFormatter.ofPattern(\"yyyy-MM-dd\") val formattedString: String = localDate?.format(formatter) gen!!.writeString(formattedString) }\r\n> \r\n> ```\r\n> override fun handledType(): Class<LocalDate>? {\r\n> return LocalDate::class.java\r\n> }\r\n> ```\r\n> \r\n> }\r\n\r\nThis is good if you need this more flexible format. \ud83d\udc4d\ud83c\udffb ","issue_id":1660627226109,"origin_id":1236763680,"user_origin_id":29496873,"create_time":1662370370,"update_time":1662370370,"id":1666215942283,"updated_at":"2022-10-19T21:45:42.283000Z","created_at":"2022-10-19T21:45:42.283000Z"}] comment

## Issue Description We are trying to use the code-gen to generate the GraphQlRequest payload, from a graphql model with custom scalar types of type java.time We have these custom...

bug
question

Add annotations to JavaBean getters

[{"_id":"6350769fea01ec786e748c12","body":"@ludovicc looks good. but could you please change the target branch to **develop**?","issue_id":1660627226112,"origin_id":1033293906,"user_origin_id":2664706,"create_time":1644375688,"update_time":1644375688,"id":1666217631528,"updated_at":"2022-10-19T22:13:51.527000Z","created_at":"2022-10-19T22:13:51.527000Z"},{"_id":"6350769fea01ec786e748c13","body":"@ludovicc can you please fix the build?","issue_id":1660627226112,"origin_id":1059953796,"user_origin_id":2664706,"create_time":1646569660,"update_time":1646569660,"id":1666217631531,"updated_at":"2022-10-19T22:13:51.530000Z","created_at":"2022-10-19T22:13:51.530000Z"},{"_id":"6350769fea01ec786e748c14","body":"Any chance you can fix the build @ludovicc? This would be really useful for me too","issue_id":1660627226112,"origin_id":1184144997,"user_origin_id":2249693,"create_time":1657786816,"update_time":1657786816,"id":1666217631533,"updated_at":"2022-10-19T22:13:51.532000Z","created_at":"2022-10-19T22:13:51.532000Z"},{"_id":"6350769fea01ec786e748c15","body":"Actually, I just realised I need this for Setters as well","issue_id":1660627226112,"origin_id":1184156051,"user_origin_id":2249693,"create_time":1657787455,"update_time":1657787455,"id":1666217631536,"updated_at":"2022-10-19T22:13:51.535000Z","created_at":"2022-10-19T22:13:51.535000Z"}] comment

### Description Add nonnull and other annotations to the getter method in addition to the field declaration. Some Java Bean introspection tools can only use annotations declared on the getter/setter...

needs-work

--- ### Description Related to #ISSUE_NUMBER --- Changes were made to: - [# ] Codegen library - Java - [ ] Codegen library - Kotlin - [ ] Codegen library...

needs-work

GraphQL Schema with multi-level operations fails to create GraphQLOperationRequest

[{"_id":"63506b4f8041c95dfb0ecf27","body":"@vpandey3 please provide the code that you expect to be generated","issue_id":1660627226119,"origin_id":1055948486,"user_origin_id":2664706,"create_time":1646175873,"update_time":1646175873,"id":1666214735703,"updated_at":"2022-10-19T21:25:35.703000Z","created_at":"2022-10-19T21:25:35.703000Z"},{"_id":"63506b4f8041c95dfb0ecf28","body":"Hello , Thanks for looking into this\r\n\r\n\r\nexpected - \r\n```package com.atlassian.Product.streams.model.schema;\r\n\r\nimport com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation;\r\nimport com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest;\r\nimport java.util.HashSet;\r\nimport java.util.LinkedHashMap;\r\nimport java.util.Map;\r\nimport java.util.Objects;\r\nimport java.util.Set;\r\n\r\[email protected](\r\n value = \"com.kobylynskyi.graphql.codegen.GraphQLCodegen\",\r\n date = \"2022-03-01T13:46:37-0600\"\r\n)\r\npublic class ProductQueryRequest implements GraphQLOperationRequest {\r\n\r\n public static final String OPERATION_NAME = \"Product\";\r\n public static final GraphQLOperation OPERATION_TYPE = GraphQLOperation.QUERY;\r\n\r\n private String alias;\r\n private final Map<String, Object> input = new LinkedHashMap<>();\r\n private final Set<String> useObjectMapperForInputSerialization = new HashSet<>();\r\n\r\n public ProductQueryRequest() {\r\n }\r\n\r\n public ProductQueryRequest(String alias) {\r\n this.alias = alias;\r\n }\r\n\r\n public void setProductOrganization(ProductQueryProductOrganizationParametrizedInput input) {\r\n this.input.put(\"ProductOrganization\", input);\r\n }\r\n\r\n @Override\r\n public GraphQLOperation getOperationType() {\r\n return OPERATION_TYPE;\r\n }\r\n\r\n @Override\r\n public String getOperationName() {\r\n return OPERATION_NAME;\r\n }\r\n\r\n @Override\r\n public String getAlias() {\r\n return alias != null ? alias : OPERATION_NAME;\r\n }\r\n\r\n @Override\r\n public Map<String, Object> getInput() {\r\n return input;\r\n }\r\n\r\n @Override\r\n public Set<String> getUseObjectMapperForInputSerialization() {\r\n return useObjectMapperForInputSerialization;\r\n }\r\n\r\n @Override\r\n public boolean equals(Object obj) {\r\n if (this == obj) {\r\n return true;\r\n }\r\n if (obj == null || getClass() != obj.getClass()) {\r\n return false;\r\n }\r\n final ProductQueryRequest that = (ProductQueryRequest) obj;\r\n return Objects.equals(getOperationType(), that.getOperationType()) &&\r\n Objects.equals(getOperationName(), that.getOperationName()) &&\r\n Objects.equals(input, that.input);\r\n }\r\n\r\n @Override\r\n public int hashCode() {\r\n return Objects.hash(getOperationType(), getOperationName(), input);\r\n }\r\n @Override\r\n public String toString() {\r\n return Objects.toString(input);\r\n }\r\n\r\n public static ProductQueryRequest.Builder builder() {\r\n return new ProductQueryRequest.Builder();\r\n }\r\n\r\n public static class Builder {\r\n\r\n private String $alias;\r\n\r\n private ProductQueryProductOrganizationParametrizedInput orgInput;\r\n\r\n\r\n public Builder() {\r\n }\r\n\r\n public Builder alias(String alias) {\r\n this.$alias = alias;\r\n return this;\r\n }\r\n\r\n public Builder setId(ProductQueryProductOrganizationParametrizedInput input) {\r\n this.orgInput = input;\r\n return this;\r\n }\r\n\r\n\r\n public ProductQueryRequest build() {\r\n ProductQueryRequest obj = new ProductQueryRequest($alias);\r\n obj.setProductOrganization(this.orgInput);\r\n return obj;\r\n }\r\n\r\n }\r\n}\r\n```\r\n\r\n\r\ngenerated \r\n\r\n```\r\npackage com.atlassian.Product.streams.model.schema;\r\n\r\nimport com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation;\r\nimport com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest;\r\nimport java.util.HashSet;\r\nimport java.util.LinkedHashMap;\r\nimport java.util.Map;\r\nimport java.util.Objects;\r\nimport java.util.Set;\r\n\r\[email protected](\r\n value = \"com.kobylynskyi.graphql.codegen.GraphQLCodegen\",\r\n date = \"2022-03-01T13:46:37-0600\"\r\n)\r\npublic class ProductQueryRequest implements GraphQLOperationRequest {\r\n\r\n public static final String OPERATION_NAME = \"Product\";\r\n public static final GraphQLOperation OPERATION_TYPE = GraphQLOperation.QUERY;\r\n\r\n private String alias;\r\n private final Map<String, Object> input = new LinkedHashMap<>();\r\n private final Set<String> useObjectMapperForInputSerialization = new HashSet<>();\r\n\r\n public ProductQueryRequest() {\r\n }\r\n\r\n public ProductQueryRequest(String alias) {\r\n this.alias = alias;\r\n }\r\n\r\n @Override\r\n public GraphQLOperation getOperationType() {\r\n return OPERATION_TYPE;\r\n }\r\n\r\n @Override\r\n public String getOperationName() {\r\n return OPERATION_NAME;\r\n }\r\n\r\n @Override\r\n public String getAlias() {\r\n return alias != null ? alias : OPERATION_NAME;\r\n }\r\n\r\n @Override\r\n public Map<String, Object> getInput() {\r\n return input;\r\n }\r\n\r\n @Override\r\n public Set<String> getUseObjectMapperForInputSerialization() {\r\n return useObjectMapperForInputSerialization;\r\n }\r\n\r\n @Override\r\n public boolean equals(Object obj) {\r\n if (this == obj) {\r\n return true;\r\n }\r\n if (obj == null || getClass() != obj.getClass()) {\r\n return false;\r\n }\r\n final ProductQueryRequest that = (ProductQueryRequest) obj;\r\n return Objects.equals(getOperationType(), that.getOperationType()) &&\r\n Objects.equals(getOperationName(), that.getOperationName()) &&\r\n Objects.equals(input, that.input);\r\n }\r\n\r\n @Override\r\n public int hashCode() {\r\n return Objects.hash(getOperationType(), getOperationName(), input);\r\n }\r\n @Override\r\n public String toString() {\r\n return Objects.toString(input);\r\n }\r\n\r\n public static ProductQueryRequest.Builder builder() {\r\n return new ProductQueryRequest.Builder();\r\n }\r\n\r\n public static class Builder {\r\n\r\n private String $alias;\r\n\r\n public Builder() {\r\n }\r\n\r\n public Builder alias(String alias) {\r\n this.$alias = alias;\r\n return this;\r\n }\r\n\r\n\r\n public ProductQueryRequest build() {\r\n ProductQueryRequest obj = new ProductQueryRequest($alias);\r\n return obj;\r\n }\r\n\r\n }\r\n}\r\n```\r\n\r\nDiff is - the `GraphQLOperationRequest` generated type which is `ProductQueryRequest` does not provide any way to link the `ProductQueryProductOrganization` sub query hence I cant query for that.\r\n","issue_id":1660627226119,"origin_id":1055954365,"user_origin_id":96260115,"create_time":1646176275,"update_time":1646176275,"id":1666214735707,"updated_at":"2022-10-19T21:25:35.707000Z","created_at":"2022-10-19T21:25:35.707000Z"},{"_id":"63506b4f8041c95dfb0ecf29","body":"Thanks for providing the info.\nThe thing is that you are using query response type as an input, so it is considered as the parametrized input.\nTry disabling the following property:\n_generateParameterizedFieldsResolvers = false_","issue_id":1660627226119,"origin_id":1055984050,"user_origin_id":2664706,"create_time":1646178666,"update_time":1646178732,"id":1666214735710,"updated_at":"2022-10-19T21:25:35.709000Z","created_at":"2022-10-19T21:25:35.709000Z"},{"_id":"63506b4f8041c95dfb0ecf2a","body":"already tried with generateParameterizedFieldsResolvers = false ; same issue :( \r\n\r\n> query response type as an input\r\nnot sure if I am following this comment? what response type am I using?\r\n","issue_id":1660627226119,"origin_id":1055988234,"user_origin_id":96260115,"create_time":1646179098,"update_time":1646181009,"id":1666214735712,"updated_at":"2022-10-19T21:25:35.712000Z","created_at":"2022-10-19T21:25:35.712000Z"},{"_id":"63506b4f8041c95dfb0ecf2b","body":"Overall your schema design looks not as per GraphQL best-practices.\r\nI think the better solution would be:\r\n```graphql\r\ntype Query {\r\n productOrganization(id: ID!): ProductOrganization\r\n}\r\n\r\ntype ProductOrganization {\r\n id: ID!\r\n enabled: Boolean!\r\n createdOn: DateTime!\r\n updatedOn: DateTime\r\n}\r\n```","issue_id":1660627226119,"origin_id":1059954195,"user_origin_id":2664706,"create_time":1646569816,"update_time":1646569816,"id":1666214735715,"updated_at":"2022-10-19T21:25:35.714000Z","created_at":"2022-10-19T21:25:35.714000Z"},{"_id":"63506b4f8041c95dfb0ecf2d","body":"+1 to this. We really really want to use this library but without this we can't. We don't want to follow the way that is listed because we need to follow nesting practices to keep our queries separate, eg: they may come from different sources.I'm not sure I'd consider it against best practices since isn't the strong suite of graphql that queries can be nested? Either for this or for having fields that can take args and so on.\r\n\r\n Any idea how much work this would be? Would possibly be able to help contribute. \r\n\r\nThanks for creating this library! ","issue_id":1660627226119,"origin_id":1111266486,"user_origin_id":92340321,"create_time":1651079866,"update_time":1651080622,"id":1666214735719,"updated_at":"2022-10-19T21:25:35.719000Z","created_at":"2022-10-19T21:25:35.719000Z"}] comment

## Issue Description I have a schema like below ``` type Query { product: productQuery } type Mutation { product: productMutation } type productQuery { productOrganization(id: ID!): productOrganization } type...

bug

# Related to #859 Java implementation was done as part of #913 What's missing is the implementation for Scala and Kotlin ## Original description from #859 > > ## Issue...

bug
scala
kotlin

Generate models with immutable list / map getters

[{"_id":"635069c5cecf4e081a195172","body":"The only problem is that Java does not natively support immutable collections(such as `singletonList` or `Collections.unmodifiableXXX` not a good choice). This requires an external library.","issue_id":1660627226125,"origin_id":994406040,"user_origin_id":29496873,"create_time":1639552289,"update_time":1639552289,"id":1666214341422,"updated_at":"2022-10-19T21:19:01.422000Z","created_at":"2022-10-19T21:19:01.422000Z"},{"_id":"635069c5cecf4e081a195173","body":"> The only problem is that Java does not natively support immutable collections(such as `singletonList` or `Collections.unmodifiableXXX` not a good choice). This requires an external library.\r\n\r\n@jxnu-liguobin would it be possible to do something like `List.copyOf()`?","issue_id":1660627226125,"origin_id":994498284,"user_origin_id":10137,"create_time":1639557644,"update_time":1639557644,"id":1666214341425,"updated_at":"2024-05-19T23:21:49.892000Z","created_at":"2022-10-19T21:19:01.424000Z"},{"_id":"635069c5cecf4e081a195174","body":"But how do I make a list immutable?\r\nImmutable collection that avoid modification by throwing exceptions are not a good design. Because this will cause a runtime exception. This is also the default implementation of the Java collection library.","issue_id":1660627226125,"origin_id":994667184,"user_origin_id":29496873,"create_time":1639565192,"update_time":1639565192,"id":1666214341428,"updated_at":"2022-10-19T21:19:01.427000Z","created_at":"2022-10-19T21:19:01.427000Z"}] comment

**Is your feature request related to a problem? Please describe.** My project is in the stage of code quality checks and associated stuff, and I'm currently using a code scanner...

Feature Request: Ability to define field visibility and turn off generating getters/setters.

[{"_id":"63506eaf3056137e2656fff9","body":"I'm a Scala\/Java developer. I've used the playframework and akka for some time. \r\nPersonally, It's really worth doing so. (Use Scala is better)\r\n\r\nBut this kind of immutability is different from the common immutability in Java and may have a large cost. Let's see what @kobylynskyi thinks.","issue_id":1660627226129,"origin_id":973677657,"user_origin_id":29496873,"create_time":1637290050,"update_time":1637290050,"id":1666215599224,"updated_at":"2022-10-19T21:39:59.223000Z","created_at":"2022-10-19T21:39:59.223000Z"},{"_id":"63506eaf3056137e2656fffa","body":"fwiw, immutability via final fields is not a hard requirement.\r\nI\u2019d be happy just being able to generate public fields.","issue_id":1660627226129,"origin_id":973733841,"user_origin_id":984705,"create_time":1637297344,"update_time":1637297344,"id":1666215599227,"updated_at":"2022-10-19T21:39:59.227000Z","created_at":"2022-10-19T21:39:59.227000Z"},{"_id":"63506eaf3056137e2656fffb","body":"in my opinion, It is mainly used to implement a concise \"immutable model\", it is necessary to set it to `final`.","issue_id":1660627226129,"origin_id":973793423,"user_origin_id":29496873,"create_time":1637303787,"update_time":1637303787,"id":1666215599231,"updated_at":"2022-10-19T21:39:59.231000Z","created_at":"2022-10-19T21:39:59.231000Z"},{"_id":"63506eaf3056137e2656fffc","body":"I am totally fine with introducing a new config `generateImmutableModels` (default = `false`).\r\nThe only concern I have is that it is better to keep fields private and to generate getters as per Java standards. If you would still like to have fields public (and final) then maybe it's worth introducing another config for field visibility? In order not to mix it up with model immutability.","issue_id":1660627226129,"origin_id":984268170,"user_origin_id":2664706,"create_time":1638417101,"update_time":1638417101,"id":1666215599235,"updated_at":"2022-10-19T21:39:59.234000Z","created_at":"2022-10-19T21:39:59.234000Z"},{"_id":"63506eaf3056137e2656fffd","body":"> The only concern I have is that it is better to keep fields private and to generate getters as per Java standards. If you would still like to have fields public (and final) then maybe it's worth introducing another config for field visibility? In order not to mix it up with model immutability.\r\n\r\n`generateFunctionalImmutableModels`?","issue_id":1660627226129,"origin_id":984552452,"user_origin_id":29496873,"create_time":1638445513,"update_time":1638445513,"id":1666215599238,"updated_at":"2022-10-19T21:39:59.237000Z","created_at":"2022-10-19T21:39:59.237000Z"},{"_id":"664a89824a8e87d14e1a553f","body":"Hello sir ,\r\nI am new to open source contribution.\r\nI already know java , my tech stacks & tools includes C, C++ , Python , Java, JavaScript , HTML , CSS , SQL , Bootstrap, ReactJS, ExpressJS, NodeJS & Git . I need a little help from your side to contribute to these amazing projects. \r\n","issue_id":1660627226129,"origin_id":1411380296,"user_origin_id":10137,"create_time":1675219985,"update_time":1675219985,"id":1716160898845,"updated_at":"2024-05-19T23:21:38.844000Z","created_at":"2024-05-19T23:21:38.844000Z"},{"_id":"664a89824a8e87d14e1a5540","body":"New config `generateModelsWithPublicFields` will be released in 5.7.0","issue_id":1660627226129,"origin_id":1475038680,"user_origin_id":2664706,"create_time":1679184198,"update_time":1679184198,"id":1716160898849,"updated_at":"2024-05-19T23:21:38.849000Z","created_at":"2024-05-19T23:21:38.849000Z"}] comment

**Is your feature request related to a problem? Please describe.** It's frustrating having to use JavaBean getter methods to access properties of generated model classes. Also, since the model classes...

enhancement
good-first-issue
java