Skip to content

Commit 99366a8

Browse files
AWS Query protocol to Json Protcol migration compatibility, support for awsQueryError metadata trait (#3442)
* Parse custom error error for AwsJson support
1 parent 94f0a4a commit 99366a8

File tree

21 files changed

+1207
-7
lines changed

21 files changed

+1207
-7
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "ziyanli-amazon",
5+
"description": "Support for clients with AWS Query protocol migrating towards AwsJson in order to support custom error codes."
6+
}

codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ public static Metadata constructMetadata(ServiceModel serviceModel,
7777
.withUid(serviceMetadata.getUid())
7878
.withServiceId(serviceMetadata.getServiceId())
7979
.withSupportsH2(supportsH2(serviceMetadata))
80-
.withJsonVersion(getJsonVersion(metadata, serviceMetadata));
80+
.withJsonVersion(getJsonVersion(metadata, serviceMetadata))
81+
.withAwsQueryCompatible(serviceMetadata.getAwsQueryCompatible());
8182

8283
return metadata;
8384
}

codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package software.amazon.awssdk.codegen.model.intermediate;
1717

18+
import java.util.Map;
1819
import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
1920
import software.amazon.awssdk.codegen.model.service.AuthType;
2021
import software.amazon.awssdk.utils.StringUtils;
@@ -83,6 +84,8 @@ public class Metadata {
8384

8485
private String jsonVersion;
8586

87+
private Map<String, String> awsQueryCompatible;
88+
8689
private String endpointPrefix;
8790

8891
private String signingName;
@@ -103,6 +106,7 @@ public class Metadata {
103106

104107
private String serviceId;
105108

109+
106110
public String getApiVersion() {
107111
return apiVersion;
108112
}
@@ -505,6 +509,19 @@ public Metadata withJsonVersion(String jsonVersion) {
505509
return this;
506510
}
507511

512+
public Map<String, String> getAwsQueryCompatible() {
513+
return awsQueryCompatible;
514+
}
515+
516+
public void setAwsQueryCompatible(Map<String, String> awsQueryCompatible) {
517+
this.awsQueryCompatible = awsQueryCompatible;
518+
}
519+
520+
public Metadata withAwsQueryCompatible(Map<String, String> awsQueryCompatible) {
521+
setAwsQueryCompatible(awsQueryCompatible);
522+
return this;
523+
}
524+
508525
public boolean isCborProtocol() {
509526
return protocol == Protocol.CBOR;
510527
}

codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ServiceMetadata.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class ServiceMetadata {
3737

3838
private String jsonVersion;
3939

40+
private Map<String, String> awsQueryCompatible;
41+
4042
private boolean resultWrapped;
4143

4244
private String signatureVersion;
@@ -114,6 +116,14 @@ public void setJsonVersion(String jsonVersion) {
114116
this.jsonVersion = jsonVersion;
115117
}
116118

119+
public Map<String, String> getAwsQueryCompatible() {
120+
return awsQueryCompatible;
121+
}
122+
123+
public void setAwsQueryCompatible(Map<String, String> awsQueryCompatible) {
124+
this.awsQueryCompatible = awsQueryCompatible;
125+
}
126+
117127
public boolean isResultWrapped() {
118128
return resultWrapped;
119129
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ public MethodSpec initProtocolFactory(IntermediateModel model) {
9696
.addCode(".protocolVersion($S)\n", metadata.getJsonVersion())
9797
.addCode("$L", customErrorCodeFieldName());
9898

99-
10099
String contentType = Optional.ofNullable(model.getCustomizationConfig().getCustomServiceMetadata())
101100
.map(MetadataConfig::getContentType)
102101
.orElse(metadata.getContentType());
@@ -105,6 +104,10 @@ public MethodSpec initProtocolFactory(IntermediateModel model) {
105104
methodSpec.addCode(".contentType($S)", contentType);
106105
}
107106

107+
if (metadata.getAwsQueryCompatible() != null) {
108+
methodSpec.addCode("$L", hasAwsQueryCompatible());
109+
}
110+
108111
registerModeledExceptions(model, poetExtensions).forEach(methodSpec::addCode);
109112
methodSpec.addCode(";");
110113

@@ -117,6 +120,10 @@ private CodeBlock customErrorCodeFieldName() {
117120
CodeBlock.of(".customErrorCodeFieldName($S)", model.getCustomizationConfig().getCustomErrorCodeFieldName());
118121
}
119122

123+
private CodeBlock hasAwsQueryCompatible() {
124+
return CodeBlock.of(".hasAwsQueryCompatible($L)", model.getMetadata().getAwsQueryCompatible() != null);
125+
}
126+
120127
private Class<?> protocolFactoryClass() {
121128
if (model.getMetadata().isCborProtocol()) {
122129
return AwsCborProtocolFactory.class;

codegen/src/test/java/software/amazon/awssdk/codegen/IntermediateModelBuilderTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertFalse;
2121
import static org.junit.jupiter.api.Assertions.assertTrue;
22+
import static org.junit.jupiter.api.Assertions.assertNotNull;
2223

2324
import java.io.File;
2425
import org.junit.jupiter.api.Test;
@@ -89,4 +90,18 @@ public void defaultEndpointDiscovery_false() {
8990
assertFalse(testModel.getEndpointOperation().get().isEndpointCacheRequired());
9091
}
9192

93+
@Test
94+
public void assertAwsQueryCompatibleTrait_notNull() {
95+
final File modelFile = new File(IntermediateModelBuilderTest.class
96+
.getResource("poet/client/c2j/query-to-json-errorcode/service-2.json").getFile());
97+
IntermediateModel testModel = new IntermediateModelBuilder(
98+
C2jModels.builder()
99+
.serviceModel(ModelLoaderUtils.loadModel(ServiceModel.class, modelFile))
100+
.customizationConfig(CustomizationConfig.create())
101+
.build())
102+
.build();
103+
104+
assertNotNull(testModel.getMetadata().getAwsQueryCompatible());
105+
}
106+
92107
}

codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@ public static IntermediateModel awsJsonServiceModels() {
4848
return new IntermediateModelBuilder(models).build();
4949
}
5050

51+
public static IntermediateModel awsQueryCompatibleJsonServiceModels() {
52+
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query-to-json-errorcode/service-2.json").getFile());
53+
File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/query-to-json-errorcode/customization.config").getFile());
54+
File paginatorsModel = new File(ClientTestModels.class.getResource("client/c2j/query-to-json-errorcode/paginators.json").getFile());
55+
C2jModels models = C2jModels.builder()
56+
.serviceModel(getServiceModel(serviceModel))
57+
.customizationConfig(getCustomizationConfig(customizationModel))
58+
.paginatorsModel(getPaginatorsModel(paginatorsModel))
59+
.build();
60+
61+
return new IntermediateModelBuilder(models).build();
62+
}
63+
5164
public static IntermediateModel bearerAuthServiceModels() {
5265
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/json-bearer-auth/service-2.json").getFile());
5366
File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/json-bearer-auth/customization.config").getFile());

codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/PoetClientFunctionalTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ public void asyncClientClassAwsJson() throws Exception {
7575
assertThat(asyncClientClass, generatesTo("test-aws-json-async-client-class.java"));
7676
}
7777

78+
@Test
79+
public void asyncClientClassAwsQueryCompatibleJson() throws Exception {
80+
AsyncClientClass asyncClientClass = createAsyncClientClass(ClientTestModels.awsQueryCompatibleJsonServiceModels());
81+
assertThat(asyncClientClass, generatesTo("test-aws-query-compatible-json-async-client-class.java"));
82+
}
83+
84+
@Test
85+
public void syncClientClassAwsQueryCompatibleJson() throws Exception {
86+
SyncClientClass syncClientClass = createSyncClientClass(ClientTestModels.awsQueryCompatibleJsonServiceModels());
87+
assertThat(syncClientClass, generatesTo("test-aws-query-compatible-json-sync-client-class.java"));
88+
}
89+
7890
@Test
7991
public void syncClientClassXml() throws Exception {
8092
SyncClientClass syncClientClass = createSyncClientClass(ClientTestModels.xmlServiceModels());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"authPolicyActions" : {
3+
"skip" : true
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"pagination": {
3+
"PaginatedOperationWithResultKey": {
4+
"input_token": "NextToken",
5+
"output_token": "NextToken",
6+
"limit_key": "MaxResults",
7+
"result_key": "Items"
8+
},
9+
"PaginatedOperationWithoutResultKey": {
10+
"input_token": "NextToken",
11+
"output_token": "NextToken",
12+
"limit_key": "MaxResults"
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)