Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: feature
packages:
- "@typespec/http-client-java"
---

Emitter support for constant optional Accept header with `@clientDefaultValue`. When an Accept header is optional with a constant type and has `@Legacy.clientDefaultValue`, the emitter now treats it as a required constant, ensuring the value is always sent and hidden from the public API.
14 changes: 12 additions & 2 deletions packages/http-client-java/emitter/src/code-model-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ export class CodeModelBuilder {
);
const parentAccessorPublic = Boolean(
subClient.clientInitialization.initializedBy & InitializedByFlags.Parent ||
subClient.clientInitialization.initializedBy === InitializedByFlags.Default,
subClient.clientInitialization.initializedBy === InitializedByFlags.Default,
);
codeModelClient.addSubClient(codeModelSubclient, buildMethodPublic, parentAccessorPublic);
}
Expand Down Expand Up @@ -1522,12 +1522,22 @@ export class CodeModelBuilder {
}

const nullable = param.type.kind === "nullable";

// When Accept header is optional with constant type and has clientDefaultValue,
// treat as required constant — always sent, hidden from public API.
const isAcceptConstantWithDefault =
param.kind === "header" &&
param.serializedName.toLowerCase() === "accept" &&
param.optional &&
sdkType.kind === "constant" &&
param.clientDefaultValue !== undefined;

const parameter = new Parameter(parameterName, param.doc ?? "", schema, {
summary: param.summary,
implementation: parameterOnClient
? ImplementationLocation.Client
: ImplementationLocation.Method,
required: !param.optional,
required: isAcceptConstantWithDefault || !param.optional,
nullable: nullable,
protocol: {
http: new HttpParameter(param.kind, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { SchemaUsage } from "./usage.js";

/** a schema that represents a choice of several values (ie, an 'enum') */
export interface ChoiceSchema<ChoiceType extends PrimitiveSchema = StringSchema>
extends ValueSchema, SchemaUsage {
extends ValueSchema,
SchemaUsage {
/** the schema type */
type: SchemaType.Choice;
/** the primitive type for the choices */
Expand All @@ -39,7 +40,8 @@ export class ChoiceSchema<ChoiceType extends PrimitiveSchema = StringSchema>

/** a schema that represents a choice of several values (ie, an 'enum') */
export interface SealedChoiceSchema<ChoiceType extends PrimitiveSchema = StringSchema>
extends ValueSchema, SchemaUsage {
extends ValueSchema,
SchemaUsage {
/** the schema type */
type: SchemaType.SealedChoice;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) TypeSpec Code Generator.

package tsptest.specialheaders;

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.FluxUtil;
import reactor.core.publisher.Mono;
import tsptest.specialheaders.implementation.ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl;

/**
* Initializes a new instance of the asynchronous SpecialHeadersClient type.
*/
@ServiceClient(builder = SpecialHeadersClientBuilder.class, isAsync = true)
public final class ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient {
@Generated
private final ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl serviceClient;

/**
* Initializes an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient class.
*
* @param serviceClient the service client implementation.
*/
@Generated
ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient(
ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl serviceClient) {
this.serviceClient = serviceClient;
}

/**
* Accept header with constant type and default value should be marked as required, before we support
* clientDefaultValue. Issue: https://github.com/microsoft/typespec/issues/10178.
*
* @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 {@link Response} on successful completion of {@link Mono}.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Response<Void>> retrieveWithResponse(RequestOptions requestOptions) {
return this.serviceClient.retrieveWithResponseAsync(requestOptions);
}

/**
* Accept header with constant type and default value should be marked as required, before we support
* clientDefaultValue. Issue: https://github.com/microsoft/typespec/issues/10178.
*
* @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 A {@link Mono} that completes when a successful response is received.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Void> retrieve() {
// Generated convenience method for retrieveWithResponse
RequestOptions requestOptions = new RequestOptions();
return retrieveWithResponse(requestOptions).flatMap(FluxUtil::toMono);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) TypeSpec Code Generator.

package tsptest.specialheaders;

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 tsptest.specialheaders.implementation.ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl;

/**
* Initializes a new instance of the synchronous SpecialHeadersClient type.
*/
@ServiceClient(builder = SpecialHeadersClientBuilder.class)
public final class ConstantAcceptHeaderWithDefaultValueAsRequiredClient {
@Generated
private final ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl serviceClient;

/**
* Initializes an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredClient class.
*
* @param serviceClient the service client implementation.
*/
@Generated
ConstantAcceptHeaderWithDefaultValueAsRequiredClient(
ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl serviceClient) {
this.serviceClient = serviceClient;
}

/**
* Accept header with constant type and default value should be marked as required, before we support
* clientDefaultValue. Issue: https://github.com/microsoft/typespec/issues/10178.
*
* @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 {@link Response}.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public Response<Void> retrieveWithResponse(RequestOptions requestOptions) {
return this.serviceClient.retrieveWithResponse(requestOptions);
}

/**
* Accept header with constant type and default value should be marked as required, before we support
* clientDefaultValue. Issue: https://github.com/microsoft/typespec/issues/10178.
*
* @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.
*/
@Generated
@ServiceMethod(returns = ReturnType.SINGLE)
public void retrieve() {
// Generated convenience method for retrieveWithResponse
RequestOptions requestOptions = new RequestOptions();
retrieveWithResponse(requestOptions).getValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@
EtagHeadersClient.class,
EtagHeadersOptionalBodyClient.class,
SkipSpecialHeadersClient.class,
ConstantAcceptHeaderWithDefaultValueAsRequiredClient.class,
RepeatabilityHeadersAsyncClient.class,
EtagHeadersAsyncClient.class,
EtagHeadersOptionalBodyAsyncClient.class,
SkipSpecialHeadersAsyncClient.class })
SkipSpecialHeadersAsyncClient.class,
ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient.class })
public final class SpecialHeadersClientBuilder implements HttpTrait<SpecialHeadersClientBuilder>,
ConfigurationTrait<SpecialHeadersClientBuilder>, EndpointTrait<SpecialHeadersClientBuilder> {
@Generated
Expand Down Expand Up @@ -332,6 +334,18 @@ public SkipSpecialHeadersAsyncClient buildSkipSpecialHeadersAsyncClient() {
return new SkipSpecialHeadersAsyncClient(buildInnerClient().getSkipSpecialHeaders());
}

/**
* Builds an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient class.
*
* @return an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient.
*/
@Generated
public ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient
buildConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient() {
return new ConstantAcceptHeaderWithDefaultValueAsRequiredAsyncClient(
buildInnerClient().getConstantAcceptHeaderWithDefaultValueAsRequireds());
}

/**
* Builds an instance of RepeatabilityHeadersClient class.
*
Expand Down Expand Up @@ -372,5 +386,17 @@ public SkipSpecialHeadersClient buildSkipSpecialHeadersClient() {
return new SkipSpecialHeadersClient(buildInnerClient().getSkipSpecialHeaders());
}

/**
* Builds an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredClient class.
*
* @return an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredClient.
*/
@Generated
public ConstantAcceptHeaderWithDefaultValueAsRequiredClient
buildConstantAcceptHeaderWithDefaultValueAsRequiredClient() {
return new ConstantAcceptHeaderWithDefaultValueAsRequiredClient(
buildInnerClient().getConstantAcceptHeaderWithDefaultValueAsRequireds());
}

private static final ClientLogger LOGGER = new ClientLogger(SpecialHeadersClientBuilder.class);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) TypeSpec Code Generator.

package tsptest.specialheaders.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.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.rest.RequestOptions;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.RestProxy;
import com.azure.core.util.Context;
import com.azure.core.util.FluxUtil;
import reactor.core.publisher.Mono;
import tsptest.specialheaders.SpecialHeadersServiceVersion;

/**
* An instance of this class provides access to all the operations defined in
* ConstantAcceptHeaderWithDefaultValueAsRequireds.
*/
public final class ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl {
/**
* The proxy service used to perform REST calls.
*/
private final ConstantAcceptHeaderWithDefaultValueAsRequiredsService service;

/**
* The service client containing this operation class.
*/
private final SpecialHeadersClientImpl client;

/**
* Initializes an instance of ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl.
*
* @param client the instance of the service client containing this operation class.
*/
ConstantAcceptHeaderWithDefaultValueAsRequiredsImpl(SpecialHeadersClientImpl client) {
this.service = RestProxy.create(ConstantAcceptHeaderWithDefaultValueAsRequiredsService.class,
client.getHttpPipeline(), client.getSerializerAdapter());
this.client = client;
}

/**
* Gets Service version.
*
* @return the serviceVersion value.
*/
public SpecialHeadersServiceVersion getServiceVersion() {
return client.getServiceVersion();
}

/**
* The interface defining all the services for SpecialHeadersClientConstantAcceptHeaderWithDefaultValueAsRequireds
* to be used by the proxy service to perform REST calls.
*/
@Host("{endpoint}")
@ServiceInterface(name = "SpecialHeadersClientConstantAcceptHeaderWithDefaultValueAsRequireds")
public interface ConstantAcceptHeaderWithDefaultValueAsRequiredsService {
@Get("/constant-optional-accept-header-with-default-value")
@ExpectedResponses({ 200 })
@UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 })
@UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 })
@UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 })
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono<Response<Void>> retrieve(@HostParam("endpoint") String endpoint, @HeaderParam("accept") String accept,
RequestOptions requestOptions, Context context);

@Get("/constant-optional-accept-header-with-default-value")
@ExpectedResponses({ 200 })
@UnexpectedResponseExceptionType(value = ClientAuthenticationException.class, code = { 401 })
@UnexpectedResponseExceptionType(value = ResourceNotFoundException.class, code = { 404 })
@UnexpectedResponseExceptionType(value = ResourceModifiedException.class, code = { 409 })
@UnexpectedResponseExceptionType(HttpResponseException.class)
Response<Void> retrieveSync(@HostParam("endpoint") String endpoint, @HeaderParam("accept") String accept,
RequestOptions requestOptions, Context context);
}

/**
* Accept header with constant type and default value should be marked as required, before we support
* clientDefaultValue. Issue: https://github.com/microsoft/typespec/issues/10178.
*
* @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 {@link Response} on successful completion of {@link Mono}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Mono<Response<Void>> retrieveWithResponseAsync(RequestOptions requestOptions) {
final String accept = "application/json;odata.metadata=minimal";
return FluxUtil
.withContext(context -> service.retrieve(this.client.getEndpoint(), accept, requestOptions, context));
}

/**
* Accept header with constant type and default value should be marked as required, before we support
* clientDefaultValue. Issue: https://github.com/microsoft/typespec/issues/10178.
*
* @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 {@link Response}.
*/
@ServiceMethod(returns = ReturnType.SINGLE)
public Response<Void> retrieveWithResponse(RequestOptions requestOptions) {
final String accept = "application/json;odata.metadata=minimal";
return service.retrieveSync(this.client.getEndpoint(), accept, requestOptions, Context.NONE);
}
}
Loading
Loading