diff --git a/build.gradle b/build.gradle index bc5bc20a4..ef3a6944d 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,7 @@ allprojects { repositories { mavenCentral() { metadataSources { mavenPom(); ignoreGradleMetadataRedirection() } } + mavenLocal() } configurations.all { diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/another/ConjureErrors.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/another/ConjureErrors.java index cdba5e331..6b16ea9cb 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/another/ConjureErrors.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/another/ConjureErrors.java @@ -1,9 +1,15 @@ package dialogue.com.palantir.another; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.palantir.conjure.java.api.errors.AbstractSerializableError; import com.palantir.conjure.java.api.errors.ErrorType; import com.palantir.conjure.java.api.errors.RemoteException; +import com.palantir.conjure.java.api.errors.SerializableError; +import com.palantir.conjure.java.api.errors.SerializableErrorProvider; import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.logsafe.Preconditions; +import com.palantir.logsafe.Safe; import javax.annotation.Nullable; import javax.annotation.processing.Generated; @@ -39,4 +45,40 @@ public static boolean isDifferentPackageError(RemoteException remoteException) { Preconditions.checkNotNull(remoteException, "remote exception must not be null"); return DIFFERENT_PACKAGE_ERROR.name().equals(remoteException.getError().errorName()); } + + public static record DifferentPackageErrorParameters() {} + + public static final class DifferentPackageErrorSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + DifferentPackageErrorSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") DifferentPackageErrorParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class DifferentPackageErrorException extends RemoteException + implements SerializableErrorProvider { + private DifferentPackageErrorSerializableError error; + + public DifferentPackageErrorException(DifferentPackageErrorSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public DifferentPackageErrorSerializableError error() { + return error; + } + } } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureErrors.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureErrors.java index b8ab5e6bf..1fc713c93 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureErrors.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureErrors.java @@ -1,13 +1,19 @@ package dialogue.com.palantir.product; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.palantir.conjure.java.api.errors.AbstractSerializableError; import com.palantir.conjure.java.api.errors.ErrorType; import com.palantir.conjure.java.api.errors.RemoteException; +import com.palantir.conjure.java.api.errors.SerializableError; +import com.palantir.conjure.java.api.errors.SerializableErrorProvider; import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.logsafe.Preconditions; import com.palantir.logsafe.Safe; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.Unsafe; import com.palantir.logsafe.UnsafeArg; +import java.util.Objects; import javax.annotation.Nullable; import javax.annotation.processing.Generated; @@ -324,4 +330,244 @@ public static boolean isInvalidTypeDefinition(RemoteException remoteException) { Preconditions.checkNotNull(remoteException, "remote exception must not be null"); return INVALID_TYPE_DEFINITION.name().equals(remoteException.getError().errorName()); } + + public static record ConflictingCauseSafeArgParameters( + @JsonProperty("cause") @Safe String cause, @JsonProperty("shouldThrow") @Safe boolean shouldThrow) {} + + public static record ConflictingCauseUnsafeArgParameters( + @JsonProperty("cause") @Unsafe String cause, @JsonProperty("shouldThrow") @Unsafe boolean shouldThrow) {} + + public static record ErrorWithComplexArgsParameters( + @JsonProperty("primitiveExample") @Safe PrimitiveExample primitiveExample, + @JsonProperty("collectionExample") @Safe CollectionExample collectionExample, + @JsonProperty("nestedCollectionExample") @Safe NestedCollectionExample nestedCollectionExample, + @JsonProperty("optionalExample") @Safe OptionalExample optionalExample, + @JsonProperty("objectReference") @Safe ObjectReference objectReference, + @JsonProperty("unionExample") @Safe UnionExample unionExample, + @JsonProperty("enumExample") @Safe EnumExample enumExample, + @JsonProperty("stringAlias") @Safe StringAliasEx stringAlias, + @JsonProperty("optionalAlias") @Safe OptionalAlias optionalAlias, + @JsonProperty("collectionAlias") @Safe CollectionAlias collectionAlias, + @JsonProperty("nestedAlias") @Safe NestedAlias nestedAlias, + @JsonProperty("externalExample") @Safe ExternalExample externalExample, + @JsonProperty("anyExample") @Safe AnyExample anyExample, + @JsonProperty("emptyObject") @Safe EmptyObject emptyObject, + @JsonProperty("complexExample") @Safe ComplexExample complexExample, + @JsonProperty("safetyExample") @Unsafe SafetyExample safetyExample) {} + + /** + * @param serviceName Name of the invalid service definition. + * @param serviceDef Details of the invalid service definition. + */ + public static record InvalidServiceDefinitionParameters( + @JsonProperty("serviceName") @Safe String serviceName, + @JsonProperty("serviceDef") @Unsafe Object serviceDef) {} + + public static record InvalidTypeDefinitionParameters( + @JsonProperty("typeName") @Safe String typeName, @JsonProperty("typeDef") @Unsafe Object typeDef) {} + + public static final class ConflictingCauseSafeArgSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + ConflictingCauseSafeArgSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") ConflictingCauseSafeArgParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .putParameters("cause", Objects.toString(parameters().cause())) + .putParameters("shouldThrow", Objects.toString(parameters().shouldThrow())) + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class ConflictingCauseUnsafeArgSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + ConflictingCauseUnsafeArgSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") ConflictingCauseUnsafeArgParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .putParameters("cause", Objects.toString(parameters().cause())) + .putParameters("shouldThrow", Objects.toString(parameters().shouldThrow())) + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class ErrorWithComplexArgsSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + ErrorWithComplexArgsSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") ErrorWithComplexArgsParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .putParameters( + "primitiveExample", Objects.toString(parameters().primitiveExample())) + .putParameters( + "collectionExample", Objects.toString(parameters().collectionExample())) + .putParameters( + "nestedCollectionExample", + Objects.toString(parameters().nestedCollectionExample())) + .putParameters( + "optionalExample", Objects.toString(parameters().optionalExample())) + .putParameters( + "objectReference", Objects.toString(parameters().objectReference())) + .putParameters("unionExample", Objects.toString(parameters().unionExample())) + .putParameters("enumExample", Objects.toString(parameters().enumExample())) + .putParameters("stringAlias", Objects.toString(parameters().stringAlias())) + .putParameters( + "optionalAlias", Objects.toString(parameters().optionalAlias())) + .putParameters( + "collectionAlias", Objects.toString(parameters().collectionAlias())) + .putParameters("nestedAlias", Objects.toString(parameters().nestedAlias())) + .putParameters( + "externalExample", Objects.toString(parameters().externalExample())) + .putParameters("anyExample", Objects.toString(parameters().anyExample())) + .putParameters("emptyObject", Objects.toString(parameters().emptyObject())) + .putParameters( + "complexExample", Objects.toString(parameters().complexExample())) + .putParameters( + "safetyExample", Objects.toString(parameters().safetyExample())) + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class InvalidServiceDefinitionSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + InvalidServiceDefinitionSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") InvalidServiceDefinitionParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .putParameters("serviceName", Objects.toString(parameters().serviceName())) + .putParameters("serviceDef", Objects.toString(parameters().serviceDef())) + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class InvalidTypeDefinitionSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + InvalidTypeDefinitionSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") InvalidTypeDefinitionParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .putParameters("typeName", Objects.toString(parameters().typeName())) + .putParameters("typeDef", Objects.toString(parameters().typeDef())) + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class ConflictingCauseSafeArgException extends RemoteException + implements SerializableErrorProvider { + private ConflictingCauseSafeArgSerializableError error; + + public ConflictingCauseSafeArgException(ConflictingCauseSafeArgSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public ConflictingCauseSafeArgSerializableError error() { + return error; + } + } + + public static final class ConflictingCauseUnsafeArgException extends RemoteException + implements SerializableErrorProvider { + private ConflictingCauseUnsafeArgSerializableError error; + + public ConflictingCauseUnsafeArgException(ConflictingCauseUnsafeArgSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public ConflictingCauseUnsafeArgSerializableError error() { + return error; + } + } + + public static final class ErrorWithComplexArgsException extends RemoteException + implements SerializableErrorProvider { + private ErrorWithComplexArgsSerializableError error; + + public ErrorWithComplexArgsException(ErrorWithComplexArgsSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public ErrorWithComplexArgsSerializableError error() { + return error; + } + } + + public static final class InvalidServiceDefinitionException extends RemoteException + implements SerializableErrorProvider { + private InvalidServiceDefinitionSerializableError error; + + public InvalidServiceDefinitionException(InvalidServiceDefinitionSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public InvalidServiceDefinitionSerializableError error() { + return error; + } + } + + public static final class InvalidTypeDefinitionException extends RemoteException + implements SerializableErrorProvider { + private InvalidTypeDefinitionSerializableError error; + + public InvalidTypeDefinitionException(InvalidTypeDefinitionSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public InvalidTypeDefinitionSerializableError error() { + return error; + } + } } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureJavaErrors.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureJavaErrors.java index def54f2f8..f437f45e0 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureJavaErrors.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/ConjureJavaErrors.java @@ -1,9 +1,15 @@ package dialogue.com.palantir.product; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.palantir.conjure.java.api.errors.AbstractSerializableError; import com.palantir.conjure.java.api.errors.ErrorType; import com.palantir.conjure.java.api.errors.RemoteException; +import com.palantir.conjure.java.api.errors.SerializableError; +import com.palantir.conjure.java.api.errors.SerializableErrorProvider; import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.logsafe.Preconditions; +import com.palantir.logsafe.Safe; import javax.annotation.Nullable; import javax.annotation.processing.Generated; @@ -39,4 +45,40 @@ public static boolean isJavaCompilationFailed(RemoteException remoteException) { Preconditions.checkNotNull(remoteException, "remote exception must not be null"); return JAVA_COMPILATION_FAILED.name().equals(remoteException.getError().errorName()); } + + public static record JavaCompilationFailedParameters() {} + + public static final class JavaCompilationFailedSerializableError + extends AbstractSerializableError { + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + JavaCompilationFailedSerializableError( + @JsonProperty("errorCode") @Safe String errorCode, + @JsonProperty("errorName") @Safe String errorName, + @JsonProperty("errorInstanceId") @Safe String errorInstanceId, + @JsonProperty("parameters") JavaCompilationFailedParameters parameters) { + super(errorCode, errorName, errorInstanceId, parameters); + } + + public SerializableError toSerializableError() { + return SerializableError.builder() + .errorCode(errorCode()) + .errorName(errorName()) + .errorInstanceId(errorInstanceId()) + .build(); + } + } + + public static final class JavaCompilationFailedException extends RemoteException + implements SerializableErrorProvider { + private JavaCompilationFailedSerializableError error; + + public JavaCompilationFailedException(JavaCompilationFailedSerializableError error, int status) { + super(error.toSerializableError(), status); + this.error = error; + } + + public JavaCompilationFailedSerializableError error() { + return error; + } + } } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/DialogueEteEndpoints.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/DialogueEteEndpoints.java index adc77ee3a..7d2e7b517 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/DialogueEteEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/DialogueEteEndpoints.java @@ -882,6 +882,44 @@ public String version() { } }, + /** + * This endpoint is used to test that error parameters serialized as JSON or using Objects.toString are + * both handled correctly by the clients that can deserialize "rich" exceptions (which are sub-types of + * RemoteException). + */ + errorParameterSerialization { + private final PathTemplate pathTemplate = PathTemplate.builder() + .fixed("base") + .fixed("errors") + .fixed("serialization") + .build(); + + @Override + public void renderPath(ListMultimap params, UrlBuilder url) { + pathTemplate.fill(params, url); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.GET; + } + + @Override + public String serviceName() { + return "EteService"; + } + + @Override + public String endpointName() { + return "errorParameterSerialization"; + } + + @Override + public String version() { + return "1.2.3"; + } + }, + aliasLongEndpoint { private final PathTemplate pathTemplate = PathTemplate.builder().fixed("base").fixed("alias-long").build(); diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceAsync.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceAsync.java index 1cb0a894e..002e9256c 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceAsync.java @@ -10,6 +10,7 @@ import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; import com.palantir.dialogue.TypeMarker; @@ -34,11 +35,54 @@ static EmptyPathServiceAsync of(EndpointChannelFactory _endpointChannelFactory, _endpointChannelFactory.endpoint(DialogueEmptyPathEndpoints.emptyPath); private final Deserializer emptyPathDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + dialogue.com.palantir.another.ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorException>() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } @Override public ListenableFuture emptyPath() { Request.Builder _request = Request.builder(); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(emptyPathChannel, _request.build(), emptyPathDeserializer); } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceBlocking.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceBlocking.java index 38a0f3426..e0e4a8fe1 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceBlocking.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EmptyPathServiceBlocking.java @@ -9,6 +9,7 @@ import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; import com.palantir.dialogue.TypeMarker; @@ -33,11 +34,54 @@ static EmptyPathServiceBlocking of(EndpointChannelFactory _endpointChannelFactor _endpointChannelFactory.endpoint(DialogueEmptyPathEndpoints.emptyPath); private final Deserializer emptyPathDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + dialogue.com.palantir.another.ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorException>() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } @Override public boolean emptyPath() { Request.Builder _request = Request.builder(); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(emptyPathChannel, _request.build(), emptyPathDeserializer); } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceAsync.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceAsync.java index 0475a8808..fcb70a714 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceAsync.java @@ -5,13 +5,16 @@ import com.palantir.dialogue.BinaryRequestBody; import com.palantir.dialogue.Channel; import com.palantir.dialogue.ConjureRuntime; +import com.palantir.dialogue.Deserializer; import com.palantir.dialogue.DialogueService; import com.palantir.dialogue.DialogueServiceFactory; import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; 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; @@ -58,31 +61,92 @@ static EteBinaryServiceAsync of(EndpointChannelFactory _endpointChannelFactory, private final EndpointChannel postBinaryChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.postBinary); + private final Deserializer postBinaryDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel postBinaryThrowsChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.postBinaryThrows); + private final Deserializer postBinaryThrowsDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel getOptionalBinaryPresentChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getOptionalBinaryPresent); + private final Deserializer> getOptionalBinaryPresentDeserializer = + _runtime.bodySerDe() + .optionalInputStreamDeserializer( + createExceptionDeserializerArgs(new TypeMarker>() {})); + private final EndpointChannel getOptionalBinaryEmptyChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getOptionalBinaryEmpty); + private final Deserializer> getOptionalBinaryEmptyDeserializer = _runtime.bodySerDe() + .optionalInputStreamDeserializer( + createExceptionDeserializerArgs(new TypeMarker>() {})); + private final EndpointChannel getBinaryFailureChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getBinaryFailure); + private final Deserializer getBinaryFailureDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel getAliasedChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getAliased); + private final Deserializer> getAliasedDeserializer = _runtime.bodySerDe() + .optionalInputStreamDeserializer( + createExceptionDeserializerArgs(new TypeMarker>() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + dialogue.com.palantir.another.ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorException>() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } + @Override public ListenableFuture postBinary(AuthHeader authHeader, BinaryRequestBody body) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(_runtime.bodySerDe().serialize(body)); - return _runtime.clients() - .call( - postBinaryChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().call(postBinaryChannel, _request.build(), postBinaryDeserializer); } @Override @@ -92,33 +156,38 @@ public ListenableFuture postBinaryThrows( _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(_runtime.bodySerDe().serialize(body)); _request.putQueryParams("bytesToRead", _plainSerDe.serializeInteger(bytesToRead)); - return _runtime.clients() - .call( - postBinaryThrowsChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().call(postBinaryThrowsChannel, _request.build(), postBinaryThrowsDeserializer); } @Override public ListenableFuture> getOptionalBinaryPresent(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() - .call( - getOptionalBinaryPresentChannel, - _request.build(), - _runtime.bodySerDe().optionalInputStreamDeserializer()); + .call(getOptionalBinaryPresentChannel, _request.build(), getOptionalBinaryPresentDeserializer); } @Override public ListenableFuture> getOptionalBinaryEmpty(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() - .call( - getOptionalBinaryEmptyChannel, - _request.build(), - _runtime.bodySerDe().optionalInputStreamDeserializer()); + .call(getOptionalBinaryEmptyChannel, _request.build(), getOptionalBinaryEmptyDeserializer); } @Override @@ -128,22 +197,24 @@ public ListenableFuture getBinaryFailure( _request.putHeaderParams("Authorization", authHeader.toString()); _request.putQueryParams("numBytes", _plainSerDe.serializeInteger(numBytes)); _request.putQueryParams("useTryWithResources", _plainSerDe.serializeBoolean(useTryWithResources)); - return _runtime.clients() - .call( - getBinaryFailureChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().call(getBinaryFailureChannel, _request.build(), getBinaryFailureDeserializer); } @Override public ListenableFuture> getAliased(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); - return _runtime.clients() - .call( - getAliasedChannel, - _request.build(), - _runtime.bodySerDe().optionalInputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().call(getAliasedChannel, _request.build(), getAliasedDeserializer); } @Override diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceBlocking.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceBlocking.java index 57533e186..2141a81c6 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceBlocking.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteBinaryServiceBlocking.java @@ -5,13 +5,16 @@ import com.palantir.dialogue.BinaryRequestBody; import com.palantir.dialogue.Channel; import com.palantir.dialogue.ConjureRuntime; +import com.palantir.dialogue.Deserializer; import com.palantir.dialogue.DialogueService; import com.palantir.dialogue.DialogueServiceFactory; import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; 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; @@ -61,31 +64,92 @@ static EteBinaryServiceBlocking of(EndpointChannelFactory _endpointChannelFactor private final EndpointChannel postBinaryChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.postBinary); + private final Deserializer postBinaryDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel postBinaryThrowsChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.postBinaryThrows); + private final Deserializer postBinaryThrowsDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel getOptionalBinaryPresentChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getOptionalBinaryPresent); + private final Deserializer> getOptionalBinaryPresentDeserializer = + _runtime.bodySerDe() + .optionalInputStreamDeserializer( + createExceptionDeserializerArgs(new TypeMarker>() {})); + private final EndpointChannel getOptionalBinaryEmptyChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getOptionalBinaryEmpty); + private final Deserializer> getOptionalBinaryEmptyDeserializer = _runtime.bodySerDe() + .optionalInputStreamDeserializer( + createExceptionDeserializerArgs(new TypeMarker>() {})); + private final EndpointChannel getBinaryFailureChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getBinaryFailure); + private final Deserializer getBinaryFailureDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel getAliasedChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getAliased); + private final Deserializer> getAliasedDeserializer = _runtime.bodySerDe() + .optionalInputStreamDeserializer( + createExceptionDeserializerArgs(new TypeMarker>() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + dialogue.com.palantir.another.ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorException>() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } + @Override public InputStream postBinary(AuthHeader authHeader, BinaryRequestBody body) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(_runtime.bodySerDe().serialize(body)); - return _runtime.clients() - .callBlocking( - postBinaryChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().callBlocking(postBinaryChannel, _request.build(), postBinaryDeserializer); } @Override @@ -94,33 +158,43 @@ public InputStream postBinaryThrows(AuthHeader authHeader, int bytesToRead, Bina _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(_runtime.bodySerDe().serialize(body)); _request.putQueryParams("bytesToRead", _plainSerDe.serializeInteger(bytesToRead)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() - .callBlocking( - postBinaryThrowsChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + .callBlocking(postBinaryThrowsChannel, _request.build(), postBinaryThrowsDeserializer); } @Override public Optional getOptionalBinaryPresent(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking( getOptionalBinaryPresentChannel, _request.build(), - _runtime.bodySerDe().optionalInputStreamDeserializer()); + getOptionalBinaryPresentDeserializer); } @Override public Optional getOptionalBinaryEmpty(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking( - getOptionalBinaryEmptyChannel, - _request.build(), - _runtime.bodySerDe().optionalInputStreamDeserializer()); + getOptionalBinaryEmptyChannel, _request.build(), getOptionalBinaryEmptyDeserializer); } @Override @@ -129,22 +203,25 @@ public InputStream getBinaryFailure(AuthHeader authHeader, int numBytes, boolean _request.putHeaderParams("Authorization", authHeader.toString()); _request.putQueryParams("numBytes", _plainSerDe.serializeInteger(numBytes)); _request.putQueryParams("useTryWithResources", _plainSerDe.serializeBoolean(useTryWithResources)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() - .callBlocking( - getBinaryFailureChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + .callBlocking(getBinaryFailureChannel, _request.build(), getBinaryFailureDeserializer); } @Override public Optional getAliased(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); - return _runtime.clients() - .callBlocking( - getAliasedChannel, - _request.build(), - _runtime.bodySerDe().optionalInputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().callBlocking(getAliasedChannel, _request.build(), getAliasedDeserializer); } @Override diff --git a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteServiceAsync.java b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteServiceAsync.java index c5ee0fde5..d5f200c9f 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/com/palantir/product/EteServiceAsync.java @@ -11,6 +11,7 @@ import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; import com.palantir.dialogue.Serializer; @@ -176,6 +177,16 @@ ListenableFuture> optionalEnumQuery( @ClientEndpoint(method = "GET", path = "/base/errors/header") ListenableFuture jsonErrorsHeader(AuthHeader authHeader, String headerParameter); + /** + * This endpoint is used to test that error parameters serialized as JSON or using Objects.toString are + * both handled correctly by the clients that can deserialize "rich" exceptions (which are sub-types of + * RemoteException). + * + * @apiNote {@code GET /base/errors/serialization} + */ + @ClientEndpoint(method = "GET", path = "/base/errors/serialization") + ListenableFuture errorParameterSerialization(AuthHeader authHeader, String headerParameter); + /** @apiNote {@code GET /base/alias-long} */ @ClientEndpoint(method = "GET", path = "/base/alias-long") ListenableFuture> aliasLongEndpoint(AuthHeader authHeader, Optional input); @@ -209,79 +220,82 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final EndpointChannel stringChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.string); private final Deserializer stringDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel integerChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.integer); private final Deserializer integerDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel double_Channel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.double_); private final Deserializer double_Deserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel boolean_Channel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.boolean_); private final Deserializer boolean_Deserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel safelongChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.safelong); private final Deserializer safelongDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel ridChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.rid); - private final Deserializer ridDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer ridDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel bearertokenChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.bearertoken); - private final Deserializer bearertokenDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer bearertokenDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel optionalStringChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalString); - private final Deserializer> optionalStringDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalStringDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel optionalEmptyChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalEmpty); - private final Deserializer> optionalEmptyDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalEmptyDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel datetimeChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.datetime); - private final Deserializer datetimeDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer datetimeDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel binaryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.binary); + private final Deserializer binaryDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel pathChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.path); private final Deserializer pathDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel externalLongPathChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.externalLongPath); private final Deserializer externalLongPathDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel optionalExternalLongQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalExternalLongQuery); - private final Deserializer> optionalExternalLongQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalExternalLongQueryDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final Serializer notNullBodySerializer = _runtime.bodySerDe().serializer(new TypeMarker() {}); @@ -289,26 +303,26 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final EndpointChannel notNullBodyChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.notNullBody); - private final Deserializer notNullBodyDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer notNullBodyDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel aliasOneChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.aliasOne); - private final Deserializer aliasOneDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer aliasOneDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel optionalAliasOneChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalAliasOne); - private final Deserializer optionalAliasOneDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer optionalAliasOneDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel aliasTwoChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.aliasTwo); - private final Deserializer aliasTwoDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer aliasTwoDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer notNullBodyExternalImportSerializer = _runtime.bodySerDe() @@ -319,7 +333,8 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final Deserializer notNullBodyExternalImportDeserializer = _runtime.bodySerDe() - .deserializer(new TypeMarker() {}); + .deserializer(createExceptionDeserializerArgs( + new TypeMarker() {})); private final Serializer> optionalBodyExternalImportSerializer = _runtime.bodySerDe() @@ -331,64 +346,72 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final Deserializer> optionalBodyExternalImportDeserializer = _runtime.bodySerDe() - .deserializer( - new TypeMarker>() {}); + .deserializer(createExceptionDeserializerArgs( + new TypeMarker< + Optional>() {})); private final EndpointChannel optionalQueryExternalImportChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalQueryExternalImport); private final Deserializer> optionalQueryExternalImportDeserializer = _runtime.bodySerDe() - .deserializer( - new TypeMarker>() {}); + .deserializer(createExceptionDeserializerArgs( + new TypeMarker< + Optional>() {})); private final EndpointChannel noReturnChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.noReturn); - private final Deserializer noReturnDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer noReturnDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel enumQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.enumQuery); private final Deserializer enumQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel enumListQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.enumListQuery); - private final Deserializer> enumListQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> enumListQueryDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel optionalEnumQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalEnumQuery); - private final Deserializer> optionalEnumQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalEnumQueryDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel enumHeaderChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.enumHeader); private final Deserializer enumHeaderDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel jsonErrorsHeaderChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.jsonErrorsHeader); private final Deserializer jsonErrorsHeaderDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private final EndpointChannel errorParameterSerializationChannel = + _endpointChannelFactory.endpoint(DialogueEteEndpoints.errorParameterSerialization); + + private final Deserializer errorParameterSerializationDeserializer = + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel aliasLongEndpointChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.aliasLongEndpoint); - private final Deserializer> aliasLongEndpointDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> aliasLongEndpointDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel complexQueryParametersChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.complexQueryParameters); - private final Deserializer complexQueryParametersDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer complexQueryParametersDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer>> receiveListOfOptionalsSerializer = _runtime.bodySerDe().serializer(new TypeMarker>>() {}); @@ -396,8 +419,8 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final EndpointChannel receiveListOfOptionalsChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.receiveListOfOptionals); - private final Deserializer receiveListOfOptionalsDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer receiveListOfOptionalsDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer>> receiveSetOfOptionalsSerializer = _runtime.bodySerDe().serializer(new TypeMarker>>() {}); @@ -405,8 +428,8 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final EndpointChannel receiveSetOfOptionalsChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.receiveSetOfOptionals); - private final Deserializer receiveSetOfOptionalsDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer receiveSetOfOptionalsDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer> receiveListOfStringsSerializer = _runtime.bodySerDe().serializer(new TypeMarker>() {}); @@ -414,13 +437,56 @@ static EteServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Conjur private final EndpointChannel receiveListOfStringsChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.receiveListOfStrings); - private final Deserializer receiveListOfStringsDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer receiveListOfStringsDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + dialogue.com.palantir.another.ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorException>() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } @Override public ListenableFuture string(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(stringChannel, _request.build(), stringDeserializer); } @@ -428,6 +494,11 @@ public ListenableFuture string(AuthHeader authHeader) { public ListenableFuture integer(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(integerChannel, _request.build(), integerDeserializer); } @@ -435,6 +506,11 @@ public ListenableFuture integer(AuthHeader authHeader) { public ListenableFuture double_(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(double_Channel, _request.build(), double_Deserializer); } @@ -442,6 +518,11 @@ public ListenableFuture double_(AuthHeader authHeader) { public ListenableFuture boolean_(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(boolean_Channel, _request.build(), boolean_Deserializer); } @@ -449,6 +530,11 @@ public ListenableFuture boolean_(AuthHeader authHeader) { public ListenableFuture safelong(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(safelongChannel, _request.build(), safelongDeserializer); } @@ -456,6 +542,11 @@ public ListenableFuture safelong(AuthHeader authHeader) { public ListenableFuture rid(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(ridChannel, _request.build(), ridDeserializer); } @@ -463,6 +554,11 @@ public ListenableFuture rid(AuthHeader authHeader) { public ListenableFuture bearertoken(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(bearertokenChannel, _request.build(), bearertokenDeserializer); } @@ -470,6 +566,11 @@ public ListenableFuture bearertoken(AuthHeader authHeader) { public ListenableFuture> optionalString(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(optionalStringChannel, _request.build(), optionalStringDeserializer); } @@ -477,6 +578,11 @@ public ListenableFuture> optionalString(AuthHeader authHeader) public ListenableFuture> optionalEmpty(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(optionalEmptyChannel, _request.build(), optionalEmptyDeserializer); } @@ -484,6 +590,11 @@ public ListenableFuture> optionalEmpty(AuthHeader authHeader) { public ListenableFuture datetime(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(datetimeChannel, _request.build(), datetimeDeserializer); } @@ -491,11 +602,12 @@ public ListenableFuture datetime(AuthHeader authHeader) { public ListenableFuture binary(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); - return _runtime.clients() - .call( - binaryChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().call(binaryChannel, _request.build(), binaryDeserializer); } @Override @@ -503,6 +615,11 @@ public ListenableFuture path(AuthHeader authHeader, String param) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putPathParams("param", _plainSerDe.serializeString(param)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(pathChannel, _request.build(), pathDeserializer); } @@ -511,6 +628,11 @@ public ListenableFuture externalLongPath(AuthHeader authHeader, long param Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putPathParams("param", Objects.toString(param)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(externalLongPathChannel, _request.build(), externalLongPathDeserializer); } @@ -522,6 +644,11 @@ public ListenableFuture> optionalExternalLongQuery( if (param.isPresent()) { _request.putQueryParams("param", Objects.toString(param.get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call( optionalExternalLongQueryChannel, @@ -535,6 +662,11 @@ public ListenableFuture notNullBody( Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(notNullBodySerializer.serialize(notNullBody)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(notNullBodyChannel, _request.build(), notNullBodyDeserializer); } @@ -544,6 +676,11 @@ public ListenableFuture aliasOne( Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putQueryParams("queryParamName", _plainSerDe.serializeString(queryParamName.get())); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(aliasOneChannel, _request.build(), aliasOneDeserializer); } @@ -557,6 +694,11 @@ public ListenableFuture optionalAliasOne( "queryParamName", _plainSerDe.serializeString(queryParamName.get().get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(optionalAliasOneChannel, _request.build(), optionalAliasOneDeserializer); } @@ -568,6 +710,11 @@ public ListenableFuture aliasTwo( _request.putQueryParams( "queryParamName", _plainSerDe.serializeString(queryParamName.get().get())); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(aliasTwoChannel, _request.build(), aliasTwoDeserializer); } @@ -577,6 +724,11 @@ public ListenableFuture not Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(notNullBodyExternalImportSerializer.serialize(notNullBody)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call( notNullBodyExternalImportChannel, @@ -591,6 +743,11 @@ public ListenableFuture not Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(optionalBodyExternalImportSerializer.serialize(body)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call( optionalBodyExternalImportChannel, @@ -608,6 +765,11 @@ public ListenableFuture not if (query.isPresent()) { _request.putQueryParams("query", Objects.toString(query.get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call( optionalQueryExternalImportChannel, @@ -619,6 +781,11 @@ public ListenableFuture not public ListenableFuture noReturn(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(noReturnChannel, _request.build(), noReturnDeserializer); } @@ -627,6 +794,11 @@ public ListenableFuture enumQuery(AuthHeader authHeader, SimpleEnum Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putQueryParams("queryParamName", Objects.toString(queryParamName)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(enumQueryChannel, _request.build(), enumQueryDeserializer); } @@ -638,6 +810,11 @@ public ListenableFuture> enumListQuery( for (SimpleEnum queryParamNameElement : queryParamName) { _request.putQueryParams("queryParamName", Objects.toString(queryParamNameElement)); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(enumListQueryChannel, _request.build(), enumListQueryDeserializer); } @@ -649,6 +826,11 @@ public ListenableFuture> optionalEnumQuery( if (queryParamName.isPresent()) { _request.putQueryParams("queryParamName", Objects.toString(queryParamName.get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call(optionalEnumQueryChannel, _request.build(), optionalEnumQueryDeserializer); } @@ -658,6 +840,11 @@ public ListenableFuture enumHeader(AuthHeader authHeader, SimpleEnum Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putHeaderParams("Custom-Header", Objects.toString(headerParameter)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(enumHeaderChannel, _request.build(), enumHeaderDeserializer); } @@ -667,9 +854,32 @@ public ListenableFuture jsonErrorsHeader(AuthHeader authHeader, String h _request.putHeaderParams("Authorization", authHeader.toString()); _request.putHeaderParams( "Accept-Conjure-Error-Parameter-Format", _plainSerDe.serializeString(headerParameter)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(jsonErrorsHeaderChannel, _request.build(), jsonErrorsHeaderDeserializer); } + @Override + public ListenableFuture errorParameterSerialization(AuthHeader authHeader, String headerParameter) { + Request.Builder _request = Request.builder(); + _request.putHeaderParams("Authorization", authHeader.toString()); + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", _plainSerDe.serializeString(headerParameter)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients() + .call( + errorParameterSerializationChannel, + _request.build(), + errorParameterSerializationDeserializer); + } + @Override public ListenableFuture> aliasLongEndpoint( AuthHeader authHeader, Optional input) { @@ -679,6 +889,11 @@ public ListenableFuture> aliasLongEndpoint( _request.putQueryParams( "input", Objects.toString(input.get().get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call(aliasLongEndpointChannel, _request.build(), aliasLongEndpointDeserializer); } @@ -702,6 +917,11 @@ public ListenableFuture complexQueryParameters( for (int intsElement : ints) { _request.putQueryParams("ints", _plainSerDe.serializeInteger(intsElement)); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call(complexQueryParametersChannel, _request.build(), complexQueryParametersDeserializer); } @@ -711,6 +931,11 @@ public ListenableFuture receiveListOfOptionals(AuthHeader authHeader, List Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(receiveListOfOptionalsSerializer.serialize(value)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .call(receiveListOfOptionalsChannel, _request.build(), receiveListOfOptionalsDeserializer); } @@ -720,6 +945,11 @@ public ListenableFuture receiveSetOfOptionals(AuthHeader authHeader, Set receiveListOfStrings(AuthHeader authHeader, List optionalQueryExter @ClientEndpoint(method = "GET", path = "/base/errors/header") String jsonErrorsHeader(AuthHeader authHeader, String headerParameter); + /** + * This endpoint is used to test that error parameters serialized as JSON or using Objects.toString are + * both handled correctly by the clients that can deserialize "rich" exceptions (which are sub-types of + * RemoteException). + * + * @apiNote {@code GET /base/errors/serialization} + */ + @ClientEndpoint(method = "GET", path = "/base/errors/serialization") + String errorParameterSerialization(AuthHeader authHeader, String headerParameter); + /** @apiNote {@code GET /base/alias-long} */ @ClientEndpoint(method = "GET", path = "/base/alias-long") Optional aliasLongEndpoint(AuthHeader authHeader, Optional input); @@ -208,79 +219,82 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final EndpointChannel stringChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.string); private final Deserializer stringDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel integerChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.integer); private final Deserializer integerDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel double_Channel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.double_); private final Deserializer double_Deserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel boolean_Channel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.boolean_); private final Deserializer boolean_Deserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel safelongChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.safelong); private final Deserializer safelongDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel ridChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.rid); - private final Deserializer ridDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer ridDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel bearertokenChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.bearertoken); - private final Deserializer bearertokenDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer bearertokenDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel optionalStringChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalString); - private final Deserializer> optionalStringDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalStringDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel optionalEmptyChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalEmpty); - private final Deserializer> optionalEmptyDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalEmptyDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel datetimeChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.datetime); - private final Deserializer datetimeDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer datetimeDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel binaryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.binary); + private final Deserializer binaryDeserializer = _runtime.bodySerDe() + .inputStreamDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + private final EndpointChannel pathChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.path); private final Deserializer pathDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel externalLongPathChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.externalLongPath); private final Deserializer externalLongPathDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel optionalExternalLongQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalExternalLongQuery); - private final Deserializer> optionalExternalLongQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalExternalLongQueryDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final Serializer notNullBodySerializer = _runtime.bodySerDe().serializer(new TypeMarker() {}); @@ -288,26 +302,26 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final EndpointChannel notNullBodyChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.notNullBody); - private final Deserializer notNullBodyDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer notNullBodyDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel aliasOneChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.aliasOne); - private final Deserializer aliasOneDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer aliasOneDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel optionalAliasOneChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalAliasOne); - private final Deserializer optionalAliasOneDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer optionalAliasOneDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel aliasTwoChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.aliasTwo); - private final Deserializer aliasTwoDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + private final Deserializer aliasTwoDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer notNullBodyExternalImportSerializer = _runtime.bodySerDe() @@ -318,7 +332,8 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final Deserializer notNullBodyExternalImportDeserializer = _runtime.bodySerDe() - .deserializer(new TypeMarker() {}); + .deserializer(createExceptionDeserializerArgs( + new TypeMarker() {})); private final Serializer> optionalBodyExternalImportSerializer = _runtime.bodySerDe() @@ -330,64 +345,72 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final Deserializer> optionalBodyExternalImportDeserializer = _runtime.bodySerDe() - .deserializer( - new TypeMarker>() {}); + .deserializer(createExceptionDeserializerArgs( + new TypeMarker< + Optional>() {})); private final EndpointChannel optionalQueryExternalImportChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalQueryExternalImport); private final Deserializer> optionalQueryExternalImportDeserializer = _runtime.bodySerDe() - .deserializer( - new TypeMarker>() {}); + .deserializer(createExceptionDeserializerArgs( + new TypeMarker< + Optional>() {})); private final EndpointChannel noReturnChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.noReturn); - private final Deserializer noReturnDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer noReturnDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel enumQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.enumQuery); private final Deserializer enumQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel enumListQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.enumListQuery); - private final Deserializer> enumListQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> enumListQueryDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel optionalEnumQueryChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.optionalEnumQuery); - private final Deserializer> optionalEnumQueryDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> optionalEnumQueryDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel enumHeaderChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.enumHeader); private final Deserializer enumHeaderDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel jsonErrorsHeaderChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.jsonErrorsHeader); private final Deserializer jsonErrorsHeaderDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private final EndpointChannel errorParameterSerializationChannel = + _endpointChannelFactory.endpoint(DialogueEteEndpoints.errorParameterSerialization); + + private final Deserializer errorParameterSerializationDeserializer = + _runtime.bodySerDe().deserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final EndpointChannel aliasLongEndpointChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.aliasLongEndpoint); - private final Deserializer> aliasLongEndpointDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker>() {}); + private final Deserializer> aliasLongEndpointDeserializer = _runtime.bodySerDe() + .deserializer(createExceptionDeserializerArgs(new TypeMarker>() {})); private final EndpointChannel complexQueryParametersChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.complexQueryParameters); - private final Deserializer complexQueryParametersDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer complexQueryParametersDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer>> receiveListOfOptionalsSerializer = _runtime.bodySerDe().serializer(new TypeMarker>>() {}); @@ -395,8 +418,8 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final EndpointChannel receiveListOfOptionalsChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.receiveListOfOptionals); - private final Deserializer receiveListOfOptionalsDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer receiveListOfOptionalsDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer>> receiveSetOfOptionalsSerializer = _runtime.bodySerDe().serializer(new TypeMarker>>() {}); @@ -404,8 +427,8 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final EndpointChannel receiveSetOfOptionalsChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.receiveSetOfOptionals); - private final Deserializer receiveSetOfOptionalsDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer receiveSetOfOptionalsDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); private final Serializer> receiveListOfStringsSerializer = _runtime.bodySerDe().serializer(new TypeMarker>() {}); @@ -413,13 +436,56 @@ static EteServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, Con private final EndpointChannel receiveListOfStringsChannel = _endpointChannelFactory.endpoint(DialogueEteEndpoints.receiveListOfStrings); - private final Deserializer receiveListOfStringsDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer receiveListOfStringsDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + dialogue.com.palantir.another.ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.another.ConjureErrors + .DifferentPackageErrorException>() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } @Override public String string(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(stringChannel, _request.build(), stringDeserializer); } @@ -427,6 +493,11 @@ public String string(AuthHeader authHeader) { public int integer(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(integerChannel, _request.build(), integerDeserializer); } @@ -434,6 +505,11 @@ public int integer(AuthHeader authHeader) { public double double_(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(double_Channel, _request.build(), double_Deserializer); } @@ -441,6 +517,11 @@ public double double_(AuthHeader authHeader) { public boolean boolean_(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(boolean_Channel, _request.build(), boolean_Deserializer); } @@ -448,6 +529,11 @@ public boolean boolean_(AuthHeader authHeader) { public SafeLong safelong(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(safelongChannel, _request.build(), safelongDeserializer); } @@ -455,6 +541,11 @@ public SafeLong safelong(AuthHeader authHeader) { public ResourceIdentifier rid(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(ridChannel, _request.build(), ridDeserializer); } @@ -462,6 +553,11 @@ public ResourceIdentifier rid(AuthHeader authHeader) { public BearerToken bearertoken(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(bearertokenChannel, _request.build(), bearertokenDeserializer); } @@ -469,6 +565,11 @@ public BearerToken bearertoken(AuthHeader authHeader) { public Optional optionalString(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking(optionalStringChannel, _request.build(), optionalStringDeserializer); } @@ -477,6 +578,11 @@ public Optional optionalString(AuthHeader authHeader) { public Optional optionalEmpty(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking(optionalEmptyChannel, _request.build(), optionalEmptyDeserializer); } @@ -485,6 +591,11 @@ public Optional optionalEmpty(AuthHeader authHeader) { public OffsetDateTime datetime(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(datetimeChannel, _request.build(), datetimeDeserializer); } @@ -492,11 +603,12 @@ public OffsetDateTime datetime(AuthHeader authHeader) { public InputStream binary(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); - return _runtime.clients() - .callBlocking( - binaryChannel, - _request.build(), - _runtime.bodySerDe().inputStreamDeserializer()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } + return _runtime.clients().callBlocking(binaryChannel, _request.build(), binaryDeserializer); } @Override @@ -504,6 +616,11 @@ public String path(AuthHeader authHeader, String param) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putPathParams("param", _plainSerDe.serializeString(param)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(pathChannel, _request.build(), pathDeserializer); } @@ -512,6 +629,11 @@ public long externalLongPath(AuthHeader authHeader, long param) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putPathParams("param", Objects.toString(param)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking(externalLongPathChannel, _request.build(), externalLongPathDeserializer); } @@ -523,6 +645,11 @@ public Optional optionalExternalLongQuery(AuthHeader authHeader, Optional< if (param.isPresent()) { _request.putQueryParams("param", Objects.toString(param.get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking( optionalExternalLongQueryChannel, @@ -535,6 +662,11 @@ public StringAliasExample notNullBody(AuthHeader authHeader, StringAliasExample Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(notNullBodySerializer.serialize(notNullBody)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(notNullBodyChannel, _request.build(), notNullBodyDeserializer); } @@ -543,6 +675,11 @@ public StringAliasExample aliasOne(AuthHeader authHeader, StringAliasExample que Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putQueryParams("queryParamName", _plainSerDe.serializeString(queryParamName.get())); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(aliasOneChannel, _request.build(), aliasOneDeserializer); } @@ -556,6 +693,11 @@ public StringAliasExample optionalAliasOne( "queryParamName", _plainSerDe.serializeString(queryParamName.get().get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking(optionalAliasOneChannel, _request.build(), optionalAliasOneDeserializer); } @@ -567,6 +709,11 @@ public NestedStringAliasExample aliasTwo(AuthHeader authHeader, NestedStringAlia _request.putQueryParams( "queryParamName", _plainSerDe.serializeString(queryParamName.get().get())); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(aliasTwoChannel, _request.build(), aliasTwoDeserializer); } @@ -576,6 +723,11 @@ public allexamples.com.palantir.product.StringAliasExample notNullBodyExternalIm Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(notNullBodyExternalImportSerializer.serialize(notNullBody)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking( notNullBodyExternalImportChannel, @@ -589,6 +741,11 @@ public Optional optionalBod Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(optionalBodyExternalImportSerializer.serialize(body)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking( optionalBodyExternalImportChannel, @@ -604,6 +761,11 @@ public Optional optionalQue if (query.isPresent()) { _request.putQueryParams("query", Objects.toString(query.get())); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking( optionalQueryExternalImportChannel, @@ -615,6 +777,11 @@ public Optional optionalQue public void noReturn(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } _runtime.clients().callBlocking(noReturnChannel, _request.build(), noReturnDeserializer); } @@ -623,6 +790,11 @@ public SimpleEnum enumQuery(AuthHeader authHeader, SimpleEnum queryParamName) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.putQueryParams("queryParamName", Objects.toString(queryParamName)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().callBlocking(enumQueryChannel, _request.build(), enumQueryDeserializer); } @@ -633,6 +805,11 @@ public List enumListQuery(AuthHeader authHeader, List qu for (SimpleEnum queryParamNameElement : queryParamName) { _request.putQueryParams("queryParamName", Objects.toString(queryParamNameElement)); } + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients() .callBlocking(enumListQueryChannel, _request.build(), enumListQueryDeserializer); } @@ -644,6 +821,11 @@ public Optional optionalEnumQuery(AuthHeader authHeader, Optional aliasLongEndpoint(AuthHeader authHeader, Optional input) { Request.Builder _request = Request.builder(); @@ -674,6 +884,11 @@ public Optional aliasLongEndpoint(AuthHeader authHeader, Optional> Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(receiveListOfOptionalsSerializer.serialize(value)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } _runtime.clients() .callBlocking( receiveListOfOptionalsChannel, _request.build(), receiveListOfOptionalsDeserializer); @@ -717,6 +942,11 @@ public void receiveSetOfOptionals(AuthHeader authHeader, Set> v Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(receiveSetOfOptionalsSerializer.serialize(value)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } _runtime.clients() .callBlocking( receiveSetOfOptionalsChannel, _request.build(), receiveSetOfOptionalsDeserializer); @@ -727,6 +957,11 @@ public void receiveListOfStrings(AuthHeader authHeader, List value) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); _request.body(receiveListOfStringsSerializer.serialize(value)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } _runtime.clients() .callBlocking(receiveListOfStringsChannel, _request.build(), receiveListOfStringsDeserializer); } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceAsync.java b/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceAsync.java index 835e97b78..7831a6f68 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceAsync.java @@ -10,9 +10,13 @@ import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; +import com.palantir.dialogue.TypeMarker; import com.palantir.tokens.auth.BearerToken; +import dialogue.com.palantir.another.ConjureErrors; +import dialogue.com.palantir.product.ConjureJavaErrors; import java.lang.Override; import java.lang.String; import java.lang.Void; @@ -33,13 +37,71 @@ static CookieServiceAsync of(EndpointChannelFactory _endpointChannelFactory, Con private final EndpointChannel eatCookiesChannel = _endpointChannelFactory.endpoint(DialogueCookieEndpoints.eatCookies); - private final Deserializer eatCookiesDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer eatCookiesDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseSafeArgSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseSafeArgException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseUnsafeArgSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseUnsafeArgException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ErrorWithComplexArgsSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors.ErrorWithComplexArgsException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidServiceDefinitionSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidServiceDefinitionException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidTypeDefinitionSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidTypeDefinitionException>() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } @Override public ListenableFuture eatCookies(BearerToken token) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Cookie", "PALANTIR_TOKEN=" + _plainSerDe.serializeBearerToken(token)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } return _runtime.clients().call(eatCookiesChannel, _request.build(), eatCookiesDeserializer); } diff --git a/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceBlocking.java b/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceBlocking.java index 78e6e8cc0..4b06d95d1 100644 --- a/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceBlocking.java +++ b/conjure-java-core/src/integrationInput/java/dialogue/test/api/CookieServiceBlocking.java @@ -9,9 +9,13 @@ import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; +import com.palantir.dialogue.TypeMarker; import com.palantir.tokens.auth.BearerToken; +import dialogue.com.palantir.another.ConjureErrors; +import dialogue.com.palantir.product.ConjureJavaErrors; import java.lang.Override; import java.lang.String; import java.lang.Void; @@ -32,13 +36,71 @@ static CookieServiceBlocking of(EndpointChannelFactory _endpointChannelFactory, private final EndpointChannel eatCookiesChannel = _endpointChannelFactory.endpoint(DialogueCookieEndpoints.eatCookies); - private final Deserializer eatCookiesDeserializer = - _runtime.bodySerDe().emptyBodyDeserializer(); + private final Deserializer eatCookiesDeserializer = _runtime.bodySerDe() + .emptyBodyDeserializer(createExceptionDeserializerArgs(new TypeMarker() {})); + + private ExceptionDeserializerArgs createExceptionDeserializerArgs(TypeMarker returnType) { + return ExceptionDeserializerArgs.builder() + .returnType(returnType) + .exception( + ConjureErrors.DIFFERENT_PACKAGE_ERROR.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseSafeArgSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseSafeArgException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.CONFLICTING_CAUSE_UNSAFE_ARG.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseUnsafeArgSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ConflictingCauseUnsafeArgException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.ERROR_WITH_COMPLEX_ARGS.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .ErrorWithComplexArgsSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors.ErrorWithComplexArgsException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.INVALID_SERVICE_DEFINITION.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidServiceDefinitionSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidServiceDefinitionException>() {}) + .exception( + dialogue.com.palantir.product.ConjureErrors.INVALID_TYPE_DEFINITION.name(), + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidTypeDefinitionSerializableError>() {}, + new TypeMarker< + dialogue.com.palantir.product.ConjureErrors + .InvalidTypeDefinitionException>() {}) + .exception( + ConjureJavaErrors.JAVA_COMPILATION_FAILED.name(), + new TypeMarker() {}, + new TypeMarker() {}) + .build(); + } @Override public void eatCookies(BearerToken token) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Cookie", "PALANTIR_TOKEN=" + _plainSerDe.serializeBearerToken(token)); + if (_runtime.bodySerDe().errorParameterFormat().isPresent()) { + _request.putHeaderParams( + "Accept-Conjure-Error-Parameter-Format", + _runtime.bodySerDe().errorParameterFormat().get().toString()); + } _runtime.clients().callBlocking(eatCookiesChannel, _request.build(), eatCookiesDeserializer); } diff --git a/conjure-java-core/src/integrationInput/java/jersey/com/palantir/product/EteService.java b/conjure-java-core/src/integrationInput/java/jersey/com/palantir/product/EteService.java index 6318aae44..a6b10b1ac 100644 --- a/conjure-java-core/src/integrationInput/java/jersey/com/palantir/product/EteService.java +++ b/conjure-java-core/src/integrationInput/java/jersey/com/palantir/product/EteService.java @@ -211,6 +211,18 @@ String jsonErrorsHeader( @HeaderParam("Authorization") @NotNull AuthHeader authHeader, @HeaderParam("Accept-Conjure-Error-Parameter-Format") String headerParameter); + /** + * This endpoint is used to test that error parameters serialized as JSON or using Objects.toString are + * both handled correctly by the clients that can deserialize "rich" exceptions (which are sub-types of + * RemoteException). + */ + @GET + @Path("base/errors/serialization") + @ClientEndpoint(method = "GET", path = "/base/errors/serialization") + String errorParameterSerialization( + @HeaderParam("Authorization") @NotNull AuthHeader authHeader, + @HeaderParam("Accept-Conjure-Error-Parameter-Format") String headerParameter); + @GET @Path("base/alias-long") @ClientEndpoint(method = "GET", path = "/base/alias-long") diff --git a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureErrors.java b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureErrors.java index b33bf14d2..68d0fcf8f 100644 --- a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureErrors.java +++ b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureErrors.java @@ -8,15 +8,15 @@ @Generated("com.palantir.conjure.java.types.ErrorGenerator") public final class ConjureErrors { /** Cause argument conflicts with reserved Throwable cause parameter. */ - public static final ErrorType CONFLICTING_CAUSE_SAFE_ARG = - ErrorType.create(ErrorType.Code.INTERNAL, "Conjure:ConflictingCauseSafeArg"); + public static final ErrorType CONFLICTING_CAUSE_SAFE_ARG_ERR = + ErrorType.create(ErrorType.Code.INTERNAL, "Conjure:ConflictingCauseSafeArgErr"); private ConjureErrors() {} - /** Returns true if the {@link RemoteException} is named Conjure:ConflictingCauseSafeArg */ - public static boolean isConflictingCauseSafeArg(RemoteException remoteException) { + /** Returns true if the {@link RemoteException} is named Conjure:ConflictingCauseSafeArgErr */ + public static boolean isConflictingCauseSafeArgErr(RemoteException remoteException) { Preconditions.checkNotNull(remoteException, "remote exception must not be null"); - return CONFLICTING_CAUSE_SAFE_ARG + return CONFLICTING_CAUSE_SAFE_ARG_ERR .name() .equals(remoteException.getError().errorName()); } diff --git a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureServerErrors.java b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureServerErrors.java index ba840ccc2..d48ed3fd2 100644 --- a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureServerErrors.java +++ b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ConjureServerErrors.java @@ -11,34 +11,35 @@ public final class ConjureServerErrors { private ConjureServerErrors() {} - public static ConflictingCauseSafeArg conflictingCauseSafeArg(@Safe String cause_, @Safe boolean shouldThrow_) { - return new ConflictingCauseSafeArg(cause_, shouldThrow_, null); + public static ConflictingCauseSafeArgErr conflictingCauseSafeArgErr( + @Safe String cause_, @Safe boolean shouldThrow_) { + return new ConflictingCauseSafeArgErr(cause_, shouldThrow_, null); } - public static ConflictingCauseSafeArg conflictingCauseSafeArg( + public static ConflictingCauseSafeArgErr conflictingCauseSafeArgErr( @Safe String cause_, @Safe boolean shouldThrow_, @Nullable Throwable cause) { - return new ConflictingCauseSafeArg(cause_, shouldThrow_, cause); + return new ConflictingCauseSafeArgErr(cause_, shouldThrow_, cause); } /** - * Throws a {@link ConflictingCauseSafeArg} when {@code shouldThrow} is true. + * Throws a {@link ConflictingCauseSafeArgErr} when {@code shouldThrow} is true. * * @param shouldThrow Cause the method to throw when true * @param cause_ * @param shouldThrow_ */ @Contract("true, _, _ -> fail") - public static void throwIfConflictingCauseSafeArg( + public static void throwIfConflictingCauseSafeArgErr( boolean shouldThrow, @Safe String cause_, @Safe boolean shouldThrow_) { if (shouldThrow) { - throw conflictingCauseSafeArg(cause_, shouldThrow_); + throw conflictingCauseSafeArgErr(cause_, shouldThrow_); } } - public static final class ConflictingCauseSafeArg extends EndpointServiceException { - private ConflictingCauseSafeArg(@Safe String cause_, @Safe boolean shouldThrow_, @Nullable Throwable cause) { + public static final class ConflictingCauseSafeArgErr extends EndpointServiceException { + private ConflictingCauseSafeArgErr(@Safe String cause_, @Safe boolean shouldThrow_, @Nullable Throwable cause) { super( - ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG, + ConjureErrors.CONFLICTING_CAUSE_SAFE_ARG_ERR, cause, SafeArg.of("cause", cause_), SafeArg.of("shouldThrow", shouldThrow_)); diff --git a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ErrorServiceEndpoints.java b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ErrorServiceEndpoints.java index 07f135008..80b7b78be 100644 --- a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ErrorServiceEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/ErrorServiceEndpoints.java @@ -60,7 +60,7 @@ private static final class TestBasicErrorEndpoint implements HttpHandler, Endpoi @Override public void handleRequest(HttpServerExchange exchange) - throws IOException, TestServerErrors.InvalidArgument, ConjureServerErrors.ConflictingCauseSafeArg { + throws IOException, TestServerErrors.InvalidArgument, ConjureServerErrors.ConflictingCauseSafeArgErr { AuthHeader authHeader = runtime.auth().header(exchange); Boolean shouldThrowError = deserializer.deserialize(exchange); String result = delegate.testBasicError(authHeader, shouldThrowError); diff --git a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/EteServiceEndpoints.java b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/EteServiceEndpoints.java index bd186ef1f..95cf24d0b 100644 --- a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/EteServiceEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/EteServiceEndpoints.java @@ -73,6 +73,7 @@ public List endpoints(UndertowRuntime runtime) { new OptionalEnumQueryEndpoint(runtime, delegate), new EnumHeaderEndpoint(runtime, delegate), new JsonErrorsHeaderEndpoint(runtime, delegate), + new ErrorParameterSerializationEndpoint(runtime, delegate), new AliasLongEndpointEndpoint(runtime, delegate), new ComplexQueryParametersEndpoint(runtime, delegate), new ReceiveListOfOptionalsEndpoint(runtime, delegate), @@ -1424,6 +1425,55 @@ public HttpHandler handler() { } } + private static final class ErrorParameterSerializationEndpoint implements HttpHandler, Endpoint { + private final UndertowRuntime runtime; + + private final UndertowEteService delegate; + + private final Serializer serializer; + + ErrorParameterSerializationEndpoint(UndertowRuntime runtime, UndertowEteService delegate) { + this.runtime = runtime; + this.delegate = delegate; + this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}, this); + } + + @Override + public void handleRequest(HttpServerExchange exchange) throws IOException { + AuthHeader authHeader = runtime.auth().header(exchange); + HeaderMap headerParams = exchange.getRequestHeaders(); + String headerParameter = + runtime.plainSerDe().deserializeString(headerParams.get("Accept-Conjure-Error-Parameter-Format")); + String result = delegate.errorParameterSerialization(authHeader, headerParameter); + serializer.serialize(result, exchange); + } + + @Override + public HttpString method() { + return Methods.GET; + } + + @Override + public String template() { + return "/base/errors/serialization"; + } + + @Override + public String serviceName() { + return "EteService"; + } + + @Override + public String name() { + return "errorParameterSerialization"; + } + + @Override + public HttpHandler handler() { + return this; + } + } + private static final class AliasLongEndpointEndpoint implements HttpHandler, Endpoint { private final UndertowRuntime runtime; diff --git a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowErrorService.java b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowErrorService.java index 124d41207..2dc96cadc 100644 --- a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowErrorService.java +++ b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowErrorService.java @@ -10,10 +10,10 @@ public interface UndertowErrorService { /** * @apiNote {@code POST /errors/basic} * @throws TestServerErrors.InvalidArgument - * @throws ConjureServerErrors.ConflictingCauseSafeArg + * @throws ConjureServerErrors.ConflictingCauseSafeArgErr */ String testBasicError(AuthHeader authHeader, boolean shouldThrowError) - throws TestServerErrors.InvalidArgument, ConjureServerErrors.ConflictingCauseSafeArg; + throws TestServerErrors.InvalidArgument, ConjureServerErrors.ConflictingCauseSafeArgErr; /** * @apiNote {@code POST /errors/imported} diff --git a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowEteService.java b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowEteService.java index b1afb0f92..49317a936 100644 --- a/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowEteService.java +++ b/conjure-java-core/src/integrationInput/java/undertow/com/palantir/product/UndertowEteService.java @@ -124,6 +124,15 @@ Optional optionalQueryExter */ String jsonErrorsHeader(AuthHeader authHeader, String headerParameter); + /** + * This endpoint is used to test that error parameters serialized as JSON or using Objects.toString are + * both handled correctly by the clients that can deserialize "rich" exceptions (which are sub-types of + * RemoteException). + * + * @apiNote {@code GET /base/errors/serialization} + */ + String errorParameterSerialization(AuthHeader authHeader, String headerParameter); + /** @apiNote {@code GET /base/alias-long} */ Optional aliasLongEndpoint(AuthHeader authHeader, Optional input); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/Options.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/Options.java index d0c62af8b..0d06eb902 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/Options.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/Options.java @@ -202,6 +202,17 @@ default boolean dangerousDoNotUseEnableEndpointAssociatedErrors() { return false; } + /** + * Enabling this flag will lead to the generation of Dialogue client interfaces that are able to send a header to + * servers specifying the Conjure error parameter serialization format they expect, and create custom exceptions for + * each error defined in the service's package. + */ + @Value.Default + @Beta + default boolean generateErrorParameterFormatRespectingDialogueInterfaces() { + return false; + } + /** * Makes immutable copies of collections for union and alias types, respecting the --nonNullCollections flag. */ diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DefaultStaticFactoryMethodGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DefaultStaticFactoryMethodGenerator.java index fa49fdf0f..28e30c717 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DefaultStaticFactoryMethodGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DefaultStaticFactoryMethodGenerator.java @@ -15,9 +15,13 @@ */ package com.palantir.conjure.java.services.dialogue; +import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableMap; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.api.errors.ConjureErrorParameterFormats; import com.palantir.conjure.java.services.Auth; +import com.palantir.conjure.java.util.ErrorGenerationUtils; +import com.palantir.conjure.java.util.Packages; import com.palantir.conjure.java.util.Primitives; import com.palantir.conjure.spec.ArgumentDefinition; import com.palantir.conjure.spec.AuthType; @@ -25,6 +29,7 @@ import com.palantir.conjure.spec.CookieAuthType; import com.palantir.conjure.spec.EndpointDefinition; import com.palantir.conjure.spec.EndpointName; +import com.palantir.conjure.spec.ErrorDefinition; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.HeaderAuthType; import com.palantir.conjure.spec.HeaderParameterType; @@ -46,6 +51,7 @@ import com.palantir.dialogue.Deserializer; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; +import com.palantir.dialogue.ExceptionDeserializerArgs; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; import com.palantir.dialogue.Serializer; @@ -59,6 +65,7 @@ import com.palantir.javapoet.ParameterizedTypeName; import com.palantir.javapoet.TypeName; import com.palantir.javapoet.TypeSpec; +import com.palantir.javapoet.TypeVariableName; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.exceptions.SafeIllegalStateException; import java.util.List; @@ -75,18 +82,21 @@ public final class DefaultStaticFactoryMethodGenerator implements StaticFactoryM private final ParameterTypeMapper parameterTypes; private final ReturnTypeMapper returnTypes; private final StaticFactoryMethodType methodType; + private final List errorDefinitions; public DefaultStaticFactoryMethodGenerator( Options options, TypeNameResolver typeNameResolver, ParameterTypeMapper parameterTypes, ReturnTypeMapper returnTypes, - StaticFactoryMethodType methodType) { + StaticFactoryMethodType methodType, + List errorDefinitions) { this.options = options; this.typeNameResolver = typeNameResolver; this.parameterTypes = parameterTypes; this.returnTypes = returnTypes; this.methodType = methodType; + this.errorDefinitions = errorDefinitions; } @Override @@ -99,6 +109,10 @@ public MethodSpec generate(ServiceDefinition def) { .initializer(CodeBlock.of("$L.plainSerDe()", StaticFactoryMethodGenerator.RUNTIME)) .build()); + if (options.generateErrorParameterFormatRespectingDialogueInterfaces()) { + impl.addMethod(createHelperToConstructExceptionDeserializerArgs()); + } + def.getEndpoints().forEach(endpoint -> { endpoint.getArgs().stream() .filter(arg -> arg.getParamType().accept(ParameterTypeVisitor.IS_BODY)) @@ -127,6 +141,43 @@ public MethodSpec generate(ServiceDefinition def) { return method; } + private ClassName getClassNameInErrorsPackage(ErrorDefinition errorDef, String name) { + return ClassName.get( + Packages.getPrefixedPackage(errorDef.getErrorName().getPackage(), options.packagePrefix()), + ErrorGenerationUtils.errorTypesClassName(errorDef.getNamespace()), + name); + } + + private MethodSpec createHelperToConstructExceptionDeserializerArgs() { + TypeVariableName typeVariableT = TypeVariableName.get("T"); + MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("createExceptionDeserializerArgs") + .addTypeVariable(typeVariableT) + .addModifiers(Modifier.PRIVATE) + .returns(ParameterizedTypeName.get(ClassName.get(ExceptionDeserializerArgs.class), typeVariableT)) + .addParameter(ParameterizedTypeName.get(ClassName.get(TypeMarker.class), typeVariableT), "returnType"); + + CodeBlock.Builder exceptions = CodeBlock.builder() + .add("return $T.<$T>builder()", ExceptionDeserializerArgs.class, typeVariableT) + .add(".returnType(returnType)"); + // Add exceptions from error definitions + for (ErrorDefinition errorDef : errorDefinitions) { + String errorName = errorDef.getErrorName().getName(); + ClassName errorClass = getClassNameInErrorsPackage( + errorDef, CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, errorName)); + ClassName serializableErrorClass = getClassNameInErrorsPackage(errorDef, errorName + "SerializableError"); + ClassName exceptionClass = getClassNameInErrorsPackage(errorDef, errorName + "Exception"); + exceptions.add( + ".exception($T.name(), new $T<$T>() {}, new $T<$T>() {})", + errorClass, + TypeMarker.class, + serializableErrorClass, + TypeMarker.class, + exceptionClass); + } + exceptions.add(".build();"); + return methodBuilder.addCode(exceptions.build()).build(); + } + private ClassName getClassName(ServiceDefinition def) { return methodType.switchBy(Names.blockingClassName(def, options), Names.asyncClassName(def, options)); } @@ -161,7 +212,8 @@ private Optional serializer(EndpointName endpointName, Type type) { private Optional deserializer(EndpointName endpointName, Optional type) { TypeName className = Primitives.box(returnTypes.baseType(type)); - if (returnTypes.isBinaryOrOptionalBinary(className)) { + if (returnTypes.isBinaryOrOptionalBinary(className) + && !options.generateErrorParameterFormatRespectingDialogueInterfaces()) { return Optional.empty(); } @@ -169,8 +221,11 @@ private Optional deserializer(EndpointName endpointName, Optional type, TypeName className) : CodeBlock.of("emptyBodyDeserializer()"); } + private CodeBlock constructDeserializerWithExceptions(Optional type, TypeName className) { + CodeBlock.Builder builder = CodeBlock.builder(); + if (type.isEmpty()) { + builder.add("emptyBodyDeserializer("); + } else if (returnTypes.isBinary(className)) { + builder.add("inputStreamDeserializer("); + } else if (returnTypes.isOptionalBinary(className)) { + builder.add("optionalInputStreamDeserializer("); + } else { + builder.add("deserializer("); + } + return builder.add("createExceptionDeserializerArgs(new $T<$T>() {}))", TypeMarker.class, className) + .build(); + } + private MethodSpec clientImpl(EndpointDefinition def) { List params = parameterTypes.implementationMethodParams(def); MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder( @@ -221,7 +291,8 @@ private MethodSpec clientImpl(EndpointDefinition def) { Names.endpointChannel(def), REQUEST, def.getReturns() - .filter(type -> returnTypes.isBinaryOrOptionalBinary(returnTypes.baseType(type))) + .filter(type -> !options.generateErrorParameterFormatRespectingDialogueInterfaces() + && returnTypes.isBinaryOrOptionalBinary(returnTypes.baseType(type))) .map(type -> StaticFactoryMethodGenerator.RUNTIME + (returnTypes.isOptionalBinary(returnTypes.baseType(type)) ? ".bodySerDe().optionalInputStreamDeserializer()" @@ -229,6 +300,18 @@ private MethodSpec clientImpl(EndpointDefinition def) { .orElseGet(() -> def.getEndpointName().get() + "Deserializer")); methodBuilder.addCode(request); + if (options.generateErrorParameterFormatRespectingDialogueInterfaces()) { + // If the BodySerDe.errorParameterFormat field is set, add the header + methodBuilder.addCode(CodeBlock.builder() + .beginControlFlow("if ($L.bodySerDe().errorParameterFormat().isPresent())", RUNTIME) + .add( + "$L.putHeaderParams($S, $L.bodySerDe().errorParameterFormat().get().toString());", + REQUEST, + ConjureErrorParameterFormats.ACCEPT_CONJURE_ERROR_PARAMETER_FORMAT_HEADER, + RUNTIME) + .endControlFlow() + .build()); + } methodBuilder.addCode(methodType.switchBy(def.getReturns().isPresent() ? "return " : "", "return ")); methodBuilder.addCode(execute); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java index a966afa7e..bd21f72df 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java @@ -75,14 +75,16 @@ public Stream generate(ConjureDefinition conjureDefinition) { typeNameResolver, parameterMapper, new ReturnTypeMapper(returnTypes), - StaticFactoryMethodType.ASYNC); + StaticFactoryMethodType.ASYNC, + conjureDefinition.getErrors()); StaticFactoryMethodGenerator blockingGenerator = new DefaultStaticFactoryMethodGenerator( options, typeNameResolver, parameterMapper, new ReturnTypeMapper(returnTypes), - StaticFactoryMethodType.BLOCKING); + StaticFactoryMethodType.BLOCKING, + conjureDefinition.getErrors()); return conjureDefinition.getServices().stream() .flatMap(serviceDef -> generateFilesForService( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java index a7a873e63..b5ff47a21 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java @@ -16,13 +16,18 @@ package com.palantir.conjure.java.types; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableList; import com.palantir.conjure.java.ConjureAnnotations; import com.palantir.conjure.java.Generator; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.api.errors.AbstractSerializableError; import com.palantir.conjure.java.api.errors.ErrorType; import com.palantir.conjure.java.api.errors.RemoteException; +import com.palantir.conjure.java.api.errors.SerializableError; +import com.palantir.conjure.java.api.errors.SerializableErrorProvider; import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.conjure.java.util.ErrorGenerationUtils; import com.palantir.conjure.java.util.ErrorGenerationUtils.DeclaredEndpointErrors; @@ -31,16 +36,23 @@ import com.palantir.conjure.spec.ConjureDefinition; import com.palantir.conjure.spec.ErrorDefinition; import com.palantir.conjure.spec.ErrorNamespace; +import com.palantir.conjure.spec.FieldDefinition; import com.palantir.conjure.spec.TypeDefinition; +import com.palantir.javapoet.AnnotationSpec; import com.palantir.javapoet.ClassName; import com.palantir.javapoet.CodeBlock; import com.palantir.javapoet.FieldSpec; import com.palantir.javapoet.JavaFile; import com.palantir.javapoet.MethodSpec; +import com.palantir.javapoet.ParameterSpec; +import com.palantir.javapoet.ParameterizedTypeName; import com.palantir.javapoet.TypeName; import com.palantir.javapoet.TypeSpec; +import com.palantir.logsafe.Safe; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -153,7 +165,8 @@ private JavaFile generateErrorTypesForNamespace( }) .collect(Collectors.toList()); - TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(errorTypesClassName(conjurePackage, namespace)) + ClassName errorsClassName = errorTypesClassName(conjurePackage, namespace); + TypeSpec.Builder typeBuilder = TypeSpec.classBuilder(errorsClassName) .addMethod(ErrorGenerationUtils.privateConstructor()) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addFields(generateErrorTypeFields(namespace, errorTypeDefinitions)) @@ -161,6 +174,12 @@ private JavaFile generateErrorTypesForNamespace( .addMethods(checkMethodSpecs) .addMethods(isRemoteExceptionDefinitions) .addAnnotation(ConjureAnnotations.getConjureGeneratedAnnotation(ErrorGenerator.class)); + if (options.generateErrorParameterFormatRespectingDialogueInterfaces()) { + typeBuilder + .addTypes(generateErrorParameterRecords(errorTypeDefinitions, typeMapper)) + .addTypes(generateSerializableErrors(errorTypeDefinitions)) + .addTypes(generateRemoteExceptionTypes(errorsClassName, errorTypeDefinitions)); + } return JavaFile.builder(conjurePackage, typeBuilder.build()) .skipJavaLangImports(true) @@ -168,6 +187,142 @@ private JavaFile generateErrorTypesForNamespace( .build(); } + private static List generateRemoteExceptionTypes( + ClassName errorsClassName, List errorDefinitions) { + return errorDefinitions.stream() + .map(def -> generateRemoteExceptionType(errorsClassName, def)) + .toList(); + } + + private static TypeSpec generateRemoteExceptionType(ClassName errorsClassName, ErrorDefinition errorDefinition) { + String remoteExceptionClassName = errorDefinition.getErrorName().getName() + "Exception"; + ClassName serializableErrorClassName = + errorsClassName.nestedClass(errorDefinition.getErrorName().getName() + "SerializableError"); + + TypeSpec.Builder classBuilder = TypeSpec.classBuilder(remoteExceptionClassName) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .superclass(RemoteException.class) + .addSuperinterface(ParameterizedTypeName.get( + ClassName.get(SerializableErrorProvider.class), + errorsClassName.nestedClass(ErrorGenerationUtils.errorParametersClassName( + errorDefinition.getErrorName().getName())))) + .addField(FieldSpec.builder(serializableErrorClassName, "error") + .addModifiers(Modifier.PRIVATE) + .build()) + .addMethod(MethodSpec.constructorBuilder() + .addModifiers(Modifier.PUBLIC) + .addParameter(serializableErrorClassName, "error") + .addParameter(int.class, "status") + .addStatement("super(error.toSerializableError(), status)") + .addStatement("this.error = error") + .build()) + .addMethod(MethodSpec.methodBuilder("error") + .addModifiers(Modifier.PUBLIC) + .returns(serializableErrorClassName) + .addStatement("return error") + .build()); + + return classBuilder.build(); + } + + private static List generateSerializableErrors(List errorDefinitions) { + return errorDefinitions.stream() + .map(ErrorGenerator::generateSerializableError) + .toList(); + } + + private static TypeSpec generateSerializableError(ErrorDefinition errorDefinition) { + String serializableErrorClassName = errorDefinition.getErrorName().getName() + "SerializableError"; + String parameterClassNameString = ErrorGenerationUtils.errorParametersClassName( + errorDefinition.getErrorName().getName()); + ClassName parametersClassName = ClassName.get("", parameterClassNameString); + + // Create constructor + MethodSpec constructor = MethodSpec.constructorBuilder() + .addAnnotation(AnnotationSpec.builder(JsonCreator.class) + .addMember("mode", "$T.$L", JsonCreator.Mode.class, JsonCreator.Mode.PROPERTIES) + .build()) + .addParameter(ParameterSpec.builder(ClassName.get(String.class), "errorCode") + .addAnnotation(AnnotationSpec.builder(JsonProperty.class) + .addMember("value", "$S", "errorCode") + .build()) + .addAnnotation(Safe.class) + .build()) + .addParameter(ParameterSpec.builder(ClassName.get(String.class), "errorName") + .addAnnotation(AnnotationSpec.builder(JsonProperty.class) + .addMember("value", "$S", "errorName") + .build()) + .addAnnotation(Safe.class) + .build()) + .addParameter(ParameterSpec.builder(ClassName.get(String.class), "errorInstanceId") + .addAnnotation(AnnotationSpec.builder(JsonProperty.class) + .addMember("value", "$S", "errorInstanceId") + .build()) + .addAnnotation(Safe.class) + .build()) + .addParameter(ParameterSpec.builder(parametersClassName, "parameters") + .addAnnotation(AnnotationSpec.builder(JsonProperty.class) + .addMember("value", "$S", "parameters") + .build()) + .build()) + .addStatement("super(errorCode, errorName, errorInstanceId, parameters)") + .build(); + + // Create the toSerializableError method + MethodSpec.Builder toSerializableErrorBuilder = MethodSpec.methodBuilder("toSerializableError") + .addModifiers(Modifier.PUBLIC) + .returns(SerializableError.class); + CodeBlock.Builder builder = CodeBlock.builder().add("return $T.builder()", SerializableError.class); + + // Add all parameters + List allArgs = new ArrayList<>(); + allArgs.addAll(errorDefinition.getSafeArgs()); + allArgs.addAll(errorDefinition.getUnsafeArgs()); + for (int i = 0; i < allArgs.size(); i++) { + FieldDefinition field = allArgs.get(i); + String fieldName = field.getFieldName().get(); + builder.add(".putParameters($S, $T.toString(parameters().$L()))", fieldName, Objects.class, fieldName); + } + builder.add(".errorCode(errorCode())") + .add(".errorName(errorName())") + .add(".errorInstanceId(errorInstanceId())") + .add(".build();"); + toSerializableErrorBuilder.addCode(builder.build()); + + // Create the class + TypeSpec.Builder classBuilder = TypeSpec.classBuilder(serializableErrorClassName) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .superclass( + ParameterizedTypeName.get(ClassName.get(AbstractSerializableError.class), parametersClassName)) + .addMethod(constructor) + .addMethod(toSerializableErrorBuilder.build()); + + return classBuilder.build(); + } + + private static List generateErrorParameterRecords( + List errorTypeDefinitions, TypeMapper typeMapper) { + return errorTypeDefinitions.stream() + .map(errorDefinition -> generateErrorParameterRecord(errorDefinition, typeMapper)) + .toList(); + } + + private static TypeSpec generateErrorParameterRecord(ErrorDefinition errorDefinition, TypeMapper typeMapper) { + TypeSpec.Builder parametersRecordBuilder = TypeSpec.recordBuilder(ErrorGenerationUtils.errorParametersClassName( + errorDefinition.getErrorName().getName())) + .addModifiers(Modifier.PUBLIC, Modifier.STATIC); + MethodSpec.Builder ctorBuilder = MethodSpec.constructorBuilder(); + for (FieldDefinition fieldDef : errorDefinition.getSafeArgs()) { + ctorBuilder.addParameter(ErrorGenerationUtils.buildUnsanitizedParameterWithSafetyAnnotationAndJsonProperty( + typeMapper, fieldDef, true)); + } + for (FieldDefinition fieldDef : errorDefinition.getUnsafeArgs()) { + ctorBuilder.addParameter(ErrorGenerationUtils.buildUnsanitizedParameterWithSafetyAnnotationAndJsonProperty( + typeMapper, fieldDef, false)); + } + return parametersRecordBuilder.recordConstructor(ctorBuilder.build()).build(); + } + private static MethodSpec generateExceptionFactory( TypeMapper typeMapper, ErrorDefinition entry, boolean withCause) { String methodName = CaseFormat.UPPER_CAMEL.to( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/ErrorGenerationUtils.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/ErrorGenerationUtils.java index 1c871d4b4..3cfe96962 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/ErrorGenerationUtils.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/ErrorGenerationUtils.java @@ -16,6 +16,7 @@ package com.palantir.conjure.java.util; +import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableList; import com.palantir.conjure.java.ConjureAnnotations; @@ -62,6 +63,10 @@ public static String errorTypesClassName(ErrorNamespace namespace) { return namespace.get() + "Errors"; } + public static String errorParametersClassName(String errorName) { + return errorName + "Parameters"; + } + public record DeclaredEndpointErrors(Set errors) { public static DeclaredEndpointErrors from(ConjureDefinition definition) { return new DeclaredEndpointErrors(definition.getServices().stream() @@ -145,15 +150,27 @@ public static void addAllParametersWithSafetyAnnotationsToMethodBuilder( public static ParameterSpec buildParameterWithSafetyAnnotation( TypeMapper typeMapper, FieldDefinition argDefinition, boolean isSafe) { - return buildParameterWithSafetyAnnotationInternal(typeMapper, argDefinition, isSafe) + return buildParameterWithSafetyAnnotationInternal(typeMapper, argDefinition, isSafe, true) .build(); } - private static ParameterSpec.Builder buildParameterWithSafetyAnnotationInternal( + public static ParameterSpec buildUnsanitizedParameterWithSafetyAnnotationAndJsonProperty( TypeMapper typeMapper, FieldDefinition argDefinition, boolean isSafe) { + ParameterSpec.Builder parameterBuilder = + buildParameterWithSafetyAnnotationInternal(typeMapper, argDefinition, isSafe, false); + parameterBuilder.addAnnotation(AnnotationSpec.builder(JsonProperty.class) + .addMember("value", "$S", argDefinition.getFieldName().get()) + .build()); + return parameterBuilder.build(); + } + + private static ParameterSpec.Builder buildParameterWithSafetyAnnotationInternal( + TypeMapper typeMapper, FieldDefinition argDefinition, boolean isSafe, boolean sanitizeName) { Optional safety = Optional.of(isSafe ? LogSafety.SAFE : LogSafety.UNSAFE); - String argName = JavaNameSanitizer.sanitizeErrorParameterName( - argDefinition.getFieldName().get()); + String argName = sanitizeName + ? JavaNameSanitizer.sanitizeErrorParameterName( + argDefinition.getFieldName().get()) + : argDefinition.getFieldName().get(); TypeName argType = ConjureAnnotations.withSafety(typeMapper.getClassName(argDefinition.getType()), safety); ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(argType, argName); argDefinition diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/JerseyEteResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/JerseyEteResource.java index 6e801f0c0..5810db419 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/JerseyEteResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/JerseyEteResource.java @@ -179,6 +179,12 @@ public String jsonErrorsHeader(AuthHeader authHeader, String _headerParameter) { return "hello!"; } + @Override + public String errorParameterSerialization(AuthHeader authHeader, String headerParameter) { + // Conjure-Java has not supported Jersey for a while. We are not testing the error serialization feature here. + return "hello!"; + } + @Override public Optional aliasLongEndpoint(AuthHeader _authHeader, Optional input) { return input; diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowEteResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowEteResource.java index 6dfbd2707..6517c9016 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowEteResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowEteResource.java @@ -16,12 +16,29 @@ package com.palantir.conjure.java; +import com.palantir.conjure.java.lib.Bytes; import com.palantir.conjure.java.lib.SafeLong; import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; import com.palantir.ri.ResourceIdentifier; import com.palantir.tokens.auth.AuthHeader; import com.palantir.tokens.auth.BearerToken; +import errors.com.palantir.product.AnyExample; +import errors.com.palantir.product.CollectionAlias; +import errors.com.palantir.product.CollectionExample; +import errors.com.palantir.product.ComplexExample; import errors.com.palantir.product.ConjureErrors; +import errors.com.palantir.product.EmptyObject; +import errors.com.palantir.product.EnumExample; +import errors.com.palantir.product.ExternalExample; +import errors.com.palantir.product.NestedAlias; +import errors.com.palantir.product.NestedCollectionExample; +import errors.com.palantir.product.ObjectReference; +import errors.com.palantir.product.OptionalAlias; +import errors.com.palantir.product.OptionalExample; +import errors.com.palantir.product.PrimitiveExample; +import errors.com.palantir.product.SafetyExample; +import errors.com.palantir.product.StringAliasEx; +import errors.com.palantir.product.UnionExample; import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.core.StreamingOutput; import java.nio.charset.StandardCharsets; @@ -30,8 +47,10 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.UUID; import undertow.com.palantir.product.LongAlias; import undertow.com.palantir.product.NestedStringAliasExample; import undertow.com.palantir.product.SimpleEnum; @@ -178,6 +197,109 @@ public String jsonErrorsHeader(AuthHeader authHeader, String headerParameter) { throw ConjureErrors.invalidServiceDefinition("my-service-string", Optional.of(SimpleEnum.VALUE)); } + @Override + public String errorParameterSerialization(AuthHeader authHeader, String headerParameter) { + if (headerParameter.startsWith("JSON") || headerParameter.equals("TOSTRING")) { + throw ConjureErrors.errorWithComplexArgs( + PrimitiveExample.builder() + .stringVal("example-string") + .intVal(42) + .longVal(SafeLong.of(42)) + .doubleVal(3.14) + .boolVal(true) + .ridVal(ResourceIdentifier.of("ri.service.instance.folder.object")) + .uuidVal(UUID.fromString("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) + .datetimeVal(OffsetDateTime.MIN) + .binaryVal(Bytes.from("hello".getBytes(StandardCharsets.UTF_8))) + .build(), + CollectionExample.builder() + .stringList(List.of("foo", "bar", "baz")) + .stringSet(Set.of("alpha", "beta")) + .stringMap(Map.of("key1", "value1", "key2", "value2")) + .build(), + NestedCollectionExample.builder() + .nestedList(List.of(List.of("nested1", "nested2"), List.of("nested3", "nested4"))) + .nestedMap(Map.of( + "outer1", Map.of("inner1", "value1", "inner2", "value2"), + "outer2", Map.of("inner3", "value3"))) + .mixedCollection(Map.of( + "objects", + List.of( + ObjectReference.builder() + .name("obj1") + .value(100) + .build(), + ObjectReference.builder() + .name("obj2") + .value(200) + .build()))) + .build(), + OptionalExample.builder() + .optionalString(Optional.of("optional-value")) + .optionalObject(Optional.of(ObjectReference.builder() + .name("optional-obj") + .value(42) + .build())) + .optionalCollection(Optional.of(List.of("opt1", "opt2"))) + .build(), + ObjectReference.builder() + .name("reference-object") + .value(999) + .build(), + UnionExample.stringVariant("union-string-value"), + EnumExample.A, + StringAliasEx.of("aliased-string"), + OptionalAlias.of(Optional.of("optional-aliased-string")), + CollectionAlias.of(List.of("alias1", "alias2", "alias3")), + NestedAlias.of(StringAliasEx.of("nested-alias-value")), + ExternalExample.builder() + .externalLong(456L) + .optionalExternal(Optional.of(789L)) + .build(), + AnyExample.builder() + .anyValue("any-type-value") + .anyMap(Map.of( + "anyKey", + "anyValue", + "anotherKey", + 123, + "complexObjectKey", + ObjectReference.builder() + .name("complex1") + .value(1) + .build())) + .build(), + EmptyObject.of(), + ComplexExample.builder() + .metadata(Map.of( + StringAliasEx.of("meta1"), + Optional.of(List.of( + ObjectReference.builder() + .name("complex1") + .value(1) + .build(), + ObjectReference.builder() + .name("complex2") + .value(2) + .build())), + StringAliasEx.of("meta2"), Optional.empty())) + .status(EnumExample.B) + .variants(List.of( + UnionExample.intVariant(42), + UnionExample.objectVariant(ObjectReference.builder() + .name("variant-obj") + .value(99) + .build()))) + .external(Optional.of(999L)) + .build(), + SafetyExample.builder() + .safeString("safe-string-value") + .unsafeDouble(2.718) + .build()); + } + return "hello!"; + } + @Override public Optional aliasLongEndpoint(AuthHeader _authHeader, Optional input) { return input; diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowServiceEteTest.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowServiceEteTest.java index 92d317a6f..3e1d70147 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowServiceEteTest.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowServiceEteTest.java @@ -37,6 +37,7 @@ import com.palantir.dialogue.clients.DialogueClients; import com.palantir.ri.ResourceIdentifier; import com.palantir.tokens.auth.AuthHeader; +import dialogue.com.palantir.product.ConjureErrors.ErrorWithComplexArgsException; import dialogue.com.palantir.product.EteBinaryServiceBlocking; import dialogue.com.palantir.product.EteServiceAsync; import dialogue.com.palantir.product.EteServiceBlocking; @@ -62,9 +63,11 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; import jersey.com.palantir.product.EmptyPathService; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -565,6 +568,57 @@ public void testErrorParametersSerializedAsJson() { } } + @Test + public void testStringParametersDoNotChangeWhenUsingJsonAndJavaString() { + Map toStringParams = Map.of(); + Map jsonParams = Map.of(); + try { + // The `TOSTRING` header does nothing: it's not used in `ConjureExceptions` to change any serialization + // behavior. It's just a way to tell the EteResource to throw an error. + client.errorParameterSerialization(AuthHeader.valueOf("authHeader"), "TOSTRING"); + } catch (RemoteException e) { + toStringParams = e.getError().parameters(); + } + + // Get the parameters when we use JSON serialization + try { + // The `JSON` header is read by `ConjureExceptions` to change the serialization behavior. The `JSON` + // representation of the parameters is sent in the `parameters` field of the Conjure error. + client.errorParameterSerialization(AuthHeader.valueOf("authHeader"), "JSON"); + } catch (RemoteException e) { + // .getError() returns the SerializableError which should contain the legacy parameters sent over the wire. + jsonParams = e.getError().parameters(); + // e should be an instance of ErrorWithComplexArgsException, which has rich parameters as well + assertThat(e).isInstanceOfSatisfying(ErrorWithComplexArgsException.class, exception -> { + assertThat(exception.error().parameters().optionalExample().getOptionalString()) + .contains("optional-value"); + }); + } + + // Assert that the two maps contain the same keys and values, except for the `primitiveExample` and `anyExample` + // keys. Those will differ. + List keysThatDiffer = List.of("primitiveExample", "anyExample"); + assertThat(filterKeys(toStringParams, keysThatDiffer)) + .containsExactlyInAnyOrderEntriesOf(filterKeys(jsonParams, keysThatDiffer)); + + // The representation of bytes differs. + String commonFieldsForPrimitive = + "PrimitiveExample{stringVal: example-string, intVal: 42, longVal: 42, doubleVal: 3.14, " + + "boolVal: true, ridVal: ri.service.instance.folder.object, " + + "uuidVal: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee, " + + "datetimeVal: -999999999-01-01T00:00+18:00, binaryVal: "; + + assertThat(toStringParams.get("primitiveExample")).isEqualTo(commonFieldsForPrimitive + "Bytes{size: 5}}"); + assertThat(jsonParams.get("primitiveExample")) + .isEqualTo(commonFieldsForPrimitive + "java.nio.HeapByteBuffer[pos=0 lim=5 cap=5]}"); + } + + private static Map filterKeys(Map map, List keysToFilter) { + return map.entrySet().stream() + .filter(entry -> !keysToFilter.contains(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + private static HttpURLConnection openConnectionToTestApi(String path) throws IOException { URL url = new URL("http://localhost:" + port + "/test-example/api" + path); return (HttpURLConnection) url.openConnection(); diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/parameterized/TestCases.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/parameterized/TestCases.java index ee8f89eb8..b6600982f 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/parameterized/TestCases.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/parameterized/TestCases.java @@ -176,7 +176,10 @@ public final class TestCases { .files(Path.of("ete-service.yml")) .files(Path.of("ete-binary.yml")) .files(Path.of("example-errors.yml")) - .options(Options.builder().apiVersion("1.2.3").build()) + .options(Options.builder() + .apiVersion("1.2.3") + .generateErrorParameterFormatRespectingDialogueInterfaces(true) + .build()) .generatorTypes(List.of(GeneratorType.DIALOGUE, GeneratorType.OBJECT, GeneratorType.ERROR)) .build()) .add(ParameterizedTestCase.builder() diff --git a/conjure-java-core/src/test/resources/ete-service.yml b/conjure-java-core/src/test/resources/ete-service.yml index 0fe520283..be68e6fe4 100644 --- a/conjure-java-core/src/test/resources/ete-service.yml +++ b/conjure-java-core/src/test/resources/ete-service.yml @@ -217,6 +217,19 @@ services: type: string returns: string + errorParameterSerialization: + http: GET /errors/serialization + docs: | + This endpoint is used to test that error parameters serialized as JSON or using `Objects.toString` are + both handled correctly by the clients that can deserialize "rich" exceptions (which are sub-types of + `RemoteException`). + args: + headerParameter: + param-type: header + param-id: Accept-Conjure-Error-Parameter-Format + type: string + returns: string + aliasLongEndpoint: http: GET /alias-long args: diff --git a/conjure-java-core/src/test/resources/example-endpoint-errors.yml b/conjure-java-core/src/test/resources/example-endpoint-errors.yml index 464ffaa70..929500640 100644 --- a/conjure-java-core/src/test/resources/example-endpoint-errors.yml +++ b/conjure-java-core/src/test/resources/example-endpoint-errors.yml @@ -33,7 +33,7 @@ types: code: INTERNAL safe-args: complicatedObjectMap: map - ConflictingCauseSafeArg: + ConflictingCauseSafeArgErr: namespace: Conjure docs: Cause argument conflicts with reserved Throwable cause parameter. code: INTERNAL @@ -54,7 +54,7 @@ services: returns: string errors: - InvalidArgument - - ConflictingCauseSafeArg + - ConflictingCauseSafeArgErr testImportedError: http: POST /imported args: diff --git a/conjure-java-undertow-runtime/src/test/java/com/palantir/conjure/java/undertow/runtime/ConjureExceptionHandlerTest.java b/conjure-java-undertow-runtime/src/test/java/com/palantir/conjure/java/undertow/runtime/ConjureExceptionHandlerTest.java index 9a8247be8..8cac4d233 100644 --- a/conjure-java-undertow-runtime/src/test/java/com/palantir/conjure/java/undertow/runtime/ConjureExceptionHandlerTest.java +++ b/conjure-java-undertow-runtime/src/test/java/com/palantir/conjure/java/undertow/runtime/ConjureExceptionHandlerTest.java @@ -138,6 +138,7 @@ static Stream differentPackageExceptions() { Arguments.of((Supplier) () -> new DifferentPackageEndpointException(null))); } + @SuppressWarnings("removal") private static final class DifferentPackageCheckedException extends CheckedServiceException { @SuppressWarnings("removal") private DifferentPackageCheckedException(@Nullable Throwable cause) { @@ -145,6 +146,7 @@ private DifferentPackageCheckedException(@Nullable Throwable cause) { } } + @SuppressWarnings("removal") private static final class DifferentPackageEndpointException extends CheckedServiceException { @SuppressWarnings("removal") private DifferentPackageEndpointException(@Nullable Throwable cause) { @@ -186,6 +188,7 @@ static Stream exceptionsWithOptionals() { private record ArgumentWithOptionals(Optional> optOfList, List> listOfOpt) {} + @SuppressWarnings("removal") private static final class OptionalCheckedException extends CheckedServiceException { @SuppressWarnings("removal") diff --git a/conjure-java/src/main/java/com/palantir/conjure/java/cli/ConjureJavaCli.java b/conjure-java/src/main/java/com/palantir/conjure/java/cli/ConjureJavaCli.java index e26a75f45..e0abd56cd 100644 --- a/conjure-java/src/main/java/com/palantir/conjure/java/cli/ConjureJavaCli.java +++ b/conjure-java/src/main/java/com/palantir/conjure/java/cli/ConjureJavaCli.java @@ -246,6 +246,16 @@ public static final class GenerateCommand implements Runnable { + "This feature is currently not supported.") private boolean dangerousDoNotUseEnableEndpointAssociatedErrors; + @CommandLine.Option( + names = "--generateErrorParameterFormatRespectingDialogueInterfaces", + defaultValue = "false", + description = + "Enabling this flag will lead to the generation of Dialogue client interfaces that are able to" + + " send a header to servers specifying the Conjure error parameter serialization format" + + " they expect, and create custom exceptions for each error defined in the service's" + + " package.") + private boolean generateErrorParameterFormatRespectingDialogueInterfaces; + @SuppressWarnings("unused") @CommandLine.Unmatched private List unmatchedOptions; @@ -320,6 +330,8 @@ CliConfiguration getConfiguration() { .defensiveCollections(defensiveCollections) .dangerousDoNotUseEnableEndpointAssociatedErrors( dangerousDoNotUseEnableEndpointAssociatedErrors) + .generateErrorParameterFormatRespectingDialogueInterfaces( + generateErrorParameterFormatRespectingDialogueInterfaces) .build()) .build(); } diff --git a/versions.lock b/versions.lock index b9ebe3409..deef6b203 100644 --- a/versions.lock +++ b/versions.lock @@ -44,11 +44,11 @@ com.palantir.conjure:conjure-api-objects:4.50.0 (3 constraints: 9327531f) com.palantir.conjure:conjure-generator-common:4.50.0 (2 constraints: fd13a782) -com.palantir.conjure.java.api:errors:2.64.0 (8 constraints: a094bf79) +com.palantir.conjure.java.api:errors:2.65.0 (8 constraints: aa94e57c) -com.palantir.conjure.java.api:service-config:2.64.0 (6 constraints: 3466fcd7) +com.palantir.conjure.java.api:service-config:2.65.0 (6 constraints: 3d66b5d9) -com.palantir.conjure.java.api:ssl-config:2.64.0 (5 constraints: b44fa72d) +com.palantir.conjure.java.api:ssl-config:2.65.0 (5 constraints: b84f512e) com.palantir.conjure.java.runtime:client-config:8.24.0 (6 constraints: ae6b4e29) @@ -60,19 +60,19 @@ com.palantir.conjure.java.runtime:keystores:8.24.0 (3 constraints: 172ac85d) com.palantir.deadlines:deadlines:0.15.0 (2 constraints: 9f1404ac) -com.palantir.dialogue:dialogue-apache-hc5-client:6.8.0 (2 constraints: 1b2977b6) +com.palantir.dialogue:dialogue-apache-hc5-client:6.8.0-30-gc323cd4 (2 constraints: 352ca5b6) -com.palantir.dialogue:dialogue-blocking-channels:6.8.0 (2 constraints: 7b235c73) +com.palantir.dialogue:dialogue-blocking-channels:6.8.0-30-gc323cd4 (2 constraints: af2987e1) -com.palantir.dialogue:dialogue-clients:6.8.0 (1 constraints: 10052136) +com.palantir.dialogue:dialogue-clients:6.8.0-30-gc323cd4 (1 constraints: 2a08ad85) -com.palantir.dialogue:dialogue-core:6.8.0 (3 constraints: ec3c9a41) +com.palantir.dialogue:dialogue-core:6.8.0-30-gc323cd4 (3 constraints: 20434a0e) -com.palantir.dialogue:dialogue-futures:6.8.0 (3 constraints: 41333839) +com.palantir.dialogue:dialogue-futures:6.8.0-30-gc323cd4 (3 constraints: 8f3ca187) -com.palantir.dialogue:dialogue-serde:6.8.0 (3 constraints: 2a2e8232) +com.palantir.dialogue:dialogue-serde:6.8.0-30-gc323cd4 (3 constraints: 5e34f448) -com.palantir.dialogue:dialogue-target:6.8.0 (7 constraints: d777644e) +com.palantir.dialogue:dialogue-target:6.8.0-30-gc323cd4 (7 constraints: 738afb3f) com.palantir.goethe:goethe:0.16.0 (1 constraints: 3905353b) @@ -124,7 +124,7 @@ com.squareup:javapoet:1.13.0 (1 constraints: f50b65f7) info.picocli:picocli:4.7.7 (1 constraints: 14051b36) -io.dropwizard.metrics:metrics-core:4.2.33 (28 constraints: f5e67410) +io.dropwizard.metrics:metrics-core:4.2.36 (28 constraints: fee68031) io.smallrye.common:smallrye-common-constraint:2.4.0 (3 constraints: c633ce60) @@ -154,7 +154,7 @@ org.apache.commons:commons-lang3:3.18.0 (3 constraints: fe2123fa) org.apache.httpcomponents.client5:httpclient5:5.4.3 (3 constraints: f43937e8) -org.apache.httpcomponents.core5:httpcore5:5.3.4 (4 constraints: 034863a7) +org.apache.httpcomponents.core5:httpcore5:5.3.5 (4 constraints: 0448f8a7) org.apache.httpcomponents.core5:httpcore5-h2:5.3.4 (1 constraints: 4013103c) @@ -238,7 +238,7 @@ com.netflix.feign:feign-jackson:8.18.0 (1 constraints: c718909e) com.palantir.conjure:conjure-core:4.50.0 (1 constraints: 3b054b3b) -com.palantir.conjure.java.api:test-utils:2.64.0 (1 constraints: 3e054f3b) +com.palantir.conjure.java.api:test-utils:2.65.0 (1 constraints: 3e054f3b) com.palantir.conjure.java.runtime:conjure-java-annotations:8.24.0 (1 constraints: c418889e) diff --git a/versions.props b/versions.props index 347cb6cf8..ed7eef086 100644 --- a/versions.props +++ b/versions.props @@ -11,7 +11,7 @@ com.palantir.conjure.java.runtime:* = 8.24.0 com.palantir.conjure.verification:* = 0.19.0 com.palantir.conjure:* = 4.50.0 com.palantir.deadlines:* = 0.15.0 -com.palantir.dialogue:* = 6.8.0 +com.palantir.dialogue:* = 6.8.0-30-gc323cd4 com.palantir.goethe:* = 0.16.0 com.palantir.human-readable-types:* = 1.7.0 com.palantir.javapoet:javapoet = 0.7.0