-
Notifications
You must be signed in to change notification settings - Fork 246
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
fix(java): invalid collections returned with non-class elements #1197
Conversation
Labelled with That shouldn't prevent reviewing the current change (the backwards compatibility can be restored by adding overloads for the previous API style, which would leverage the new API transparently - it would however conserve the previously broken behavior). |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
To help me review, since this change is ungodly: This was flagged as a regression (since jsii 0.17 if I'm reading the breadcrumb trail directly). Can you explain succinctly what the changes were that caused this breakage (starting from the wire protocol changes, if any) and what the approach for the fix is? To the uncultured plebeian that I am, it would seem that if the wire protocol says:
It should be easy enough to construct a It's probably trickier than that but I need it explained to me like I'm 5 :). |
I significantly reduced the amount of regression test file changes by preserving the previous API (and having it delegate into the new one); and only switching generated code to the new API when the older one was unsafe. To answer @rix0rrr's question, here's what happened:
Hopefully this helps clarify the problem... Now - to the approach for solving this: I introduced a way to represent complex types to provide directions to the deserializer, in the form of the |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
I am not sure I fully understand if this is a breaking change. I don't think we can afford breaking changes neither of the manifest nor of the runtime protocol. |
@eladb - I don't think this changes the runtime protocol. The only part that may be "broken" here is technically not working correctly in the current state of things. The only one thing which I think may still need "easing in" (so new runtime works with code generated by the previous generator) is with how the "old API" was modified to delegate into the "new API", which will throw if one attempts to use an api that returns a List or a Map (those could have returned collection with "illegal" items in them). I think I can work out a way to make the old behavior preserved, so older generated code keeps behaving the same as it currently does (still broken when it was, but not failing more). I can then attempt to run a number of scenarios using the current CDK libraries with the new Java runtime ahead of the class path to validate it is indeed backwards-compatible? I'd add unit tests to assert persistence of the older behavior, but I'd be skeptical as to the coverage of such (new) tests being sufficient... |
This part I don't get. It used to be:
And now it's:
We can restore the "old" behavior by picking the first interface from the associated list and instantiating the proxy class for that type, right? I guess we're doing all this work so that if there are 2 interfaces in the wire list, we'll pick the one that the current method has been declared to return? (Without looking at the wire data, looks like, just assuming the types will work out as declared?) I am slightly concerned about all the introspection happening on every JSII call; every call constructs a set of new |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
This will allow ensuring the fix is not "critically" backwards incompatible with older generated code. For instance, that old code will continue to "work" (including the current bug) instead of throwing some new exception (IllegalArgument, IllegalState, ...).
The Java runtime for jsii used to not be able to necessarily hold the type information necessary to correctly process the contents of collections, as the generic information is lost. In order to address this, introduced a new `NativeType<T>` class that is able to carry: 1. The actual declared type of the value (via generic type parameter) 2. The raw type of the value (reified) 3. The correct JavaType to pass to Jackson to obtain the correct result It also preserves the specific behavior around de-serialization of `JsiiObject` sub-classes as well as jsii interfaces, correctly requesting de-serialization as the `JsiiObject` class, and in a second phase `transform` this into the correct value type as needed. Introduced a new test that validates the `List<T>` and `Map<String, T>` values received from `node` are deserialized to instances with the appropriate content type. Fixes #1196
cd152f0
to
ecedc20
Compare
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
I added a test of the previous behavior with respects to |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious, how come this issue did not occur with .NET? Was the modeling of native types different there?
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core --> | ||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this changed?
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
|
||
public abstract class NativeType<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing documentation
import java.util.stream.Collectors; | ||
|
||
public abstract class NativeType<T> { | ||
protected static final JavaType[] NO_TYPE_PARAMS = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing docs
Thank you for contributing! ❤️ I will now look into making sure the PR is up-to-date, then proceed to try and merge it! |
1 similar comment
Thank you for contributing! ❤️ I will now look into making sure the PR is up-to-date, then proceed to try and merge it! |
The Java runtime for jsii used to not be able to necessarily hold the
type information necessary to correctly process the contents of
collections, as the generic information is lost.
In order to address this, introduced a new
NativeType<T>
class that isable to carry:
It also preserves the specific behavior around de-serialization of
JsiiObject
sub-classes as well as jsii interfaces, correctlyrequesting de-serialization as the
JsiiObject
class, and in a secondphase
transform
this into the correct value type as needed.Introduced a new test that validates the
List<T>
andMap<String, T>
values received from
node
are deserialized to instances with theappropriate content type.
Fixes #1196
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Commit Message
fix(java): invalid collections returned with non-class elements (#1197)
The Java runtime for jsii used to not be able to necessarily hold the
type information necessary to correctly process the contents of
collections, as the generic information is lost.
In order to address this, introduced a new
NativeType<T>
class that isable to carry:
It also preserves the specific behavior around de-serialization of
JsiiObject
sub-classes as well as jsii interfaces, correctlyrequesting de-serialization as the
JsiiObject
class, and in a secondphase
transform
this into the correct value type as needed.Introduced a new test that validates the
List<T>
andMap<String, T>
values received from
node
are deserialized to instances with theappropriate content type.
Fixes #1196