Skip to content

Commit d179735

Browse files
committed
Remove redundant code, modify ErrorPayloadParser interface to make protocol based parser not stateful
1 parent 8e9b84f commit d179735

File tree

9 files changed

+85
-113
lines changed

9 files changed

+85
-113
lines changed

aws/client/aws-client-awsjson/src/main/java/software/amazon/smithy/java/aws/client/awsjson/AwsJson11Protocol.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public final class AwsJson11Protocol extends AwsJsonProtocol {
2525
* discriminator of documents that use relative shape IDs.
2626
*/
2727
public AwsJson11Protocol(ShapeId service) {
28-
super(TRAIT_ID, service, new HttpErrorDeserializer.DocumentPayloadParser());
28+
super(TRAIT_ID, service, HttpErrorDeserializer.DEFAULT_ERROR_PAYLOAD_PARSER);
2929
}
3030

3131
@Override

aws/client/aws-client-awsjson/src/main/java/software/amazon/smithy/java/aws/client/awsjson/AwsJson1Protocol.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import software.amazon.smithy.java.client.core.ClientProtocolFactory;
1212
import software.amazon.smithy.java.client.core.ProtocolSettings;
1313
import software.amazon.smithy.java.client.http.ErrorTypeUtils;
14-
import software.amazon.smithy.java.client.http.HttpErrorDeserializer;
1514
import software.amazon.smithy.java.core.serde.document.Document;
1615
import software.amazon.smithy.java.core.serde.document.DocumentDeserializer;
1716
import software.amazon.smithy.model.shapes.ShapeId;
@@ -28,16 +27,13 @@ public final class AwsJson1Protocol extends AwsJsonProtocol {
2827
* discriminator of documents that use relative shape IDs.
2928
*/
3029
public AwsJson1Protocol(ShapeId service) {
31-
super(TRAIT_ID, service, new Json10Parser());
30+
super(TRAIT_ID, service, AwsJson1Protocol::extractErrorType);
3231
}
3332

34-
private static final class Json10Parser extends HttpErrorDeserializer.DocumentPayloadParser {
35-
@Override
36-
public ShapeId extractErrorType(Document document, String namespace) {
37-
return DocumentDeserializer.parseDiscriminator(
38-
ErrorTypeUtils.removeUri(ErrorTypeUtils.readTypeAndCode(document)),
39-
namespace);
40-
}
33+
private static ShapeId extractErrorType(Document document, String namespace) {
34+
return DocumentDeserializer.parseDiscriminator(
35+
ErrorTypeUtils.removeUri(ErrorTypeUtils.readTypeAndCode(document)),
36+
namespace);
4137
}
4238

4339
@Override

aws/client/aws-client-restxml/src/main/java/software/amazon/smithy/java/aws/client/restxml/RestXmlClientProtocol.java

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import software.amazon.smithy.java.client.http.binding.HttpBindingClientProtocol;
1919
import software.amazon.smithy.java.client.http.binding.HttpBindingErrorFactory;
2020
import software.amazon.smithy.java.context.Context;
21+
import software.amazon.smithy.java.core.error.CallException;
2122
import software.amazon.smithy.java.core.error.ModeledException;
2223
import software.amazon.smithy.java.core.schema.InputEventStreamingApiOperation;
2324
import software.amazon.smithy.java.core.schema.OutputEventStreamingApiOperation;
2425
import software.amazon.smithy.java.core.serde.Codec;
2526
import software.amazon.smithy.java.core.serde.TypeRegistry;
27+
import software.amazon.smithy.java.core.serde.document.Document;
2628
import software.amazon.smithy.java.core.serde.event.EventDecoderFactory;
2729
import software.amazon.smithy.java.core.serde.event.EventEncoderFactory;
2830
import software.amazon.smithy.java.core.serde.event.EventStreamingException;
@@ -95,24 +97,34 @@ protected EventDecoderFactory<AwsEventFrame> getEventDecoderFactory(
9597
return AwsEventDecoderFactory.forOutputStream(outputOperation, payloadCodec(), f -> f);
9698
}
9799

98-
private static final HttpErrorDeserializer.ErrorPayloadParser XML_ERROR_PAYLOAD_PARSER = (
99-
Context context,
100-
Codec codec,
101-
HttpErrorDeserializer.KnownErrorFactory knownErrorFactory,
102-
ShapeId serviceId,
103-
TypeRegistry typeRegistry,
104-
HttpResponse response,
105-
ByteBuffer buffer) -> {
106-
var deserializer = codec.createDeserializer(buffer);
107-
String code = XmlUtil.parseErrorCodeName(deserializer);
108-
var nameSpace = serviceId.getNamespace();
109-
var id = ShapeId.fromOptionalNamespace(nameSpace, code);
110-
var builder = typeRegistry.createBuilder(id, ModeledException.class);
111-
if (builder != null) {
112-
return knownErrorFactory.createError(context, codec, response, builder);
113-
}
114-
return null;
115-
};
100+
private static final HttpErrorDeserializer.ErrorPayloadParser XML_ERROR_PAYLOAD_PARSER =
101+
new HttpErrorDeserializer.ErrorPayloadParser() {
102+
@Override
103+
public CallException parsePayload(
104+
Context context,
105+
Codec codec,
106+
HttpErrorDeserializer.KnownErrorFactory knownErrorFactory,
107+
ShapeId serviceId,
108+
TypeRegistry typeRegistry,
109+
HttpResponse response,
110+
ByteBuffer buffer
111+
) {
112+
var deserializer = codec.createDeserializer(buffer);
113+
String code = XmlUtil.parseErrorCodeName(deserializer);
114+
var nameSpace = serviceId.getNamespace();
115+
var id = ShapeId.fromOptionalNamespace(nameSpace, code);
116+
var builder = typeRegistry.createBuilder(id, ModeledException.class);
117+
if (builder != null) {
118+
return knownErrorFactory.createError(context, codec, response, builder);
119+
}
120+
return null;
121+
}
122+
123+
@Override
124+
public ShapeId extractErrorType(Document document, String namespace) {
125+
return null;
126+
}
127+
};
116128

117129
public static final class Factory implements ClientProtocolFactory<RestXmlTrait> {
118130
@Override

client/client-http/src/main/java/software/amazon/smithy/java/client/http/ErrorTypeUtils.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
import software.amazon.smithy.java.core.serde.document.Document;
99
import software.amazon.smithy.model.shapes.ShapeType;
1010

11-
public class ErrorTypeUtils {
11+
public final class ErrorTypeUtils {
12+
13+
private ErrorTypeUtils() {}
1214

1315
/**
1416
* Read the error type from __type field of the document.

client/client-http/src/main/java/software/amazon/smithy/java/client/http/HttpErrorDeserializer.java

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ default ModeledException createErrorFromDocument(
117117
* Different protocols need different parsers to extract the ShapeId given their different response structures.
118118
* If no parser specified, {@link #DEFAULT_ERROR_PAYLOAD_PARSER} will be picked.
119119
*/
120+
@FunctionalInterface
120121
public interface ErrorPayloadParser {
121122
/**
122123
* This method should parse the response payload and extract error's ShapeId,and
@@ -132,15 +133,41 @@ public interface ErrorPayloadParser {
132133
*
133134
* @return the created error.
134135
*/
135-
CallException parsePayload(
136+
default CallException parsePayload(
136137
Context context,
137138
Codec codec,
138139
KnownErrorFactory knownErrorFactory,
139140
ShapeId serviceId,
140141
TypeRegistry typeRegistry,
141142
HttpResponse response,
142143
ByteBuffer buffer
143-
) throws SerializationException, DiscriminatorException;
144+
) {
145+
var document = codec.createDeserializer(buffer).readDocument();
146+
var id = extractErrorType(document, serviceId.getNamespace());
147+
var builder = typeRegistry.createBuilder(id, ModeledException.class);
148+
if (builder != null) {
149+
return knownErrorFactory.createErrorFromDocument(
150+
context,
151+
codec,
152+
response,
153+
buffer,
154+
document,
155+
builder);
156+
}
157+
return null;
158+
}
159+
160+
/**
161+
* This method should extract the error type from converted document based on the
162+
* protocol requirement from either __type or code and apply necessary sanitizing to
163+
* the error type.
164+
*
165+
* @param document The converted document of the payload.
166+
* @param namespace The default namespace used for error type's ShapeId.
167+
*
168+
* @return the created error.
169+
*/
170+
ShapeId extractErrorType(Document document, String namespace);
144171
}
145172

146173
// Does not check for any error headers by default.
@@ -191,45 +218,12 @@ public ModeledException createErrorFromDocument(
191218
}
192219
};
193220

194-
/**
195-
* An implementation of ErrorPayloadParser which provides default payload parsing and error type extraction for protocols
196-
* whose payload will be converted to a document.
197-
*/
198-
public static class DocumentPayloadParser implements ErrorPayloadParser {
199-
public CallException parsePayload(
200-
Context context,
201-
Codec codec,
202-
KnownErrorFactory knownErrorFactory,
203-
ShapeId serviceId,
204-
TypeRegistry typeRegistry,
205-
HttpResponse response,
206-
ByteBuffer buffer
207-
) {
208-
var document = codec.createDeserializer(buffer).readDocument();
209-
var id = extractErrorType(document, serviceId.getNamespace());
210-
var builder = typeRegistry.createBuilder(id, ModeledException.class);
211-
if (builder != null) {
212-
return knownErrorFactory.createErrorFromDocument(
213-
context,
214-
codec,
215-
response,
216-
buffer,
217-
document,
218-
builder);
219-
}
220-
return null;
221-
}
222-
223-
public ShapeId extractErrorType(Document document, String namespace) {
224-
return DocumentDeserializer.parseDiscriminator(
225-
ErrorTypeUtils.removeNamespaceAndUri(ErrorTypeUtils.readTypeAndCode(document)),
226-
namespace);
227-
}
228-
}
229-
230221
// This default parser should work for most protocols, but other protocols
231222
// that do not support document types will need a custom parser to extract error ShapeId.
232-
private static final ErrorPayloadParser DEFAULT_ERROR_PAYLOAD_PARSER = new DocumentPayloadParser();
223+
public static final ErrorPayloadParser DEFAULT_ERROR_PAYLOAD_PARSER =
224+
(document, namespace) -> DocumentDeserializer.parseDiscriminator(
225+
ErrorTypeUtils.removeNamespaceAndUri(ErrorTypeUtils.readTypeAndCode(document)),
226+
namespace);
233227

234228
private final Codec codec;
235229
private final HeaderErrorExtractor headerErrorExtractor;

client/client-http/src/test/java/software/amazon/smithy/java/client/http/ErrorTypeUtilsTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package software.amazon.smithy.java.client.http;
77

88
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertNull;
910

1011
import java.util.Map;
1112
import org.junit.jupiter.api.Test;
@@ -53,4 +54,11 @@ public void testReadTypeAndCode() {
5354
assertEquals("foo", ErrorTypeUtils.readTypeAndCode(document1));
5455
assertEquals("bar", ErrorTypeUtils.readTypeAndCode(document2));
5556
}
57+
58+
@Test
59+
public void testWrongTypeIgnored() {
60+
var document = Document.of(Map.of("__type", Document.of(123)));
61+
62+
assertNull(ErrorTypeUtils.readType(document));
63+
}
5664
}

client/client-rpcv2-cbor/src/main/java/software/amazon/smithy/java/client/rpcv2/RpcV2CborProtocol.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public RpcV2CborProtocol(ShapeId service) {
5757
this.errorDeserializer = HttpErrorDeserializer.builder()
5858
.codec(CBOR_CODEC)
5959
.serviceId(service)
60-
.errorPayloadParser(new CborParser())
60+
.errorPayloadParser(RpcV2CborProtocol::extractErrorType)
6161
.build();
6262
}
6363

@@ -170,13 +170,10 @@ private EventDecoderFactory<AwsEventFrame> getEventDecoderFactory(
170170
return AwsEventDecoderFactory.forOutputStream(outputOperation, payloadCodec(), f -> f);
171171
}
172172

173-
private static final class CborParser extends HttpErrorDeserializer.DocumentPayloadParser {
174-
@Override
175-
public ShapeId extractErrorType(Document document, String namespace) {
176-
return DocumentDeserializer.parseDiscriminator(
177-
ErrorTypeUtils.removeUri(ErrorTypeUtils.readType(document)),
178-
namespace);
179-
}
173+
private static ShapeId extractErrorType(Document document, String namespace) {
174+
return DocumentDeserializer.parseDiscriminator(
175+
ErrorTypeUtils.removeUri(ErrorTypeUtils.readType(document)),
176+
namespace);
180177
}
181178

182179
public static final class Factory implements ClientProtocolFactory<Rpcv2CborTrait> {

codecs/json-codec/src/main/java/software/amazon/smithy/java/json/JsonCodec.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import java.io.OutputStream;
99
import java.nio.ByteBuffer;
10-
import java.util.function.Function;
1110
import software.amazon.smithy.java.core.serde.Codec;
1211
import software.amazon.smithy.java.core.serde.ShapeDeserializer;
1312
import software.amazon.smithy.java.core.serde.ShapeSerializer;
@@ -175,16 +174,5 @@ Builder overrideSerdeProvider(JsonSerdeProvider provider) {
175174
settingsBuilder.overrideSerdeProvider(provider);
176175
return this;
177176
}
178-
179-
/**
180-
* Uses a custom error type sanitizer to process the {@code __type} field.
181-
*
182-
* @param errorTypeSanitizer the type sanitizer to use.
183-
* @return the builder.
184-
*/
185-
public Builder errorTypeSanitizer(Function<String, String> errorTypeSanitizer) {
186-
settingsBuilder.errorTypeSanitizer(errorTypeSanitizer);
187-
return this;
188-
}
189177
}
190178
}

codecs/json-codec/src/main/java/software/amazon/smithy/java/json/JsonSettings.java

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import java.util.Objects;
99
import java.util.ServiceLoader;
10-
import java.util.function.Function;
1110
import software.amazon.smithy.java.core.serde.TimestampFormatter;
1211

1312
/**
@@ -46,7 +45,6 @@ public final class JsonSettings {
4645
private final JsonSerdeProvider provider;
4746
private final boolean serializeTypeInDocuments;
4847
private final boolean prettyPrint;
49-
private final Function<String, String> errorTypeSanitizer;
5048

5149
private JsonSettings(Builder builder) {
5250
this.timestampResolver = builder.useTimestampFormat
@@ -60,7 +58,6 @@ private JsonSettings(Builder builder) {
6058
this.provider = builder.provider;
6159
this.serializeTypeInDocuments = builder.serializeTypeInDocuments;
6260
this.prettyPrint = builder.prettyPrint;
63-
this.errorTypeSanitizer = builder.errorTypeSanitizer;
6461
}
6562

6663
/**
@@ -118,16 +115,6 @@ public boolean serializeTypeInDocuments() {
118115
return serializeTypeInDocuments;
119116
}
120117

121-
/**
122-
* The error type sanitizer to use for {@code __type} or {@code code} when parsing the error discriminator.
123-
* Default is null
124-
*
125-
* @return the sanitizer used or null
126-
*/
127-
public Function<String, String> errorTypeSanitizer() {
128-
return errorTypeSanitizer;
129-
}
130-
131118
/**
132119
* Whether to format the JSON output with pretty printing (indentation and line breaks).
133120
*
@@ -178,7 +165,6 @@ public static final class Builder {
178165
private JsonSerdeProvider provider = PROVIDER;
179166
private boolean serializeTypeInDocuments = true;
180167
private boolean prettyPrint = false;
181-
private Function<String, String> errorTypeSanitizer;
182168

183169
private Builder() {}
184170

@@ -289,16 +275,5 @@ Builder overrideSerdeProvider(JsonSerdeProvider provider) {
289275
this.provider = Objects.requireNonNull(provider);
290276
return this;
291277
}
292-
293-
/**
294-
* Uses a custom error type sanitizer for error type
295-
*
296-
* @param errorTypeSanitizer the sanitizer to use for error type.
297-
* @return the builder.
298-
*/
299-
public Builder errorTypeSanitizer(Function<String, String> errorTypeSanitizer) {
300-
this.errorTypeSanitizer = errorTypeSanitizer;
301-
return this;
302-
}
303278
}
304279
}

0 commit comments

Comments
 (0)