diff --git a/.chronus/changes/fix-per-client-serviceversion-2026-7-17-11-10-0.md b/.chronus/changes/fix-per-client-serviceversion-2026-7-17-11-10-0.md new file mode 100644 index 00000000000..cc513156429 --- /dev/null +++ b/.chronus/changes/fix-per-client-serviceversion-2026-7-17-11-10-0.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/http-client-java" +--- + +Fix multi-client packages generating a separate `ServiceVersion` enum per client when all clients share the same api-versions. The api-version comparison now compares version strings instead of `ApiVersion` object references, restoring a single shared `ServiceVersion` for such packages. diff --git a/packages/http-client-java/emitter/src/code-model-builder.ts b/packages/http-client-java/emitter/src/code-model-builder.ts index 0cfbd588a8d..a5672b10976 100644 --- a/packages/http-client-java/emitter/src/code-model-builder.ts +++ b/packages/http-client-java/emitter/src/code-model-builder.ts @@ -842,9 +842,13 @@ export class CodeModelBuilder { // first client, set it to sharedApiVersions sharedApiVersions = apiVersions; } else { + // Compare the api-version strings, not the ApiVersion object references. Each client + // builds its own ApiVersion instances (see `new ApiVersion()` above), so reference + // equality ("===") would always be false for clients that in fact share the same + // api-versions, incorrectly producing a separate ServiceVersion enum per client. apiVersionSameForAllClients = sharedApiVersions.length === apiVersions.length && - sharedApiVersions.every((it, index) => it === apiVersions[index]); + sharedApiVersions.every((it, index) => it.version === apiVersions[index].version); } if (!apiVersionSameForAllClients) { break; diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaAsyncClient.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaAsyncClient.java new file mode 100644 index 00000000000..8226df498a8 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaAsyncClient.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceClient; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.exception.ClientAuthenticationException; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.exception.ResourceModifiedException; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.http.rest.Response; +import com.azure.core.util.BinaryData; +import com.azure.core.util.FluxUtil; +import reactor.core.publisher.Mono; +import tsptest.multipleclientssameversion.implementation.AlphaClientImpl; +import tsptest.multipleclientssameversion.models.Resource; + +/** + * Initializes a new instance of the asynchronous AlphaClient type. + */ +@ServiceClient(builder = AlphaClientBuilder.class, isAsync = true) +public final class AlphaAsyncClient { + @Generated + private final AlphaClientImpl serviceClient; + + /** + * Initializes an instance of AlphaAsyncClient class. + * + * @param serviceClient the service client implementation. + */ + @Generated + AlphaAsyncClient(AlphaClientImpl serviceClient) { + this.serviceClient = serviceClient; + } + + /** + * The getAlpha operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response} on successful completion of {@link Mono}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> getAlphaWithResponse(String id, RequestOptions requestOptions) { + return this.serviceClient.getAlphaWithResponseAsync(id, requestOptions); + } + + /** + * The getAlpha operation. + * + * @param id The id parameter. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body on successful completion of {@link Mono}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono getAlpha(String id) { + // Generated convenience method for getAlphaWithResponse + RequestOptions requestOptions = new RequestOptions(); + return getAlphaWithResponse(id, requestOptions).flatMap(FluxUtil::toMono) + .map(protocolMethodData -> protocolMethodData.toObject(Resource.class)); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaClient.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaClient.java new file mode 100644 index 00000000000..c8e309abce2 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaClient.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceClient; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.exception.ClientAuthenticationException; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.exception.ResourceModifiedException; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.http.rest.Response; +import com.azure.core.util.BinaryData; +import tsptest.multipleclientssameversion.implementation.AlphaClientImpl; +import tsptest.multipleclientssameversion.models.Resource; + +/** + * Initializes a new instance of the synchronous AlphaClient type. + */ +@ServiceClient(builder = AlphaClientBuilder.class) +public final class AlphaClient { + @Generated + private final AlphaClientImpl serviceClient; + + /** + * Initializes an instance of AlphaClient class. + * + * @param serviceClient the service client implementation. + */ + @Generated + AlphaClient(AlphaClientImpl serviceClient) { + this.serviceClient = serviceClient; + } + + /** + * The getAlpha operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Response getAlphaWithResponse(String id, RequestOptions requestOptions) { + return this.serviceClient.getAlphaWithResponse(id, requestOptions); + } + + /** + * The getAlpha operation. + * + * @param id The id parameter. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Resource getAlpha(String id) { + // Generated convenience method for getAlphaWithResponse + RequestOptions requestOptions = new RequestOptions(); + return getAlphaWithResponse(id, requestOptions).getValue().toObject(Resource.class); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaClientBuilder.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaClientBuilder.java new file mode 100644 index 00000000000..80cf44e77d0 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/AlphaClientBuilder.java @@ -0,0 +1,308 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.ServiceClientBuilder; +import com.azure.core.client.traits.ConfigurationTrait; +import com.azure.core.client.traits.EndpointTrait; +import com.azure.core.client.traits.HttpTrait; +import com.azure.core.http.HttpClient; +import com.azure.core.http.HttpHeaders; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpPipelineBuilder; +import com.azure.core.http.HttpPipelinePosition; +import com.azure.core.http.policy.AddDatePolicy; +import com.azure.core.http.policy.AddHeadersFromContextPolicy; +import com.azure.core.http.policy.AddHeadersPolicy; +import com.azure.core.http.policy.HttpLogOptions; +import com.azure.core.http.policy.HttpLoggingPolicy; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.http.policy.HttpPolicyProviders; +import com.azure.core.http.policy.RequestIdPolicy; +import com.azure.core.http.policy.RetryOptions; +import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.util.ClientOptions; +import com.azure.core.util.Configuration; +import com.azure.core.util.CoreUtils; +import com.azure.core.util.builder.ClientBuilderUtil; +import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.serializer.JacksonAdapter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import tsptest.multipleclientssameversion.implementation.AlphaClientImpl; + +/** + * A builder for creating a new instance of the AlphaClient type. + */ +@ServiceClientBuilder(serviceClients = { AlphaClient.class, AlphaAsyncClient.class }) +public final class AlphaClientBuilder implements HttpTrait, ConfigurationTrait, + EndpointTrait { + @Generated + private static final String SDK_NAME = "name"; + + @Generated + private static final String SDK_VERSION = "version"; + + @Generated + private static final Map PROPERTIES + = CoreUtils.getProperties("tsptest-multipleclientssameversion.properties"); + + @Generated + private final List pipelinePolicies; + + /** + * Create an instance of the AlphaClientBuilder. + */ + @Generated + public AlphaClientBuilder() { + this.pipelinePolicies = new ArrayList<>(); + } + + /* + * The HTTP client used to send the request. + */ + @Generated + private HttpClient httpClient; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /* + * The HTTP pipeline to send requests through. + */ + @Generated + private HttpPipeline pipeline; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder pipeline(HttpPipeline pipeline) { + if (this.pipeline != null && pipeline == null) { + LOGGER.atInfo().log("HttpPipeline is being set to 'null' when it was previously configured."); + } + this.pipeline = pipeline; + return this; + } + + /* + * The logging configuration for HTTP requests and responses. + */ + @Generated + private HttpLogOptions httpLogOptions; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder httpLogOptions(HttpLogOptions httpLogOptions) { + this.httpLogOptions = httpLogOptions; + return this; + } + + /* + * The client options such as application ID and custom headers to set on a request. + */ + @Generated + private ClientOptions clientOptions; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder clientOptions(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + return this; + } + + /* + * The retry options to configure retry policy for failed requests. + */ + @Generated + private RetryOptions retryOptions; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder retryOptions(RetryOptions retryOptions) { + this.retryOptions = retryOptions; + return this; + } + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder addPolicy(HttpPipelinePolicy customPolicy) { + Objects.requireNonNull(customPolicy, "'customPolicy' cannot be null."); + pipelinePolicies.add(customPolicy); + return this; + } + + /* + * The configuration store that is used during construction of the service client. + */ + @Generated + private Configuration configuration; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } + + /* + * The service endpoint + */ + @Generated + private String endpoint; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public AlphaClientBuilder endpoint(String endpoint) { + this.endpoint = endpoint; + return this; + } + + /* + * Service version + */ + @Generated + private MultipleClientsSameVersionServiceVersion serviceVersion; + + /** + * Sets Service version. + * + * @param serviceVersion the serviceVersion value. + * @return the AlphaClientBuilder. + */ + @Generated + public AlphaClientBuilder serviceVersion(MultipleClientsSameVersionServiceVersion serviceVersion) { + this.serviceVersion = serviceVersion; + return this; + } + + /* + * The retry policy that will attempt to retry failed requests, if applicable. + */ + @Generated + private RetryPolicy retryPolicy; + + /** + * Sets The retry policy that will attempt to retry failed requests, if applicable. + * + * @param retryPolicy the retryPolicy value. + * @return the AlphaClientBuilder. + */ + @Generated + public AlphaClientBuilder retryPolicy(RetryPolicy retryPolicy) { + this.retryPolicy = retryPolicy; + return this; + } + + /** + * Builds an instance of AlphaClientImpl with the provided parameters. + * + * @return an instance of AlphaClientImpl. + */ + @Generated + private AlphaClientImpl buildInnerClient() { + this.validateClient(); + HttpPipeline localPipeline = (pipeline != null) ? pipeline : createHttpPipeline(); + MultipleClientsSameVersionServiceVersion localServiceVersion + = (serviceVersion != null) ? serviceVersion : MultipleClientsSameVersionServiceVersion.getLatest(); + AlphaClientImpl client = new AlphaClientImpl(localPipeline, JacksonAdapter.createDefaultSerializerAdapter(), + this.endpoint, localServiceVersion); + return client; + } + + @Generated + private void validateClient() { + // This method is invoked from 'buildInnerClient'/'buildClient' method. + // Developer can customize this method, to validate that the necessary conditions are met for the new client. + Objects.requireNonNull(endpoint, "'endpoint' cannot be null."); + } + + @Generated + private HttpPipeline createHttpPipeline() { + Configuration buildConfiguration + = (configuration == null) ? Configuration.getGlobalConfiguration() : configuration; + HttpLogOptions localHttpLogOptions = this.httpLogOptions == null ? new HttpLogOptions() : this.httpLogOptions; + ClientOptions localClientOptions = this.clientOptions == null ? new ClientOptions() : this.clientOptions; + List policies = new ArrayList<>(); + String clientName = PROPERTIES.getOrDefault(SDK_NAME, "UnknownName"); + String clientVersion = PROPERTIES.getOrDefault(SDK_VERSION, "UnknownVersion"); + String applicationId = CoreUtils.getApplicationId(localClientOptions, localHttpLogOptions); + policies.add(new UserAgentPolicy(applicationId, clientName, clientVersion, buildConfiguration)); + policies.add(new RequestIdPolicy()); + policies.add(new AddHeadersFromContextPolicy()); + HttpHeaders headers = CoreUtils.createHttpHeadersFromClientOptions(localClientOptions); + if (headers != null) { + policies.add(new AddHeadersPolicy(headers)); + } + this.pipelinePolicies.stream() + .filter(p -> p.getPipelinePosition() == HttpPipelinePosition.PER_CALL) + .forEach(p -> policies.add(p)); + HttpPolicyProviders.addBeforeRetryPolicies(policies); + policies.add(ClientBuilderUtil.validateAndGetRetryPolicy(retryPolicy, retryOptions, new RetryPolicy())); + policies.add(new AddDatePolicy()); + this.pipelinePolicies.stream() + .filter(p -> p.getPipelinePosition() == HttpPipelinePosition.PER_RETRY) + .forEach(p -> policies.add(p)); + HttpPolicyProviders.addAfterRetryPolicies(policies); + policies.add(new HttpLoggingPolicy(localHttpLogOptions)); + HttpPipeline httpPipeline = new HttpPipelineBuilder().policies(policies.toArray(new HttpPipelinePolicy[0])) + .httpClient(httpClient) + .clientOptions(localClientOptions) + .build(); + return httpPipeline; + } + + /** + * Builds an instance of AlphaAsyncClient class. + * + * @return an instance of AlphaAsyncClient. + */ + @Generated + public AlphaAsyncClient buildAsyncClient() { + return new AlphaAsyncClient(buildInnerClient()); + } + + /** + * Builds an instance of AlphaClient class. + * + * @return an instance of AlphaClient. + */ + @Generated + public AlphaClient buildClient() { + return new AlphaClient(buildInnerClient()); + } + + private static final ClientLogger LOGGER = new ClientLogger(AlphaClientBuilder.class); +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaAsyncClient.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaAsyncClient.java new file mode 100644 index 00000000000..690fc2052de --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaAsyncClient.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceClient; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.exception.ClientAuthenticationException; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.exception.ResourceModifiedException; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.http.rest.Response; +import com.azure.core.util.BinaryData; +import com.azure.core.util.FluxUtil; +import reactor.core.publisher.Mono; +import tsptest.multipleclientssameversion.implementation.BetaClientImpl; +import tsptest.multipleclientssameversion.models.Resource; + +/** + * Initializes a new instance of the asynchronous BetaClient type. + */ +@ServiceClient(builder = BetaClientBuilder.class, isAsync = true) +public final class BetaAsyncClient { + @Generated + private final BetaClientImpl serviceClient; + + /** + * Initializes an instance of BetaAsyncClient class. + * + * @param serviceClient the service client implementation. + */ + @Generated + BetaAsyncClient(BetaClientImpl serviceClient) { + this.serviceClient = serviceClient; + } + + /** + * The getBeta operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response} on successful completion of {@link Mono}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> getBetaWithResponse(String id, RequestOptions requestOptions) { + return this.serviceClient.getBetaWithResponseAsync(id, requestOptions); + } + + /** + * The getBeta operation. + * + * @param id The id parameter. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response body on successful completion of {@link Mono}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono getBeta(String id) { + // Generated convenience method for getBetaWithResponse + RequestOptions requestOptions = new RequestOptions(); + return getBetaWithResponse(id, requestOptions).flatMap(FluxUtil::toMono) + .map(protocolMethodData -> protocolMethodData.toObject(Resource.class)); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaClient.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaClient.java new file mode 100644 index 00000000000..7e039a02d2c --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaClient.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceClient; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.exception.ClientAuthenticationException; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.exception.ResourceModifiedException; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.http.rest.Response; +import com.azure.core.util.BinaryData; +import tsptest.multipleclientssameversion.implementation.BetaClientImpl; +import tsptest.multipleclientssameversion.models.Resource; + +/** + * Initializes a new instance of the synchronous BetaClient type. + */ +@ServiceClient(builder = BetaClientBuilder.class) +public final class BetaClient { + @Generated + private final BetaClientImpl serviceClient; + + /** + * Initializes an instance of BetaClient class. + * + * @param serviceClient the service client implementation. + */ + @Generated + BetaClient(BetaClientImpl serviceClient) { + this.serviceClient = serviceClient; + } + + /** + * The getBeta operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response}. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Response getBetaWithResponse(String id, RequestOptions requestOptions) { + return this.serviceClient.getBetaWithResponse(id, requestOptions); + } + + /** + * The getBeta operation. + * + * @param id The id parameter. + * @throws IllegalArgumentException thrown if parameters fail the validation. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @throws RuntimeException all other wrapped checked exceptions if the request fails to be sent. + * @return the response. + */ + @Generated + @ServiceMethod(returns = ReturnType.SINGLE) + public Resource getBeta(String id) { + // Generated convenience method for getBetaWithResponse + RequestOptions requestOptions = new RequestOptions(); + return getBetaWithResponse(id, requestOptions).getValue().toObject(Resource.class); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaClientBuilder.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaClientBuilder.java new file mode 100644 index 00000000000..cc7a314c7c2 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/BetaClientBuilder.java @@ -0,0 +1,308 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.ServiceClientBuilder; +import com.azure.core.client.traits.ConfigurationTrait; +import com.azure.core.client.traits.EndpointTrait; +import com.azure.core.client.traits.HttpTrait; +import com.azure.core.http.HttpClient; +import com.azure.core.http.HttpHeaders; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpPipelineBuilder; +import com.azure.core.http.HttpPipelinePosition; +import com.azure.core.http.policy.AddDatePolicy; +import com.azure.core.http.policy.AddHeadersFromContextPolicy; +import com.azure.core.http.policy.AddHeadersPolicy; +import com.azure.core.http.policy.HttpLogOptions; +import com.azure.core.http.policy.HttpLoggingPolicy; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.http.policy.HttpPolicyProviders; +import com.azure.core.http.policy.RequestIdPolicy; +import com.azure.core.http.policy.RetryOptions; +import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.util.ClientOptions; +import com.azure.core.util.Configuration; +import com.azure.core.util.CoreUtils; +import com.azure.core.util.builder.ClientBuilderUtil; +import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.serializer.JacksonAdapter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import tsptest.multipleclientssameversion.implementation.BetaClientImpl; + +/** + * A builder for creating a new instance of the BetaClient type. + */ +@ServiceClientBuilder(serviceClients = { BetaClient.class, BetaAsyncClient.class }) +public final class BetaClientBuilder + implements HttpTrait, ConfigurationTrait, EndpointTrait { + @Generated + private static final String SDK_NAME = "name"; + + @Generated + private static final String SDK_VERSION = "version"; + + @Generated + private static final Map PROPERTIES + = CoreUtils.getProperties("tsptest-multipleclientssameversion.properties"); + + @Generated + private final List pipelinePolicies; + + /** + * Create an instance of the BetaClientBuilder. + */ + @Generated + public BetaClientBuilder() { + this.pipelinePolicies = new ArrayList<>(); + } + + /* + * The HTTP client used to send the request. + */ + @Generated + private HttpClient httpClient; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder httpClient(HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /* + * The HTTP pipeline to send requests through. + */ + @Generated + private HttpPipeline pipeline; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder pipeline(HttpPipeline pipeline) { + if (this.pipeline != null && pipeline == null) { + LOGGER.atInfo().log("HttpPipeline is being set to 'null' when it was previously configured."); + } + this.pipeline = pipeline; + return this; + } + + /* + * The logging configuration for HTTP requests and responses. + */ + @Generated + private HttpLogOptions httpLogOptions; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder httpLogOptions(HttpLogOptions httpLogOptions) { + this.httpLogOptions = httpLogOptions; + return this; + } + + /* + * The client options such as application ID and custom headers to set on a request. + */ + @Generated + private ClientOptions clientOptions; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder clientOptions(ClientOptions clientOptions) { + this.clientOptions = clientOptions; + return this; + } + + /* + * The retry options to configure retry policy for failed requests. + */ + @Generated + private RetryOptions retryOptions; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder retryOptions(RetryOptions retryOptions) { + this.retryOptions = retryOptions; + return this; + } + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder addPolicy(HttpPipelinePolicy customPolicy) { + Objects.requireNonNull(customPolicy, "'customPolicy' cannot be null."); + pipelinePolicies.add(customPolicy); + return this; + } + + /* + * The configuration store that is used during construction of the service client. + */ + @Generated + private Configuration configuration; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder configuration(Configuration configuration) { + this.configuration = configuration; + return this; + } + + /* + * The service endpoint + */ + @Generated + private String endpoint; + + /** + * {@inheritDoc}. + */ + @Generated + @Override + public BetaClientBuilder endpoint(String endpoint) { + this.endpoint = endpoint; + return this; + } + + /* + * Service version + */ + @Generated + private MultipleClientsSameVersionServiceVersion serviceVersion; + + /** + * Sets Service version. + * + * @param serviceVersion the serviceVersion value. + * @return the BetaClientBuilder. + */ + @Generated + public BetaClientBuilder serviceVersion(MultipleClientsSameVersionServiceVersion serviceVersion) { + this.serviceVersion = serviceVersion; + return this; + } + + /* + * The retry policy that will attempt to retry failed requests, if applicable. + */ + @Generated + private RetryPolicy retryPolicy; + + /** + * Sets The retry policy that will attempt to retry failed requests, if applicable. + * + * @param retryPolicy the retryPolicy value. + * @return the BetaClientBuilder. + */ + @Generated + public BetaClientBuilder retryPolicy(RetryPolicy retryPolicy) { + this.retryPolicy = retryPolicy; + return this; + } + + /** + * Builds an instance of BetaClientImpl with the provided parameters. + * + * @return an instance of BetaClientImpl. + */ + @Generated + private BetaClientImpl buildInnerClient() { + this.validateClient(); + HttpPipeline localPipeline = (pipeline != null) ? pipeline : createHttpPipeline(); + MultipleClientsSameVersionServiceVersion localServiceVersion + = (serviceVersion != null) ? serviceVersion : MultipleClientsSameVersionServiceVersion.getLatest(); + BetaClientImpl client = new BetaClientImpl(localPipeline, JacksonAdapter.createDefaultSerializerAdapter(), + this.endpoint, localServiceVersion); + return client; + } + + @Generated + private void validateClient() { + // This method is invoked from 'buildInnerClient'/'buildClient' method. + // Developer can customize this method, to validate that the necessary conditions are met for the new client. + Objects.requireNonNull(endpoint, "'endpoint' cannot be null."); + } + + @Generated + private HttpPipeline createHttpPipeline() { + Configuration buildConfiguration + = (configuration == null) ? Configuration.getGlobalConfiguration() : configuration; + HttpLogOptions localHttpLogOptions = this.httpLogOptions == null ? new HttpLogOptions() : this.httpLogOptions; + ClientOptions localClientOptions = this.clientOptions == null ? new ClientOptions() : this.clientOptions; + List policies = new ArrayList<>(); + String clientName = PROPERTIES.getOrDefault(SDK_NAME, "UnknownName"); + String clientVersion = PROPERTIES.getOrDefault(SDK_VERSION, "UnknownVersion"); + String applicationId = CoreUtils.getApplicationId(localClientOptions, localHttpLogOptions); + policies.add(new UserAgentPolicy(applicationId, clientName, clientVersion, buildConfiguration)); + policies.add(new RequestIdPolicy()); + policies.add(new AddHeadersFromContextPolicy()); + HttpHeaders headers = CoreUtils.createHttpHeadersFromClientOptions(localClientOptions); + if (headers != null) { + policies.add(new AddHeadersPolicy(headers)); + } + this.pipelinePolicies.stream() + .filter(p -> p.getPipelinePosition() == HttpPipelinePosition.PER_CALL) + .forEach(p -> policies.add(p)); + HttpPolicyProviders.addBeforeRetryPolicies(policies); + policies.add(ClientBuilderUtil.validateAndGetRetryPolicy(retryPolicy, retryOptions, new RetryPolicy())); + policies.add(new AddDatePolicy()); + this.pipelinePolicies.stream() + .filter(p -> p.getPipelinePosition() == HttpPipelinePosition.PER_RETRY) + .forEach(p -> policies.add(p)); + HttpPolicyProviders.addAfterRetryPolicies(policies); + policies.add(new HttpLoggingPolicy(localHttpLogOptions)); + HttpPipeline httpPipeline = new HttpPipelineBuilder().policies(policies.toArray(new HttpPipelinePolicy[0])) + .httpClient(httpClient) + .clientOptions(localClientOptions) + .build(); + return httpPipeline; + } + + /** + * Builds an instance of BetaAsyncClient class. + * + * @return an instance of BetaAsyncClient. + */ + @Generated + public BetaAsyncClient buildAsyncClient() { + return new BetaAsyncClient(buildInnerClient()); + } + + /** + * Builds an instance of BetaClient class. + * + * @return an instance of BetaClient. + */ + @Generated + public BetaClient buildClient() { + return new BetaClient(buildInnerClient()); + } + + private static final ClientLogger LOGGER = new ClientLogger(BetaClientBuilder.class); +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/MultipleClientsSameVersionServiceVersion.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/MultipleClientsSameVersionServiceVersion.java new file mode 100644 index 00000000000..095134cf068 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/MultipleClientsSameVersionServiceVersion.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion; + +import com.azure.core.util.ServiceVersion; + +/** + * Service version of MultipleClientsSameVersionClient. + */ +public enum MultipleClientsSameVersionServiceVersion implements ServiceVersion { + /** + * Enum value 2023-01-01. + */ + V2023_01_01("2023-01-01"), + + /** + * Enum value 2023-06-01. + */ + V2023_06_01("2023-06-01"); + + private final String version; + + MultipleClientsSameVersionServiceVersion(String version) { + this.version = version; + } + + /** + * {@inheritDoc} + */ + @Override + public String getVersion() { + return this.version; + } + + /** + * Gets the latest service version supported by this client library. + * + * @return The latest {@link MultipleClientsSameVersionServiceVersion}. + */ + public static MultipleClientsSameVersionServiceVersion getLatest() { + return V2023_06_01; + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/AlphaClientImpl.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/AlphaClientImpl.java new file mode 100644 index 00000000000..bde42377dfa --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/AlphaClientImpl.java @@ -0,0 +1,220 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion.implementation; + +import com.azure.core.annotation.ExpectedResponses; +import com.azure.core.annotation.Get; +import com.azure.core.annotation.HeaderParam; +import com.azure.core.annotation.Host; +import com.azure.core.annotation.HostParam; +import com.azure.core.annotation.PathParam; +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceInterface; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.annotation.UnexpectedResponseExceptionType; +import com.azure.core.exception.ClientAuthenticationException; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.exception.ResourceModifiedException; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpPipelineBuilder; +import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.RestProxy; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Context; +import com.azure.core.util.FluxUtil; +import com.azure.core.util.serializer.JacksonAdapter; +import com.azure.core.util.serializer.SerializerAdapter; +import reactor.core.publisher.Mono; +import tsptest.multipleclientssameversion.MultipleClientsSameVersionServiceVersion; + +/** + * Initializes a new instance of the AlphaClient type. + */ +public final class AlphaClientImpl { + /** + * The proxy service used to perform REST calls. + */ + private final AlphaClientService service; + + /** + * Service host. + */ + private final String endpoint; + + /** + * Gets Service host. + * + * @return the endpoint value. + */ + public String getEndpoint() { + return this.endpoint; + } + + /** + * Service version. + */ + private final MultipleClientsSameVersionServiceVersion serviceVersion; + + /** + * Gets Service version. + * + * @return the serviceVersion value. + */ + public MultipleClientsSameVersionServiceVersion getServiceVersion() { + return this.serviceVersion; + } + + /** + * The HTTP pipeline to send requests through. + */ + private final HttpPipeline httpPipeline; + + /** + * Gets The HTTP pipeline to send requests through. + * + * @return the httpPipeline value. + */ + public HttpPipeline getHttpPipeline() { + return this.httpPipeline; + } + + /** + * The serializer to serialize an object into a string. + */ + private final SerializerAdapter serializerAdapter; + + /** + * Gets The serializer to serialize an object into a string. + * + * @return the serializerAdapter value. + */ + public SerializerAdapter getSerializerAdapter() { + return this.serializerAdapter; + } + + /** + * Initializes an instance of AlphaClient client. + * + * @param endpoint Service host. + * @param serviceVersion Service version. + */ + public AlphaClientImpl(String endpoint, MultipleClientsSameVersionServiceVersion serviceVersion) { + this(new HttpPipelineBuilder().policies(new UserAgentPolicy(), new RetryPolicy()).build(), + JacksonAdapter.createDefaultSerializerAdapter(), endpoint, serviceVersion); + } + + /** + * Initializes an instance of AlphaClient client. + * + * @param httpPipeline The HTTP pipeline to send requests through. + * @param endpoint Service host. + * @param serviceVersion Service version. + */ + public AlphaClientImpl(HttpPipeline httpPipeline, String endpoint, + MultipleClientsSameVersionServiceVersion serviceVersion) { + this(httpPipeline, JacksonAdapter.createDefaultSerializerAdapter(), endpoint, serviceVersion); + } + + /** + * Initializes an instance of AlphaClient client. + * + * @param httpPipeline The HTTP pipeline to send requests through. + * @param serializerAdapter The serializer to serialize an object into a string. + * @param endpoint Service host. + * @param serviceVersion Service version. + */ + public AlphaClientImpl(HttpPipeline httpPipeline, SerializerAdapter serializerAdapter, String endpoint, + MultipleClientsSameVersionServiceVersion serviceVersion) { + this.httpPipeline = httpPipeline; + this.serializerAdapter = serializerAdapter; + this.endpoint = endpoint; + this.serviceVersion = serviceVersion; + this.service = RestProxy.create(AlphaClientService.class, this.httpPipeline, this.getSerializerAdapter()); + } + + /** + * The interface defining all the services for AlphaClient to be used by the proxy service to perform REST calls. + */ + @Host("{endpoint}") + @ServiceInterface(name = "AlphaClient") + public interface AlphaClientService { + @Get("/alpha/{id}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Mono> getAlpha(@HostParam("endpoint") String endpoint, @PathParam("id") String id, + @HeaderParam("Accept") String accept, RequestOptions requestOptions, Context context); + + @Get("/alpha/{id}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Response getAlphaSync(@HostParam("endpoint") String endpoint, @PathParam("id") String id, + @HeaderParam("Accept") String accept, RequestOptions requestOptions, Context context); + } + + /** + * The getAlpha operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> getAlphaWithResponseAsync(String id, RequestOptions requestOptions) { + final String accept = "application/json"; + return FluxUtil + .withContext(context -> service.getAlpha(this.getEndpoint(), id, accept, requestOptions, context)); + } + + /** + * The getAlpha operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Response getAlphaWithResponse(String id, RequestOptions requestOptions) { + final String accept = "application/json"; + return service.getAlphaSync(this.getEndpoint(), id, accept, requestOptions, Context.NONE); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/BetaClientImpl.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/BetaClientImpl.java new file mode 100644 index 00000000000..95c3e234d70 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/BetaClientImpl.java @@ -0,0 +1,220 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion.implementation; + +import com.azure.core.annotation.ExpectedResponses; +import com.azure.core.annotation.Get; +import com.azure.core.annotation.HeaderParam; +import com.azure.core.annotation.Host; +import com.azure.core.annotation.HostParam; +import com.azure.core.annotation.PathParam; +import com.azure.core.annotation.ReturnType; +import com.azure.core.annotation.ServiceInterface; +import com.azure.core.annotation.ServiceMethod; +import com.azure.core.annotation.UnexpectedResponseExceptionType; +import com.azure.core.exception.ClientAuthenticationException; +import com.azure.core.exception.HttpResponseException; +import com.azure.core.exception.ResourceModifiedException; +import com.azure.core.exception.ResourceNotFoundException; +import com.azure.core.http.HttpPipeline; +import com.azure.core.http.HttpPipelineBuilder; +import com.azure.core.http.policy.RetryPolicy; +import com.azure.core.http.policy.UserAgentPolicy; +import com.azure.core.http.rest.RequestOptions; +import com.azure.core.http.rest.Response; +import com.azure.core.http.rest.RestProxy; +import com.azure.core.util.BinaryData; +import com.azure.core.util.Context; +import com.azure.core.util.FluxUtil; +import com.azure.core.util.serializer.JacksonAdapter; +import com.azure.core.util.serializer.SerializerAdapter; +import reactor.core.publisher.Mono; +import tsptest.multipleclientssameversion.MultipleClientsSameVersionServiceVersion; + +/** + * Initializes a new instance of the BetaClient type. + */ +public final class BetaClientImpl { + /** + * The proxy service used to perform REST calls. + */ + private final BetaClientService service; + + /** + * Service host. + */ + private final String endpoint; + + /** + * Gets Service host. + * + * @return the endpoint value. + */ + public String getEndpoint() { + return this.endpoint; + } + + /** + * Service version. + */ + private final MultipleClientsSameVersionServiceVersion serviceVersion; + + /** + * Gets Service version. + * + * @return the serviceVersion value. + */ + public MultipleClientsSameVersionServiceVersion getServiceVersion() { + return this.serviceVersion; + } + + /** + * The HTTP pipeline to send requests through. + */ + private final HttpPipeline httpPipeline; + + /** + * Gets The HTTP pipeline to send requests through. + * + * @return the httpPipeline value. + */ + public HttpPipeline getHttpPipeline() { + return this.httpPipeline; + } + + /** + * The serializer to serialize an object into a string. + */ + private final SerializerAdapter serializerAdapter; + + /** + * Gets The serializer to serialize an object into a string. + * + * @return the serializerAdapter value. + */ + public SerializerAdapter getSerializerAdapter() { + return this.serializerAdapter; + } + + /** + * Initializes an instance of BetaClient client. + * + * @param endpoint Service host. + * @param serviceVersion Service version. + */ + public BetaClientImpl(String endpoint, MultipleClientsSameVersionServiceVersion serviceVersion) { + this(new HttpPipelineBuilder().policies(new UserAgentPolicy(), new RetryPolicy()).build(), + JacksonAdapter.createDefaultSerializerAdapter(), endpoint, serviceVersion); + } + + /** + * Initializes an instance of BetaClient client. + * + * @param httpPipeline The HTTP pipeline to send requests through. + * @param endpoint Service host. + * @param serviceVersion Service version. + */ + public BetaClientImpl(HttpPipeline httpPipeline, String endpoint, + MultipleClientsSameVersionServiceVersion serviceVersion) { + this(httpPipeline, JacksonAdapter.createDefaultSerializerAdapter(), endpoint, serviceVersion); + } + + /** + * Initializes an instance of BetaClient client. + * + * @param httpPipeline The HTTP pipeline to send requests through. + * @param serializerAdapter The serializer to serialize an object into a string. + * @param endpoint Service host. + * @param serviceVersion Service version. + */ + public BetaClientImpl(HttpPipeline httpPipeline, SerializerAdapter serializerAdapter, String endpoint, + MultipleClientsSameVersionServiceVersion serviceVersion) { + this.httpPipeline = httpPipeline; + this.serializerAdapter = serializerAdapter; + this.endpoint = endpoint; + this.serviceVersion = serviceVersion; + this.service = RestProxy.create(BetaClientService.class, this.httpPipeline, this.getSerializerAdapter()); + } + + /** + * The interface defining all the services for BetaClient to be used by the proxy service to perform REST calls. + */ + @Host("{endpoint}") + @ServiceInterface(name = "BetaClient") + public interface BetaClientService { + @Get("/beta/{id}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Mono> getBeta(@HostParam("endpoint") String endpoint, @PathParam("id") String id, + @HeaderParam("Accept") String accept, RequestOptions requestOptions, Context context); + + @Get("/beta/{id}") + @ExpectedResponses({ 200 }) + @UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 }) + @UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 }) + @UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 }) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Response getBetaSync(@HostParam("endpoint") String endpoint, @PathParam("id") String id, + @HeaderParam("Accept") String accept, RequestOptions requestOptions, Context context); + } + + /** + * The getBeta operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response} on successful completion of {@link Mono}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> getBetaWithResponseAsync(String id, RequestOptions requestOptions) { + final String accept = "application/json"; + return FluxUtil + .withContext(context -> service.getBeta(this.getEndpoint(), id, accept, requestOptions, context)); + } + + /** + * The getBeta operation. + *

Response Body Schema

+ * + *
+     * {@code
+     * {
+     *     id: String (Required)
+     *     name: String (Required)
+     * }
+     * }
+     * 
+ * + * @param id The id parameter. + * @param requestOptions The options to configure the HTTP request before HTTP client sends it. + * @throws HttpResponseException thrown if the request is rejected by server. + * @throws ClientAuthenticationException thrown if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException thrown if the request is rejected by server on status code 404. + * @throws ResourceModifiedException thrown if the request is rejected by server on status code 409. + * @return the response body along with {@link Response}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Response getBetaWithResponse(String id, RequestOptions requestOptions) { + final String accept = "application/json"; + return service.getBetaSync(this.getEndpoint(), id, accept, requestOptions, Context.NONE); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/package-info.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/package-info.java new file mode 100644 index 00000000000..a961a6627af --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/implementation/package-info.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +/** + * + * Package containing the implementations for MultipleClientsSameVersion. + * + */ +package tsptest.multipleclientssameversion.implementation; diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/models/Resource.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/models/Resource.java new file mode 100644 index 00000000000..f3ba1ffde74 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/models/Resource.java @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion.models; + +import com.azure.core.annotation.Generated; +import com.azure.core.annotation.Immutable; +import com.azure.json.JsonReader; +import com.azure.json.JsonSerializable; +import com.azure.json.JsonToken; +import com.azure.json.JsonWriter; +import java.io.IOException; + +/** + * The Resource model. + */ +@Immutable +public final class Resource implements JsonSerializable { + /* + * The id property. + */ + @Generated + private String id; + + /* + * The name property. + */ + @Generated + private final String name; + + /** + * Creates an instance of Resource class. + * + * @param name the name value to set. + */ + @Generated + private Resource(String name) { + this.name = name; + } + + /** + * Get the id property: The id property. + * + * @return the id value. + */ + @Generated + public String getId() { + return this.id; + } + + /** + * Get the name property: The name property. + * + * @return the name value. + */ + @Generated + public String getName() { + return this.name; + } + + /** + * {@inheritDoc} + */ + @Generated + @Override + public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { + jsonWriter.writeStartObject(); + jsonWriter.writeStringField("name", this.name); + return jsonWriter.writeEndObject(); + } + + /** + * Reads an instance of Resource from the JsonReader. + * + * @param jsonReader The JsonReader being read. + * @return An instance of Resource if the JsonReader was pointing to an instance of it, or null if it was pointing + * to JSON null. + * @throws IllegalStateException If the deserialized JSON object was missing any required properties. + * @throws IOException If an error occurs while reading the Resource. + */ + @Generated + public static Resource fromJson(JsonReader jsonReader) throws IOException { + return jsonReader.readObject(reader -> { + String id = null; + String name = null; + while (reader.nextToken() != JsonToken.END_OBJECT) { + String fieldName = reader.getFieldName(); + reader.nextToken(); + + if ("id".equals(fieldName)) { + id = reader.getString(); + } else if ("name".equals(fieldName)) { + name = reader.getString(); + } else { + reader.skipChildren(); + } + } + Resource deserializedResource = new Resource(name); + deserializedResource.id = id; + + return deserializedResource; + }); + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/models/package-info.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/models/package-info.java new file mode 100644 index 00000000000..17a1b65ad63 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/models/package-info.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +/** + * + * Package containing the data models for MultipleClientsSameVersion. + * + */ +package tsptest.multipleclientssameversion.models; diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/package-info.java b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/package-info.java new file mode 100644 index 00000000000..b6fb73c3e32 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/java/tsptest/multipleclientssameversion/package-info.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +/** + * + * Package containing the classes for MultipleClientsSameVersion. + * + */ +package tsptest.multipleclientssameversion; diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/resources/META-INF/tsptest-multipleclientssameversion_metadata.json b/packages/http-client-java/generator/http-client-generator-test/src/main/resources/META-INF/tsptest-multipleclientssameversion_metadata.json new file mode 100644 index 00000000000..5617f0fdbaa --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/resources/META-INF/tsptest-multipleclientssameversion_metadata.json @@ -0,0 +1 @@ +{"flavor":"Azure","apiVersions":{"TspTest.MultipleClientsSameVersion":"2023-06-01"},"crossLanguagePackageId":"TspTest.MultipleClientsSameVersion","crossLanguageVersion":"310aa2ab63d8","crossLanguageDefinitions":{"tsptest.multipleclientssameversion.AlphaAsyncClient":"TspTest.MultipleClientsSameVersion.AlphaClient","tsptest.multipleclientssameversion.AlphaAsyncClient.getAlpha":"TspTest.MultipleClientsSameVersion.AlphaClient.getAlpha","tsptest.multipleclientssameversion.AlphaAsyncClient.getAlphaWithResponse":"TspTest.MultipleClientsSameVersion.AlphaClient.getAlpha","tsptest.multipleclientssameversion.AlphaClient":"TspTest.MultipleClientsSameVersion.AlphaClient","tsptest.multipleclientssameversion.AlphaClient.getAlpha":"TspTest.MultipleClientsSameVersion.AlphaClient.getAlpha","tsptest.multipleclientssameversion.AlphaClient.getAlphaWithResponse":"TspTest.MultipleClientsSameVersion.AlphaClient.getAlpha","tsptest.multipleclientssameversion.AlphaClientBuilder":"TspTest.MultipleClientsSameVersion.AlphaClient","tsptest.multipleclientssameversion.BetaAsyncClient":"TspTest.MultipleClientsSameVersion.BetaClient","tsptest.multipleclientssameversion.BetaAsyncClient.getBeta":"TspTest.MultipleClientsSameVersion.BetaClient.getBeta","tsptest.multipleclientssameversion.BetaAsyncClient.getBetaWithResponse":"TspTest.MultipleClientsSameVersion.BetaClient.getBeta","tsptest.multipleclientssameversion.BetaClient":"TspTest.MultipleClientsSameVersion.BetaClient","tsptest.multipleclientssameversion.BetaClient.getBeta":"TspTest.MultipleClientsSameVersion.BetaClient.getBeta","tsptest.multipleclientssameversion.BetaClient.getBetaWithResponse":"TspTest.MultipleClientsSameVersion.BetaClient.getBeta","tsptest.multipleclientssameversion.BetaClientBuilder":"TspTest.MultipleClientsSameVersion.BetaClient","tsptest.multipleclientssameversion.models.Resource":"TspTest.MultipleClientsSameVersion.Resource"},"generatedFiles":["src/main/java/module-info.java","src/main/java/tsptest/multipleclientssameversion/AlphaAsyncClient.java","src/main/java/tsptest/multipleclientssameversion/AlphaClient.java","src/main/java/tsptest/multipleclientssameversion/AlphaClientBuilder.java","src/main/java/tsptest/multipleclientssameversion/BetaAsyncClient.java","src/main/java/tsptest/multipleclientssameversion/BetaClient.java","src/main/java/tsptest/multipleclientssameversion/BetaClientBuilder.java","src/main/java/tsptest/multipleclientssameversion/MultipleClientsSameVersionServiceVersion.java","src/main/java/tsptest/multipleclientssameversion/MultipleClientsSameVersionServiceVersion.java","src/main/java/tsptest/multipleclientssameversion/implementation/AlphaClientImpl.java","src/main/java/tsptest/multipleclientssameversion/implementation/BetaClientImpl.java","src/main/java/tsptest/multipleclientssameversion/implementation/package-info.java","src/main/java/tsptest/multipleclientssameversion/models/Resource.java","src/main/java/tsptest/multipleclientssameversion/models/package-info.java","src/main/java/tsptest/multipleclientssameversion/package-info.java"]} \ No newline at end of file diff --git a/packages/http-client-java/generator/http-client-generator-test/src/main/resources/tsptest-multipleclientssameversion.properties b/packages/http-client-java/generator/http-client-generator-test/src/main/resources/tsptest-multipleclientssameversion.properties new file mode 100644 index 00000000000..ca812989b4f --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/main/resources/tsptest-multipleclientssameversion.properties @@ -0,0 +1,2 @@ +name=${project.artifactId} +version=${project.version} diff --git a/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/multipleclientssameversion/generated/AlphaClientTestBase.java b/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/multipleclientssameversion/generated/AlphaClientTestBase.java new file mode 100644 index 00000000000..8db368bb7f4 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/src/test/java/tsptest/multipleclientssameversion/generated/AlphaClientTestBase.java @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Code generated by Microsoft (R) TypeSpec Code Generator. + +package tsptest.multipleclientssameversion.generated; + +// The Java test files under 'generated' package are generated for your reference. +// If you wish to modify these files, please copy them out of the 'generated' package, and modify there. +// See https://aka.ms/azsdk/dpg/java/tests for guide on adding a test. + +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import com.azure.core.test.TestMode; +import com.azure.core.test.TestProxyTestBase; +import com.azure.core.util.Configuration; +import tsptest.multipleclientssameversion.AlphaClient; +import tsptest.multipleclientssameversion.AlphaClientBuilder; +import tsptest.multipleclientssameversion.BetaClient; +import tsptest.multipleclientssameversion.BetaClientBuilder; + +class AlphaClientTestBase extends TestProxyTestBase { + protected AlphaClient alphaClient; + + protected BetaClient betaClient; + + @Override + protected void beforeTest() { + AlphaClientBuilder alphaClientbuilder + = new AlphaClientBuilder().endpoint(Configuration.getGlobalConfiguration().get("ENDPOINT", "endpoint")) + .httpClient(getHttpClientOrUsePlayback(getHttpClients().findFirst().orElse(null))) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BASIC)); + if (getTestMode() == TestMode.RECORD) { + alphaClientbuilder.addPolicy(interceptorManager.getRecordPolicy()); + } + alphaClient = alphaClientbuilder.buildClient(); + + BetaClientBuilder betaClientbuilder + = new BetaClientBuilder().endpoint(Configuration.getGlobalConfiguration().get("ENDPOINT", "endpoint")) + .httpClient(getHttpClientOrUsePlayback(getHttpClients().findFirst().orElse(null))) + .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BASIC)); + if (getTestMode() == TestMode.RECORD) { + betaClientbuilder.addPolicy(interceptorManager.getRecordPolicy()); + } + betaClient = betaClientbuilder.buildClient(); + + } +} diff --git a/packages/http-client-java/generator/http-client-generator-test/tsp/multiple-clients-same-version.tsp b/packages/http-client-java/generator/http-client-generator-test/tsp/multiple-clients-same-version.tsp new file mode 100644 index 00000000000..eafb6480733 --- /dev/null +++ b/packages/http-client-java/generator/http-client-generator-test/tsp/multiple-clients-same-version.tsp @@ -0,0 +1,53 @@ +import "@typespec/rest"; +import "@typespec/http"; +import "@typespec/versioning"; +import "@azure-tools/typespec-client-generator-core"; + +using TypeSpec.Http; +using TypeSpec.Versioning; +using Azure.ClientGenerator.Core; + +// A single versioned service that is split into two clients (AlphaClient, BetaClient). Both +// clients therefore share the same set of api-versions. In this case the emitter must generate a +// SINGLE shared `MultipleClientsSameVersionServiceVersion` enum (named after the service), NOT a +// separate `ServiceVersion` per client. +// +// Regression test for the api-version comparison in code-model-builder.ts (getServiceVersion +// postprocess): comparing ApiVersion object references (with `===`) instead of the version +// strings incorrectly produced one ServiceVersion enum per client here, because each client +// builds its own ApiVersion instances. +@service(#{ title: "MultipleClientsSameVersion" }) +@versioned(ServiceApiVersions) +namespace TspTest.MultipleClientsSameVersion; + +enum ServiceApiVersions { + v2023_01_01: "2023-01-01", + v2023_06_01: "2023-06-01", +} + +model Resource { + @visibility(Lifecycle.Read) + id: string; + + name: string; +} + +@client({ + service: TspTest.MultipleClientsSameVersion, + name: "AlphaClient", +}) +@route("/alpha") +interface AlphaClient { + @get + getAlpha(@path id: string): Resource; +} + +@client({ + service: TspTest.MultipleClientsSameVersion, + name: "BetaClient", +}) +@route("/beta") +interface BetaClient { + @get + getBeta(@path id: string): Resource; +}