-
Notifications
You must be signed in to change notification settings - Fork 656
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
Add addJvmOverloads support to Input types #5397
Comments
Good catch! See also #4659 for a similar issue with argument order. I think you're 100% right that In the longer term, I'd aim for To your question, I think Even with |
+1 to input builders and making constructors private. I see, it makes sense to call it "input" but it may sound confusing. Maybe I don't see how (https://github.com/graphql/graphql-spec/issues/1062)[https://github.com/graphql/graphql-spec/issues/1062] would cause issues with builders. Maybe I'm missing something. Another option to consider is to move away from data classes to fully fletched classes for better maintainability as outlined in this article. |
Could work. 2 potential caveats:
Another way to look at this, especially if we were to make
Sorry I meant to link #5375 instead. If you have 2 mandatory parameters in your
Funny you mentioned that article, I had this in mind too :). AFAIK, data classes are relatively used for programmatically updating the cache (where you end up using a lot of |
I haven't used the input builders yet so I'm not familiar how it works internally, but when I get a chance and when we start the spike for migration I will take a look. The more we look into this, the more problems are surfacing. We discovered that For Java clients Example: data class Foo @JvmOverloads constructor(
val a: String = "a",
val b: String = "b",
)
class FooTester {
val validCase1 = Foo(a = "a", b= "b")
val validCase2 = Foo("a", "b")
val validCase3 = Foo(a = "a", "")
val failureCase1 = Foo("a")
val failureCase2 = Foo(a = "a")
val failureCase3 = Foo()
} You add a new parameter data class Foo @JvmOverloads constructor(
val a: String = "a",
val b: String = "b",
val c: String = "c",
) When the library gets updated transitively Cause If you decompile to Java, you will see those constructors are calling the synthetic constructor: And the signature of the synthetic constructor changes between two versions: To: |
Makes a lot of sense 👍 . Good old Builders will live forever! :). I still think we should add the Re:
If you get a chance to enable |
V4 is now out, which includes |
FWIW, I changed my mind on See also #6095 |
Yes, I agree with the approach. JvmOverloads only helps with Java, not Kotlin. I will close this. |
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Kotlin usage and allow us to serve you better. |
Version
v3.8.2
Summary
Problem
Adding a new nullable field to the schema is a “safe” operation from the point of GQL Schema checks, but it is not safe on the client side since the binary of the generated code changes. This may result in
NoSuchMethodExceptions
at runtime.Example:
The input type above generates the following data class:
If we modify the schema,
the generated data class constructor changes
When precompiled libraries call
Login("user", "1234")
, they will receive `NoSuchMethodException.Proposal
We should extend the functionality added with #3848 and add
addJvmOverloads
support toInput
types. Adding this support to Fragment Data Classes would be nice as well, but I don't know how this would work since they don't have default values. Possibly, we can add a flag that defaults nullable fragment arguments tonull
.Considerations
@JvmOverloads
will not make it fully binary compatible. This only works if you add the new parameter to the end of the constructor. Since the schema dictates the order, this will be difficult to control on the client side but can be handled when designing the schema.copy()
function will not be binary compatible. However, this may not be a problem for the majority of the use cases.generateInputBuilders
can be used to mitigate this. CangenerateInputBuilders
be extended to Operations and Fragments as well?Steps to reproduce the behavior
No response
Logs
The text was updated successfully, but these errors were encountered: