kobylynskyi / graphql-java-codegen

Make your GraphQL Java application schema-driven.
https://kobylynskyi.github.io/graphql-java-codegen/
MIT License
269 stars 114 forks source link

Client-side code generation #37

Closed kobylynskyi closed 4 years ago

kobylynskyi commented 4 years ago

Is your feature request related to a problem? Please describe. Currently, the main purpose of the plugin is to generate server-side code (POJOs and interfaces). The idea is to add support of client-side classes generation. This will allow users to build a GraphQL request.

Describe the solution you'd like Schema example:

type Mutation {
    newBike(bikeInput: BikeInput!): Bike
}

input BikeInput {
    type: BikeType!
    brand: String!
    size: String!
    price: BigDecimal
}

type Bike {
    id: ID
    type: BikeType
    brand: String
    size: String
    price: BigDecimal
    addedDateTime: DateTime
}

Generated class:

public class NewBikeMutationRequest {
    private BikeInput bikeInput;
    //getters/setters
}

public class BikeInputTO {
    private BikeTypeTO type;
    private String brand;
    private String size;
    private String price;

    public BikeInputTO() { }

    //getters/setters

The end-user will then use these classes to build the request and response projection (open question for now). So that it will be serialized to the following request string:

mutation newBike {
  newBike(bike: {
    type: ROAD,
    brand: "LOL",
    size: "Big",
    year: 2019,
    price: "123.45"
  }) {
    id
    addedDateTime
  }
}
joffrey-bion commented 4 years ago

Existing client side code generators I heard about actually generate types from the actual queries (and the schema of course). They yield types that are specific to that query and only contain the fields that have been requested. This is to ensure type safety so that the client doesn't access fields it didn't actually ask for in the query. I don't think generated full POJOs from the schema would be useful.

However, the problem that frontend engineers face in my company is that the types from 2 independent queries are not related at all, so it reduces code sharing. Maybe we could start with a similar approach but taking all queries into account at the same time and build a type hierarchy depending on the fields that are asked for in each query. Finding common subsets of fields for a given type would allow to generate reusable interfaces. This way, each query gets a specific type with the field it asked for, but common interfaces can still be used in shared code.

On Fri, Apr 3, 2020, 21:06 Bogdan Kobylynskyi notifications@github.com wrote:

Is your feature request related to a problem? Please describe. Currently, the main purpose of the plugin is to generate server-side code (POJOs and interfaces). The idea is to add support of client-side classes generation. This will allow users to build a GraphQL request.

Describe the solution you'd like Schema example:

type Mutation { newBike(bikeInput: BikeInput!): Bike } input BikeInput { type: BikeType! brand: String! size: String! price: BigDecimal } type Bike { id: ID type: BikeType brand: String size: String price: BigDecimal addedDateTime: DateTime }

Generated class:

public class NewBikeMutationRequest { private BikeInput bikeInput; //getters/setters } public class BikeInputTO { private BikeTypeTO type; private String brand; private String size; private String price;

public BikeInputTO() { }

//getters/setters

The end-user will then use these classes to build the request and response projection (open question for now). So that it will be serialized to the following request string:

mutation newBike { newBike(bike: { type: ROAD, brand: "LOL", size: "Big", year: 2019, price: "123.45" }) { id addedDateTime } }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/kobylynskyi/graphql-java-codegen/issues/37, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAOTDUGLYGLYT7P4Z2QIOGLRKYXTLANCNFSM4L4MCORA .

kobylynskyi commented 4 years ago

@joffrey-bion I was not able to find a solution for client-side code generation in Java.

The idea of this feature would be:

  1. Define the projection of the response object (which fields to fetch)
  2. Properly serialize the request.

So the code on the client-side will look like:

BikeInputTO input = new BikeInputTO(...);
NewBikeMutationRequest request = new NewBikeMutationRequest(input)
                .responseProjection(new BikeProjection()
                        .id().addedDateTime());
Bike bikeResponse = restTemplate.postForObject("https://localhost:8080", request, Bike.class);

(the DSL is still discussable)

joffrey-bion commented 4 years ago

I was not able to find a solution for client-side code generation in Java.

Yes, I was actually mentioning code generators in general. The one I heard about was for Swift I think.

The idea of this feature would be:

  1. Define the projection of the response object (which fields to fetch)
  2. Properly serialize the request.

Oh OK, so you want to build client queries in Java directly? That could be a way too, I just felt like the idea of this library was to go schema-first, so I expected a query-first solution here. But that implies parsing queries. I don't know if the library you're using can do this.

kobylynskyi commented 4 years ago

Oh OK, so you want to build client queries in Java directly?

Yes. But the approach will still be schema-first because the client will use schema to generate the request and response classes. The main problem that I am facing in one of my projects is to serialize the request. Because GraphQL request is not a JSON and I can't find a proper GraphQL request serialization in java.

JustinBlandford commented 4 years ago

Hi @kobylynskyi that's exactly what I was thinking about and thanks for raising this feature, I initially thought that the graphql-codegen-maven-plugin plugin did generate client code as it generates classes that do seem to map to the response class :-), A new feature the way you have illustrated above would be very handy. Ultimately, all I'd like to is to be able to run a GraphQL query by building a request in Java and interrogate the response (similar to the swagger-codegen-maven-plugin). Schema first is critical as it dynamically creates the classes when changes to the schema are made as you have re-iterated above.

Do you have any rough idea of when such a feature may be available to use?

Thanks again, Justin

kobylynskyi commented 4 years ago

@JustinBlandford Thanks for your feedback. I am glad that you found this helpful. I am targeting to release this feature by the end of this week.

JustinBlandford commented 4 years ago

@kobylynskyi that's great, thanks

kobylynskyi commented 4 years ago

@JustinBlandford This feature is available in plugin version 1.6.0.

Please feel free to open an issue in this project or feature request if you have any suggestions/ideas. Thanks!