From d1dab3c6a1aadb04b26771fef60709e6cad880b9 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Fri, 2 Oct 2020 15:03:48 -0400 Subject: [PATCH] fix #1099: conjure-undertow correctly dealiases binary responses --- ...liasOptionalDoubleAliasedBinaryResult.java | 48 ++++++++++++++++ .../palantir/product/AliasedBinaryResult.java | 43 +++++++++++++++ .../product/DialogueEteBinaryEndpoints.java | 30 ++++++++++ .../product/DoubleAliasedBinaryResult.java | 43 +++++++++++++++ .../palantir/product/EteBinaryService.java | 4 ++ .../product/EteBinaryServiceAsync.java | 20 +++++++ .../product/EteBinaryServiceBlocking.java | 10 ++++ .../product/EteBinaryServiceEndpoints.java | 55 ++++++++++++++++++- .../product/EteBinaryServiceRetrofit.java | 4 ++ .../product/UndertowEteBinaryService.java | 5 ++ .../UndertowReturnValueClassNameVisitor.java | 24 +++++++- .../UndertowServiceHandlerGenerator.java | 42 ++++++++------ .../java/services/UndertowTypeFunctions.java | 31 +++++++---- .../conjure/java/EteBinaryResource.java | 6 ++ .../conjure/java/UndertowBinaryResource.java | 5 ++ .../src/test/resources/ete-binary.yml | 14 +++++ .../test/api/TestService.java.undertow | 2 +- .../test/api/TestService.java.undertow.prefix | 2 +- .../api/TestServiceEndpoints.java.undertow | 8 +-- .../TestServiceEndpoints.java.undertow.prefix | 8 +-- 20 files changed, 364 insertions(+), 40 deletions(-) create mode 100644 conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java create mode 100644 conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java create mode 100644 conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java new file mode 100644 index 000000000..3cd181f34 --- /dev/null +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java @@ -0,0 +1,48 @@ +package com.palantir.product; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.palantir.logsafe.Preconditions; +import java.util.Optional; +import javax.annotation.Generated; +import javax.annotation.Nonnull; + +@Generated("com.palantir.conjure.java.types.AliasGenerator") +public final class AliasOptionalDoubleAliasedBinaryResult { + private final Optional value; + + private AliasOptionalDoubleAliasedBinaryResult(@Nonnull Optional value) { + this.value = Preconditions.checkNotNull(value, "value cannot be null"); + } + + private AliasOptionalDoubleAliasedBinaryResult() { + this(Optional.empty()); + } + + @JsonValue + public Optional get() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } + + @Override + public boolean equals(Object other) { + return this == other + || (other instanceof AliasOptionalDoubleAliasedBinaryResult + && this.value.equals(((AliasOptionalDoubleAliasedBinaryResult) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @JsonCreator + public static AliasOptionalDoubleAliasedBinaryResult of(@Nonnull Optional value) { + return new AliasOptionalDoubleAliasedBinaryResult(value); + } +} diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java new file mode 100644 index 000000000..f0c206e5e --- /dev/null +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java @@ -0,0 +1,43 @@ +package com.palantir.product; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.palantir.logsafe.Preconditions; +import java.nio.ByteBuffer; +import javax.annotation.Generated; +import javax.annotation.Nonnull; + +@Generated("com.palantir.conjure.java.types.AliasGenerator") +public final class AliasedBinaryResult { + private final ByteBuffer value; + + private AliasedBinaryResult(@Nonnull ByteBuffer value) { + this.value = Preconditions.checkNotNull(value, "value cannot be null"); + } + + @JsonValue + public ByteBuffer get() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } + + @Override + public boolean equals(Object other) { + return this == other + || (other instanceof AliasedBinaryResult && this.value.equals(((AliasedBinaryResult) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @JsonCreator + public static AliasedBinaryResult of(@Nonnull ByteBuffer value) { + return new AliasedBinaryResult(value); + } +} diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java index 19633e7db..7d66deaac 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java @@ -164,6 +164,36 @@ public String endpointName() { return "getBinaryFailure"; } + @Override + public String version() { + return "1.2.3"; + } + }, + + getAliased { + private final PathTemplate pathTemplate = + PathTemplate.builder().fixed("binary").fixed("aliased").build(); + + @Override + public void renderPath(Map params, UrlBuilder url) { + pathTemplate.fill(params, url); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.GET; + } + + @Override + public String serviceName() { + return "EteBinaryService"; + } + + @Override + public String endpointName() { + return "getAliased"; + } + @Override public String version() { return "1.2.3"; diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java new file mode 100644 index 000000000..34589c61d --- /dev/null +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java @@ -0,0 +1,43 @@ +package com.palantir.product; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.palantir.logsafe.Preconditions; +import javax.annotation.Generated; +import javax.annotation.Nonnull; + +@Generated("com.palantir.conjure.java.types.AliasGenerator") +public final class DoubleAliasedBinaryResult { + private final AliasedBinaryResult value; + + private DoubleAliasedBinaryResult(@Nonnull AliasedBinaryResult value) { + this.value = Preconditions.checkNotNull(value, "value cannot be null"); + } + + @JsonValue + public AliasedBinaryResult get() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } + + @Override + public boolean equals(Object other) { + return this == other + || (other instanceof DoubleAliasedBinaryResult + && this.value.equals(((DoubleAliasedBinaryResult) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @JsonCreator + public static DoubleAliasedBinaryResult of(@Nonnull AliasedBinaryResult value) { + return new DoubleAliasedBinaryResult(value); + } +} diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java index da7ebb039..e628cd601 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java @@ -53,4 +53,8 @@ StreamingOutput postBinaryThrows( @Produces(MediaType.APPLICATION_OCTET_STREAM) StreamingOutput getBinaryFailure( @HeaderParam("Authorization") @NotNull AuthHeader authHeader, @QueryParam("numBytes") int numBytes); + + @GET + @Path("binary/aliased") + AliasOptionalDoubleAliasedBinaryResult getAliased(@HeaderParam("Authorization") @NotNull AuthHeader authHeader); } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java index 614eb6fd0..db1c8c015 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java @@ -4,11 +4,13 @@ import com.palantir.dialogue.BinaryRequestBody; import com.palantir.dialogue.Channel; import com.palantir.dialogue.ConjureRuntime; +import com.palantir.dialogue.Deserializer; import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; +import com.palantir.dialogue.TypeMarker; import com.palantir.tokens.auth.AuthHeader; import java.io.InputStream; import java.lang.Override; @@ -44,6 +46,11 @@ public interface EteBinaryServiceAsync { */ ListenableFuture getBinaryFailure(AuthHeader authHeader, int numBytes); + /** + * @apiNote {@code GET /binary/aliased} + */ + ListenableFuture getAliased(AuthHeader authHeader); + /** * Creates an asynchronous/non-blocking client for a EteBinaryService service. */ @@ -66,6 +73,12 @@ static EteBinaryServiceAsync of(EndpointChannelFactory _endpointChannelFactory, private final EndpointChannel getBinaryFailureChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getBinaryFailure); + private final EndpointChannel getAliasedChannel = + _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getAliased); + + private final Deserializer getAliasedDeserializer = + _runtime.bodySerDe().deserializer(new TypeMarker() {}); + @Override public ListenableFuture postBinary(AuthHeader authHeader, BinaryRequestBody body) { Request.Builder _request = Request.builder(); @@ -126,6 +139,13 @@ public ListenableFuture getBinaryFailure(AuthHeader authHeader, int _runtime.bodySerDe().inputStreamDeserializer()); } + @Override + public ListenableFuture getAliased(AuthHeader authHeader) { + Request.Builder _request = Request.builder(); + _request.putHeaderParams("Authorization", authHeader.toString()); + return _runtime.clients().call(getAliasedChannel, _request.build(), getAliasedDeserializer); + } + @Override public String toString() { return "EteBinaryServiceAsync{_endpointChannelFactory=" + _endpointChannelFactory + ", runtime=" diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java index cd2d62095..1077bde03 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java @@ -45,6 +45,11 @@ public interface EteBinaryServiceBlocking { @MustBeClosed InputStream getBinaryFailure(AuthHeader authHeader, int numBytes); + /** + * @apiNote {@code GET /binary/aliased} + */ + AliasOptionalDoubleAliasedBinaryResult getAliased(AuthHeader authHeader); + /** * Creates a synchronous/blocking client for a EteBinaryService service. */ @@ -76,6 +81,11 @@ public InputStream getBinaryFailure(AuthHeader authHeader, int numBytes) { return _runtime.clients().block(delegate.getBinaryFailure(authHeader, numBytes)); } + @Override + public AliasOptionalDoubleAliasedBinaryResult getAliased(AuthHeader authHeader) { + return _runtime.clients().block(delegate.getAliased(authHeader)); + } + @Override public String toString() { return "EteBinaryServiceBlocking{_endpointChannelFactory=" + _endpointChannelFactory + ", runtime=" diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java index 81a04d40d..963e78365 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java @@ -2,6 +2,8 @@ import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; import com.palantir.conjure.java.undertow.lib.Endpoint; +import com.palantir.conjure.java.undertow.lib.Serializer; +import com.palantir.conjure.java.undertow.lib.TypeMarker; import com.palantir.conjure.java.undertow.lib.UndertowRuntime; import com.palantir.conjure.java.undertow.lib.UndertowService; import com.palantir.tokens.auth.AuthHeader; @@ -39,7 +41,8 @@ public List endpoints(UndertowRuntime runtime) { new PostBinaryThrowsEndpoint(runtime, delegate), new GetOptionalBinaryPresentEndpoint(runtime, delegate), new GetOptionalBinaryEmptyEndpoint(runtime, delegate), - new GetBinaryFailureEndpoint(runtime, delegate))); + new GetBinaryFailureEndpoint(runtime, delegate), + new GetAliasedEndpoint(runtime, delegate))); } private static final class PostBinaryEndpoint implements HttpHandler, Endpoint { @@ -270,4 +273,54 @@ public HttpHandler handler() { return this; } } + + private static final class GetAliasedEndpoint implements HttpHandler, Endpoint { + private final UndertowRuntime runtime; + + private final UndertowEteBinaryService delegate; + + private final Serializer> serializer; + + GetAliasedEndpoint(UndertowRuntime runtime, UndertowEteBinaryService delegate) { + this.runtime = runtime; + this.delegate = delegate; + this.serializer = runtime.bodySerDe().serializer(new TypeMarker>() {}); + } + + @Override + public void handleRequest(HttpServerExchange exchange) throws IOException { + AuthHeader authHeader = runtime.auth().header(exchange); + Optional result = delegate.getAliased(authHeader); + if (result.isPresent()) { + runtime.bodySerDe().serialize(result.get(), exchange); + } else { + exchange.setStatusCode(StatusCodes.NO_CONTENT); + } + } + + @Override + public HttpString method() { + return Methods.GET; + } + + @Override + public String template() { + return "/binary/aliased"; + } + + @Override + public String serviceName() { + return "EteBinaryService"; + } + + @Override + public String name() { + return "getAliased"; + } + + @Override + public HttpHandler handler() { + return this; + } + } } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java index 9aa71e153..b0fe87e27 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java @@ -47,4 +47,8 @@ ListenableFuture postBinaryThrows( @Streaming ListenableFuture getBinaryFailure( @Header("Authorization") AuthHeader authHeader, @Query("numBytes") int numBytes); + + @GET("./binary/aliased") + @Headers({"hr-path-template: /binary/aliased", "Accept: application/json"}) + ListenableFuture getAliased(@Header("Authorization") AuthHeader authHeader); } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java index 11c22d149..5e4293f75 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java @@ -33,4 +33,9 @@ public interface UndertowEteBinaryService { * @apiNote {@code GET /binary/failure} */ BinaryResponseBody getBinaryFailure(AuthHeader authHeader, int numBytes); + + /** + * @apiNote {@code GET /binary/aliased} + */ + Optional getAliased(AuthHeader authHeader); } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java index 9c9a8df52..fd23a66eb 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java @@ -26,6 +26,7 @@ import com.palantir.conjure.spec.OptionalType; import com.palantir.conjure.spec.PrimitiveType; import com.palantir.conjure.spec.SetType; +import com.palantir.conjure.spec.Type; import com.palantir.conjure.spec.TypeDefinition; import com.palantir.conjure.visitor.TypeVisitor; import com.squareup.javapoet.ClassName; @@ -37,8 +38,10 @@ public final class UndertowReturnValueClassNameVisitor implements ClassNameVisitor { private final ClassNameVisitor delegate; + private final List types; public UndertowReturnValueClassNameVisitor(List types, Options featureFlags) { + this.types = types; delegate = new DefaultClassNameVisitor(types, featureFlags); } @@ -57,9 +60,9 @@ public TypeName visitPrimitive(PrimitiveType primitiveType) { @Override public TypeName visitOptional(OptionalType optionalType) { - if (optionalType.getItemType().accept(TypeVisitor.IS_BINARY)) { - return ParameterizedTypeName.get( - ClassName.get(Optional.class), optionalType.getItemType().accept(this)); + Type dealiased = dealiasBinary(optionalType.getItemType()); + if (dealiased.accept(TypeVisitor.IS_BINARY)) { + return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); } return delegate.visitOptional(optionalType); } @@ -81,6 +84,13 @@ public TypeName visitMap(MapType mapType) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { + Optional type = UndertowTypeFunctions.getAliasedType(typeName, types); + if (type.isPresent()) { + Type dealiased = dealiasBinary(type.get()); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased.accept(this); + } + } return delegate.visitReference(typeName); } @@ -88,4 +98,12 @@ public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { public TypeName visitExternal(ExternalReference externalReference) { return delegate.visitExternal(externalReference); } + + private Type dealiasBinary(Type input) { + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(input, types); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased; + } + return input; + } } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index 3ec706f70..73744b5a5 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -452,31 +452,41 @@ private CodeBlock generateReturnValueCodeBlock( if (endpointDefinition.getReturns().isPresent()) { Type returnType = endpointDefinition.getReturns().get(); // optional<> handling - // TODO(ckozak): Support aliased binary types - if (UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions) - .accept(TypeVisitor.IS_OPTIONAL)) { - CodeBlock serializer = UndertowTypeFunctions.isOptionalBinary(returnType) - ? CodeBlock.builder() - .add( - "$1N.bodySerDe().serialize($2N.get(), $3N)", - RUNTIME_VAR_NAME, - RESULT_VAR_NAME, - EXCHANGE_VAR_NAME) - .build() - : CodeBlock.builder() - .add("$1N.serialize($2N, $3N)", SERIALIZER_VAR_NAME, RESULT_VAR_NAME, EXCHANGE_VAR_NAME) - .build(); + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); + if (dealiased.accept(TypeVisitor.IS_OPTIONAL)) { + CodeBlock serializer; + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + serializer = CodeBlock.builder() + .add( + dealiased.accept(TypeVisitor.IS_BINARY) + ? "$1N.bodySerDe().serialize($2N, $3N)" + : "$1N.bodySerDe().serialize($2N.get(), $3N)", + RUNTIME_VAR_NAME, + RESULT_VAR_NAME, + EXCHANGE_VAR_NAME) + .build(); + } else { + serializer = CodeBlock.builder() + .add("$1N.serialize($2N, $3N)", SERIALIZER_VAR_NAME, RESULT_VAR_NAME, EXCHANGE_VAR_NAME) + .build(); + } // For optional<>: set response code to 204/NO_CONTENT if result is absent code.add(CodeBlock.builder() .beginControlFlow( - "if ($1L)", createIsOptionalPresentCall(returnType, RESULT_VAR_NAME, typeDefinitions)) + "if ($1L)", + createIsOptionalPresentCall( + UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased) + ? dealiased + : returnType, + RESULT_VAR_NAME, + typeDefinitions)) .addStatement(serializer) .nextControlFlow("else") .addStatement("$1N.setStatusCode($2T.NO_CONTENT)", EXCHANGE_VAR_NAME, StatusCodes.class) .endControlFlow() .build()); } else { - if (returnType.accept(TypeVisitor.IS_BINARY)) { + if (dealiased.accept(TypeVisitor.IS_BINARY)) { code.addStatement( "$1N.bodySerDe().serialize($2N, $3N)", RUNTIME_VAR_NAME, diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java index f1726200f..162935f44 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java @@ -60,6 +60,10 @@ public Boolean visitOptional(OptionalType value) { }); } + static boolean isBinaryOrOptionalBinary(Type type) { + return type.accept(TypeVisitor.IS_BINARY) || isOptionalBinary(type); + } + static boolean isCollectionType(Type type) { return type.accept(TypeVisitor.IS_LIST) || type.accept(TypeVisitor.IS_SET); } @@ -70,16 +74,7 @@ static boolean isCollectionType(Type type) { static Type getAliasedType(Type type, List typeDefinitions) { com.palantir.logsafe.Preconditions.checkArgument( isAliasType(type), "Expected an alias", SafeArg.of("type", type)); - return getAliasedType( - type.accept(new AbstractTypeVisitor() { - @Override - public com.palantir.conjure.spec.TypeName visitReference( - com.palantir.conjure.spec.TypeName value) { - return value; - } - }), - typeDefinitions) - .get(); + return maybeGetAliasedType(type, typeDefinitions).get(); } static Optional getAliasedType( @@ -101,6 +96,22 @@ static Optional getAliasedType( return Optional.empty(); } + // Dealias the given type if possible, otherwise returns empty. This may occur if the type cannot be + // located, or if it is not an alias. + static Optional maybeGetAliasedType(Type type, List typeDefinitions) { + if (!isAliasType(type)) { + return Optional.empty(); + } + return getAliasedType( + type.accept(new AbstractTypeVisitor() { + @Override + public com.palantir.conjure.spec.TypeName visitReference(com.palantir.conjure.spec.TypeName value) { + return value; + } + }), + typeDefinitions); + } + private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< PrimitiveType.Value, String>() .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java index 9059b9f52..aec2c0fb4 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java @@ -22,6 +22,7 @@ import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.exceptions.SafeRuntimeException; +import com.palantir.product.AliasOptionalDoubleAliasedBinaryResult; import com.palantir.product.EteBinaryService; import com.palantir.tokens.auth.AuthHeader; import java.io.IOException; @@ -71,4 +72,9 @@ public StreamingOutput getBinaryFailure(AuthHeader _authHeader, int numBytes) { throw new SafeRuntimeException("failure"); }; } + + @Override + public AliasOptionalDoubleAliasedBinaryResult getAliased(@NotNull AuthHeader authHeader) { + return AliasOptionalDoubleAliasedBinaryResult.of(Optional.empty()); + } } diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java index 2eef7934e..e1599a5ff 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java @@ -71,4 +71,9 @@ public BinaryResponseBody getBinaryFailure(AuthHeader _authHeader, int numBytes) throw new SafeRuntimeException("failure"); }; } + + @Override + public Optional getAliased(AuthHeader _authHeader) { + return Optional.empty(); + } } diff --git a/conjure-java-core/src/test/resources/ete-binary.yml b/conjure-java-core/src/test/resources/ete-binary.yml index 0a65850cc..c89b7fac7 100644 --- a/conjure-java-core/src/test/resources/ete-binary.yml +++ b/conjure-java-core/src/test/resources/ete-binary.yml @@ -1,3 +1,14 @@ +types: + definitions: + default-package: com.palantir.product + objects: + AliasedBinaryResult: + alias: binary + DoubleAliasedBinaryResult: + alias: AliasedBinaryResult + AliasOptionalDoubleAliasedBinaryResult: + alias: optional + services: EteBinaryService: default-auth: header @@ -32,3 +43,6 @@ services: param-type: query docs: Throws an exception after partially writing a binary response. returns: binary + getAliased: + http: GET /aliased + returns: AliasOptionalDoubleAliasedBinaryResult diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow index dab8d4890..1f084e380 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow @@ -46,7 +46,7 @@ public interface TestService { /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-aliased} */ - NestedAliasedBinary getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); + BinaryResponseBody getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-maybe} diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix index bd7a298c1..ebd2c8a28 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix @@ -46,7 +46,7 @@ public interface TestService { /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-aliased} */ - NestedAliasedBinary getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); + BinaryResponseBody getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-maybe} diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow index 91b04eda9..c5c590348 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow +++ b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow @@ -277,12 +277,12 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Serializer serializer; + private final Serializer serializer; GetAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); + this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); } @Override @@ -292,8 +292,8 @@ public final class TestServiceEndpoints implements UndertowService { exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters(); ResourceIdentifier datasetRid = runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid")); runtime.markers().param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange); - NestedAliasedBinary result = delegate.getAliasedRawData(authHeader, datasetRid); - serializer.serialize(result, exchange); + BinaryResponseBody result = delegate.getAliasedRawData(authHeader, datasetRid); + runtime.bodySerDe().serialize(result, exchange); } @Override diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix index fdf398b5b..b8cdd4c39 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix @@ -277,12 +277,12 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Serializer serializer; + private final Serializer serializer; GetAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); + this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); } @Override @@ -292,8 +292,8 @@ public final class TestServiceEndpoints implements UndertowService { exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters(); ResourceIdentifier datasetRid = runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid")); runtime.markers().param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange); - NestedAliasedBinary result = delegate.getAliasedRawData(authHeader, datasetRid); - serializer.serialize(result, exchange); + BinaryResponseBody result = delegate.getAliasedRawData(authHeader, datasetRid); + runtime.bodySerDe().serialize(result, exchange); } @Override