Skip to content
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

feat: Generate DDB client code for Java V2 AWS SDK #92

Closed
wants to merge 19 commits into from

Conversation

lucasmcdonald3
Copy link
Contributor

@lucasmcdonald3 lucasmcdonald3 commented Jan 25, 2023

Note this is based on another change that is currently in PR: #82

#82 makes changes that are used in this PR. #82 should be merged into main-1.x before this change is merged.


Description of changes:

  • Generate DDB code for AWS SDK for Java V2

Testing:

I ran bin/generate_code.sh from my private-ESDK-dafny repo, then ran make transpile_java && make test_java.

The tests run GetItem, QueryItem, and PutItem. See test file.

I opened a draft PR with the generated changes in my fork of private-ESDK-dafny: link

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@lucasmcdonald3 lucasmcdonald3 requested a review from a team as a code owner January 25, 2023 21:59
// This is the only time when Polymorph needs to convert a list of a Dafny type to a list
// of a type that Polymorph does not know about. So this is a special case and warrants
// its own generation logic.
if (targetShape.getId().getName().equals("BinarySetAttributeValue")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: I am a little hesitant on using only the name of a shape to trigger an edge case.
BinarySetAttributeValue is probably fine, as it's so unique,
no other AWS Service model we use will include it...
Actually, another Database Service (RDS, Aurora, etc. ) might...

// SizeEstimateRangeGB is a list of the case above, where Smithy models values as integers,
// but the SDK expects doubles.
// This is the only instance of double -> int conversion in a list right now.
if (memberShape.getMemberName().equals("SizeEstimateRangeGB")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Many AWS Services could have a shape named SizeEstimateRangeGB.
We only know this logic works for DDB...
We should use both the namespace and the name to protect this edge case.

Comment on lines +268 to +269
return shapeName.equals("ConsumedCapacityUnits")
|| shapeName.equals("Double");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Many AWS Services could have a shape named ConsumedCapacityUnits.
We only know this logic works for DDB...
We should use both the namespace and the name to protect this edge case.

Comment on lines +392 to +395
.addAnnotation(
AnnotationSpec.builder(SuppressWarnings.class)
.addMember("value", "$S", "unchecked")
.build()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Praise: Nice job on figuring this out!
Nuances with Dafny like this trip my polymorph work up all the time.

Comment on lines +69 to +70
public static final ClassName BLOB_TO_NATIVE_SDK_BYTES =
ClassName.get("software.amazon.awssdk.core", "SdkBytes");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue/Suggestion: It may be best if this constant lived in awssdk/v2/ShimV2.java,
as compared to here.

Comment on lines +230 to +232
// "TargetValue" refers to a table's target R/W capacity target values.
// SDK handles these as doubles, but the Smithy model stores them as integers.
if (member.getMemberName().equals("TargetValue")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: Many AWS Services could have a shape named TargetValue.
We only know this logic works for DDB...
We should use both the namespace and the name to protect this edge case.

Comment on lines +194 to +196
public ClassName classForDouble() {
return ClassName.get(Double.class);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: I wonder why we need this method?

Comment on lines 67 to +72
if ("message".equals(uncapitalize(memberShape.getMemberName()))) {
return CodeBlock.of("$L.get$L()", variableName, capitalize(memberShape.getMemberName()));
// BatchStatementError and CancellationReason types' messages are retrieved via "message".
if (memberShape.getContainer().getName().contains("BatchStatementError")
|| memberShape.getContainer().getName().contains("CancellationReason")) {
return CodeBlock.of("$L.$L()", variableName,
uncapitalize(memberShape.getMemberName()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: This follows from my comment on the KMS PR.
#82 (comment)
We should go ahead and be specific here.
Fully qualify BatchStatementError and CancellationReason
(both are names that could be in any AWS Service Model, but not get treated the same as DDB's).
I'd also advocate for handling Error Structures seperately...
i.e.: if the member name is message and it's structure has the error trait, use getMessage).

Comment on lines +166 to +170
public boolean shapeIdRequiresStaticTypeDescriptor(final ShapeId shapeId) {
String className = classForNotErrorNotUnitShape(shapeId).toString();

return (className.equals("Dafny.Com.Amazonaws.Dynamodb.Types.AttributeMap")
|| className.equals("Dafny.Com.Amazonaws.Dynamodb.Types.Key"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Praise: This is great and safe as the edge case is handled by a fully qualified name.

Comment on lines +230 to +246
if (smithyName.simpleName().endsWith("Input")) {
return ClassName.get(smithyName.packageName(),
smithyName.simpleName()
.substring(
0,
smithyName.simpleName().lastIndexOf("Input"))
+ "Request"
);
}
if (smithyName.simpleName().endsWith("Output")) {
return ClassName.get(smithyName.packageName(),
smithyName.simpleName()
.substring(
0,
smithyName.simpleName().lastIndexOf("Output"))
+ "Response"
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Why did we not need this for KMS?
Is this not true for KMS?
Or do all KMS shapes already use Request and Response... I bet that is it...

Comment on lines +94 to +102
// OperationErrors are streamed to gather the types that are only inputs or outputs to errors.
// Right now this is only CancellationReasonList.
LinkedHashSet<ShapeId> operationErrors = subject.serviceShape
.getOperations().stream()
.map(shapeId -> subject.model.expectShape(shapeId, OperationShape.class))
.map(OperationShape::getErrors)
.flatMap(Collection::stream)
.filter(structureShape -> !structureShape.toString().contains("InvalidEndpointException"))
.collect(Collectors.toCollection(LinkedHashSet::new));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the value in this.
But, operationErrors is left in allReleventShapeIds.
So... those Error structures will get included in convertAllRelevent,
and will be passed to generateConvertStructure.
Then, as part of convertServiceErrors, they will get
another conversion method, but a modeledError conversion method.
I will refactor this so that we only generate modeledError.

Comment on lines +69 to +70
if (memberShape.getContainer().getName().contains("BatchStatementError")
|| memberShape.getContainer().getName().contains("CancellationReason")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: BatchStatementError (link to shape in model) and
CancellationReason (link to shape in model) are not marked with the @error trait.

Thus, they are just normal structures.
That is why their access is via message, as compared to getMessage.
In Java, getMessage is method of java.lang.Exception,
the global base Exception.

All AWS SDK exceptions extend from java.lang.Exception,
as do the Exceptions we generate.

This is why message is accessed by getMessage for structures marked with the Error trait.

texastony added a commit that referenced this pull request Feb 15, 2023
Where "srv's Op strucs" is
a Service's Operation Structures,
or all of a Service's Operations' Input, Output, Errors
and all shapes related to the above.

We need dafny-lang/dafny#3034
to resolve singular datatype creation
(now known as a "Record Type").

DONE:
- [x] Test Java KMS
- [x] Test Java DDB
- [x] Merge #83 into this

TODO:
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
texastony added a commit that referenced this pull request Feb 16, 2023
Use the codegen for the AWS SDK V2
to correctly name the Enums.

I have also addressed some issues
raised in the PRs.

DONE:
- [x] Test Java KMS
- [x] Test Java DDB
- [x] Merge #83 into this

TODO:
- [ ] Implement ToNative Double solution
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
- [ ] Consolidate duplicated code
- [ ] Test Java KMS & DDB Again
- [ ] PR & Merge
texastony added a commit that referenced this pull request Feb 20, 2023
TODO:
- [ ] Implement ToNative Double solution
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
- [ ] Consolidate duplicated code
- [ ] Test Java KMS & DDB Again
- [ ] PR & Merge
texastony added a commit that referenced this pull request Feb 20, 2023
TODO:
- [ ] Implement ToNative Double solution
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
- [ ] Consolidate duplicated code
- [ ] Test Java KMS & DDB Again
- [ ] PR & Merge
texastony added a commit that referenced this pull request Mar 2, 2023
Where "srv's Op strucs" is
a Service's Operation Structures,
or all of a Service's Operations' Input, Output, Errors
and all shapes related to the above.

We need dafny-lang/dafny#3034
to resolve singular datatype creation
(now known as a "Record Type").

DONE:
- [x] Test Java KMS
- [x] Test Java DDB
- [x] Merge #83 into this

TODO:
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
texastony added a commit that referenced this pull request Mar 2, 2023
Use the codegen for the AWS SDK V2
to correctly name the Enums.

I have also addressed some issues
raised in the PRs.

DONE:
- [x] Test Java KMS
- [x] Test Java DDB
- [x] Merge #83 into this

TODO:
- [ ] Implement ToNative Double solution
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
- [ ] Consolidate duplicated code
- [ ] Test Java KMS & DDB Again
- [ ] PR & Merge
texastony added a commit that referenced this pull request Mar 2, 2023
TODO:
- [ ] Implement ToNative Double solution
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
- [ ] Consolidate duplicated code
- [ ] Test Java KMS & DDB Again
- [ ] PR & Merge
texastony added a commit that referenced this pull request Mar 2, 2023
TODO:
- [ ] Implement ToNative Double solution
- [ ] Test Java DDB again
- [ ] Address Issues raised in PR #82, #92, #83
- [ ] Consolidate duplicated code
- [ ] Test Java KMS & DDB Again
- [ ] PR & Merge
@seebees
Copy link
Contributor

seebees commented Mar 31, 2023

This landed elsewhere right?

@texastony
Copy link
Contributor

This landed elsewhere right?

Yes. I merged this else where. I left this open as I wanted to make sure I came back are resolved these issues...
But that is now all tracked in https://sim.amazon.com/issues/CrypTool-5101

@texastony texastony closed this Mar 31, 2023
@lucasmcdonald3 lucasmcdonald3 deleted the java-sdk-v2-ddb branch August 15, 2023 22:20
robin-aws pushed a commit that referenced this pull request Apr 19, 2024
Create a shared makefile,
and then use that shared makefile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants