Skip to content

Commit df30aca

Browse files
http-client-java, generate error model for unbranded (microsoft#5209)
fix Azure/autorest.java#2991
1 parent e9003b1 commit df30aca

File tree

10 files changed

+79
-32
lines changed

10 files changed

+79
-32
lines changed

packages/http-client-java/emitter/src/code-model-builder.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,6 +1764,12 @@ export class CodeModelBuilder {
17641764

17651765
if (response instanceof SchemaResponse) {
17661766
this.trackSchemaUsage(response.schema, { usage: [SchemaContext.Exception] });
1767+
1768+
if (trackConvenienceApi && !this.isBranded()) {
1769+
this.trackSchemaUsage(response.schema, {
1770+
usage: [op.internalApi ? SchemaContext.Internal : SchemaContext.Public],
1771+
});
1772+
}
17671773
}
17681774
} else {
17691775
op.addResponse(response);

packages/http-client-java/emitter/src/emitter.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
EmitContext,
44
getNormalizedAbsolutePath,
55
JSONSchemaType,
6-
NoTarget,
76
resolvePath,
87
} from "@typespec/compiler";
98
import { spawn } from "child_process";
@@ -227,15 +226,7 @@ export async function $onEmit(context: EmitContext<EmitterOptions>) {
227226
// program.trace("http-client-java", output.stdout ? output.stdout : output.stderr);
228227
} catch (error: any) {
229228
if (error && "code" in error && error["code"] === "ENOENT") {
230-
const msg = "'java' is not on PATH. Please install JDK 11 or above.";
231-
program.trace("http-client-java", msg);
232-
program.reportDiagnostic({
233-
code: "http-client-java",
234-
severity: "error",
235-
message: msg,
236-
target: NoTarget,
237-
});
238-
logError(program, msg);
229+
logError(program, "'java' is not on PATH. Please install JDK 11 or above.");
239230
} else {
240231
logError(program, error.message);
241232
}

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/ProxyMethodMapper.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Locale;
3737
import java.util.Map;
3838
import java.util.Set;
39+
import java.util.TreeMap;
3940
import java.util.concurrent.ConcurrentHashMap;
4041
import java.util.concurrent.atomic.AtomicReference;
4142
import java.util.function.Function;
@@ -500,7 +501,7 @@ protected void buildUnexpectedResponseExceptionTypes(ProxyMethod.Builder builder
500501
// Initialize the merged map with the Swagger defined configurations so that the settings configurations
501502
// overrides it.
502503
Map<Integer, ClassType> mergedExceptionTypeMapping
503-
= new HashMap<>(swaggerExceptionDefinitions.exceptionTypeMapping);
504+
= new TreeMap<>(swaggerExceptionDefinitions.exceptionTypeMapping);
504505
mergedExceptionTypeMapping.putAll(settingsExceptionTypeMap);
505506

506507
// remove expected status codes
@@ -532,7 +533,7 @@ private SwaggerExceptionDefinitions getSwaggerExceptionDefinitions(Operation ope
532533
ClassType swaggerDefaultExceptionType = null;
533534
Map<Integer, ClassType> swaggerExceptionTypeMap = new HashMap<>();
534535

535-
if (settings.isDataPlaneClient()) {
536+
if (settings.isDataPlaneClient() && settings.isBranded()) {
536537
// LLC does not use model, hence exception from swagger
537538
swaggerDefaultExceptionType = ClassType.HTTP_RESPONSE_EXCEPTION;
538539
exceptionDefinitions.defaultExceptionType = swaggerDefaultExceptionType;
@@ -559,7 +560,7 @@ private SwaggerExceptionDefinitions getSwaggerExceptionDefinitions(Operation ope
559560
ClassType exceptionType = getExceptionType(exception, settings);
560561
statusCodes.stream()
561562
.map(Integer::parseInt)
562-
.forEach(status -> swaggerExceptionTypeMap.put(status, exceptionType));
563+
.forEach(status -> swaggerExceptionTypeMap.putIfAbsent(status, exceptionType));
563564

564565
isDefaultError = false;
565566
} catch (NumberFormatException ex) {
@@ -574,8 +575,10 @@ private SwaggerExceptionDefinitions getSwaggerExceptionDefinitions(Operation ope
574575
}
575576
}
576577

577-
if (swaggerDefaultExceptionType == null && !CoreUtils.isNullOrEmpty(operation.getExceptions())
578578
// m4 could return Response without schema, when the Swagger uses e.g. "produces: [ application/x-rdp ]"
579+
if (swaggerDefaultExceptionType == null
580+
&& settings.isBranded()
581+
&& !CoreUtils.isNullOrEmpty(operation.getExceptions())
579582
&& operation.getExceptions().get(0).getSchema() != null) {
580583
// no default error, use the 1st to keep backward compatibility
581584
swaggerDefaultExceptionType = processExceptionClassType(

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/model/clientmodel/ClassType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.azure.core.http.HttpPipeline;
2323
import com.azure.core.http.HttpPipelineBuilder;
2424
import com.azure.core.http.HttpRequest;
25+
import com.azure.core.http.HttpResponse;
2526
import com.azure.core.http.MatchConditions;
2627
import com.azure.core.http.ProxyOptions;
2728
import com.azure.core.http.RequestConditions;
@@ -126,6 +127,8 @@ public String getGenericClass() {
126127
put(HttpHeaderName.class,
127128
new ClassDetails(HttpHeaderName.class, "io.clientcore.core.http.models.HttpHeaderName"));
128129
put(HttpRequest.class, new ClassDetails(HttpRequest.class, "io.clientcore.core.http.models.HttpRequest"));
130+
put(HttpResponse.class,
131+
new ClassDetails(HttpResponse.class, "io.clientcore.core.http.models.HttpResponse"));
129132
put(RequestOptions.class,
130133
new ClassDetails(RequestOptions.class, "io.clientcore.core.http.models.RequestOptions"));
131134
put(BinaryData.class, new ClassDetails(BinaryData.class, "io.clientcore.core.util.binarydata.BinaryData"));
@@ -516,6 +519,7 @@ private static ClassType.Builder getClassTypeBuilder(Class<?> classKey) {
516519
public static final ClassType HTTP_REQUEST = getClassTypeBuilder(HttpRequest.class).build();
517520
public static final ClassType HTTP_HEADERS = getClassTypeBuilder(HttpHeaders.class).build();
518521
public static final ClassType HTTP_HEADER_NAME = getClassTypeBuilder(HttpHeaderName.class).build();
522+
public static final ClassType HTTP_RESPONSE = getClassTypeBuilder(HttpResponse.class).build();
519523

520524
// Java exception types
521525
public static final ClassType HTTP_RESPONSE_EXCEPTION = getClassTypeBuilder(HttpResponseException.class).build();

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/model/clientmodel/ProxyMethod.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.azure.core.http.HttpMethod;
88
import com.microsoft.typespec.http.client.generator.core.extension.base.util.HttpExceptionType;
99
import com.microsoft.typespec.http.client.generator.core.extension.plugin.JavaSettings;
10+
import com.microsoft.typespec.http.client.generator.core.util.ClientModelUtil;
1011
import com.microsoft.typespec.http.client.generator.core.util.CodeNamer;
1112
import com.microsoft.typespec.http.client.generator.core.util.MethodNamer;
1213
import java.util.List;
@@ -382,15 +383,33 @@ private IType mapToSyncType(IType type) {
382383
public void addImportsTo(Set<String> imports, boolean includeImplementationImports, JavaSettings settings) {
383384
Annotation.HTTP_REQUEST_INFORMATION.addImportsTo(imports);
384385
Annotation.UNEXPECTED_RESPONSE_EXCEPTION_INFORMATION.addImportsTo(imports);
386+
ClassType.HTTP_RESPONSE_EXCEPTION.addImportsTo(imports, false);
385387
if (includeImplementationImports) {
386388
if (getUnexpectedResponseExceptionType() != null) {
387389
Annotation.UNEXPECTED_RESPONSE_EXCEPTION_TYPE.addImportsTo(imports);
388390
getUnexpectedResponseExceptionType().addImportsTo(imports, includeImplementationImports);
391+
392+
if (!settings.isBranded()) {
393+
ClientModel errorModel
394+
= ClientModelUtil.getErrorModelFromException(getUnexpectedResponseExceptionType());
395+
if (errorModel != null) {
396+
errorModel.addImportsTo(imports, settings);
397+
}
398+
}
389399
}
390400
if (getUnexpectedResponseExceptionTypes() != null) {
391401
Annotation.UNEXPECTED_RESPONSE_EXCEPTION_TYPE.addImportsTo(imports);
392402
getUnexpectedResponseExceptionTypes().keySet()
393403
.forEach(e -> e.addImportsTo(imports, includeImplementationImports));
404+
405+
if (!settings.isBranded()) {
406+
for (ClassType exceptionType : getUnexpectedResponseExceptionTypes().keySet()) {
407+
ClientModel errorModel = ClientModelUtil.getErrorModelFromException(exceptionType);
408+
if (errorModel != null) {
409+
errorModel.addImportsTo(imports, settings);
410+
}
411+
}
412+
}
394413
}
395414
if (isResumable()) {
396415
imports.add("com.azure.core.annotation.ResumeOperation");

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/template/ExceptionTemplate.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
package com.microsoft.typespec.http.client.generator.core.template;
55

6+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClassType;
67
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClientException;
78
import com.microsoft.typespec.http.client.generator.core.model.javamodel.JavaFile;
89
import com.microsoft.typespec.http.client.generator.core.model.javamodel.JavaJavadocComment;
@@ -69,6 +70,6 @@ public final void write(ClientException exception, JavaFile javaFile) {
6970
}
7071

7172
protected String getHttpResponseImport() {
72-
return "com.azure.core.http.HttpResponse";
73+
return ClassType.HTTP_RESPONSE.getFullName();
7374
}
7475
}

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/template/ProxyTemplate.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
import com.microsoft.typespec.http.client.generator.core.extension.model.codemodel.RequestParameterLocation;
88
import com.microsoft.typespec.http.client.generator.core.extension.plugin.JavaSettings;
99
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClassType;
10+
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ClientModel;
1011
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.IType;
1112
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.Proxy;
1213
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ProxyMethod;
1314
import com.microsoft.typespec.http.client.generator.core.model.clientmodel.ProxyMethodParameter;
1415
import com.microsoft.typespec.http.client.generator.core.model.javamodel.JavaClass;
1516
import com.microsoft.typespec.http.client.generator.core.model.javamodel.JavaInterface;
1617
import com.microsoft.typespec.http.client.generator.core.model.javamodel.JavaVisibility;
18+
import com.microsoft.typespec.http.client.generator.core.util.ClientModelUtil;
1719
import com.microsoft.typespec.http.client.generator.core.util.CodeNamer;
1820
import java.util.ArrayList;
1921
import java.util.List;
@@ -94,7 +96,7 @@ public final void write(Proxy restAPI, JavaClass classBlock) {
9496
}
9597
}
9698

97-
if (!settings.isDataPlaneClient() || isExceptionCustomized()) {
99+
if (!settings.isDataPlaneClient() || !settings.isBranded() || isExceptionCustomized()) {
98100
// write @UnexpectedResponseExceptionType
99101

100102
if (restAPIMethod.getUnexpectedResponseExceptionTypes() != null) {
@@ -198,11 +200,21 @@ protected void writeUnexpectedExceptions(ProxyMethod restAPIMethod, JavaInterfac
198200
exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(", "))));
199201
}
200202
} else {
201-
for (Map.Entry<ClassType, List<Integer>> exception : restAPIMethod.getUnexpectedResponseExceptionTypes()
202-
.entrySet()) {
203-
interfaceBlock.annotation("UnexpectedResponseExceptionDetail(exceptionTypeName = \""
204-
+ restAPIMethod.getHttpExceptionType(exception.getKey()).toString() + "\", statusCode = {"
205-
+ exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(",")) + " })");
203+
if (JavaSettings.getInstance().isUseDefaultHttpStatusCodeToExceptionTypeMapping()) {
204+
for (Map.Entry<ClassType, List<Integer>> exception : restAPIMethod.getUnexpectedResponseExceptionTypes()
205+
.entrySet()) {
206+
interfaceBlock.annotation("UnexpectedResponseExceptionDetail(exceptionTypeName = \""
207+
+ restAPIMethod.getHttpExceptionType(exception.getKey()).toString() + "\", statusCode = {"
208+
+ exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(",")) + " })");
209+
}
210+
} else {
211+
for (Map.Entry<ClassType, List<Integer>> exception : restAPIMethod.getUnexpectedResponseExceptionTypes()
212+
.entrySet()) {
213+
ClientModel errorModel = ClientModelUtil.getErrorModelFromException(exception.getKey());
214+
interfaceBlock.annotation("UnexpectedResponseExceptionDetail(statusCode = {"
215+
+ exception.getValue().stream().map(String::valueOf).collect(Collectors.joining(","))
216+
+ " }, exceptionBodyClass = " + errorModel.getName() + ".class)");
217+
}
206218
}
207219
}
208220
}
@@ -212,7 +224,18 @@ protected void writeSingleUnexpectedException(ProxyMethod restAPIMethod, JavaInt
212224
interfaceBlock.annotation(String.format("UnexpectedResponseExceptionType(%1$s.class)",
213225
restAPIMethod.getUnexpectedResponseExceptionType()));
214226
} else {
215-
interfaceBlock.annotation("UnexpectedResponseExceptionDetail");
227+
if (JavaSettings.getInstance().isUseDefaultHttpStatusCodeToExceptionTypeMapping()) {
228+
interfaceBlock.annotation("UnexpectedResponseExceptionDetail");
229+
} else {
230+
ClientModel errorModel
231+
= ClientModelUtil.getErrorModelFromException(restAPIMethod.getUnexpectedResponseExceptionType());
232+
if (errorModel != null) {
233+
interfaceBlock.annotation(
234+
"UnexpectedResponseExceptionDetail(exceptionBodyClass = " + errorModel.getName() + ".class)");
235+
} else {
236+
interfaceBlock.annotation("UnexpectedResponseExceptionDetail");
237+
}
238+
}
216239
}
217240
}
218241

packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/util/ClientModelUtil.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,14 @@ public static boolean isMultipartModel(ClientModel model) {
891891
return model.getSerializationFormats().contains(KnownMediaType.MULTIPART.value());
892892
}
893893

894+
public static ClientModel getErrorModelFromException(ClassType exceptionType) {
895+
String errorBodyClassName = exceptionType.getName();
896+
if (errorBodyClassName.endsWith("Exception")) {
897+
errorBodyClassName = errorBodyClassName.substring(0, errorBodyClassName.length() - "Exception".length());
898+
}
899+
return ClientModels.getInstance().getModel(errorBodyClassName);
900+
}
901+
894902
private static boolean hasNoUsage(ClientModel model) {
895903
ImplementationDetails details = model.getImplementationDetails();
896904
return details == null || CoreUtils.isNullOrEmpty(details.getUsages());

packages/http-client-java/generator/http-client-generator/src/main/java/com/microsoft/typespec/http/client/generator/TypeSpecPlugin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ public TypeSpecPlugin(EmitterOptions options, boolean sdkIntegration) {
294294
SETTINGS_MAP.put("license-header", "SMALL_TYPESPEC");
295295

296296
SETTINGS_MAP.put("sync-methods", "sync-only");
297+
SETTINGS_MAP.put("use-default-http-status-code-to-exception-type-mapping", false);
297298
SETTINGS_MAP.put("generate-samples", false);
298299
SETTINGS_MAP.put("generate-tests", false);
299300
}

packages/http-client-java/generator/http-client-generator/src/main/java/com/microsoft/typespec/http/client/generator/util/ModelUtil.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,13 @@ public class ModelUtil {
1717
public static boolean isGeneratingModel(ClientModel model) {
1818
return model.getImplementationDetails() != null
1919
&& (model.getImplementationDetails().isPublic() || model.getImplementationDetails().isInternal())
20-
&& !(isModelUsedOnlyInException(model.getImplementationDetails()))
2120
&& !(isExternalModel(model.getImplementationDetails()))
2221
&& !(isPagedModel(model.getImplementationDetails()));
2322
}
2423

2524
public static boolean isGeneratingModel(EnumType model) {
2625
return model.getImplementationDetails() != null
27-
&& (model.getImplementationDetails().isPublic() || model.getImplementationDetails().isInternal())
28-
&& !(isModelUsedOnlyInException(model.getImplementationDetails()));
26+
&& (model.getImplementationDetails().isPublic() || model.getImplementationDetails().isInternal());
2927
}
3028

3129
public static boolean isGeneratingModel(ClientResponse response) {
@@ -44,16 +42,9 @@ public static boolean isGeneratingModel(ClientResponse response) {
4442
public static boolean isGeneratingModel(UnionModel model) {
4543
return model.getImplementationDetails() != null
4644
&& (model.getImplementationDetails().isPublic() || model.getImplementationDetails().isInternal())
47-
&& !(isModelUsedOnlyInException(model.getImplementationDetails()))
4845
&& !(isExternalModel(model.getImplementationDetails()));
4946
}
5047

51-
private static boolean isModelUsedOnlyInException(ImplementationDetails implementationDetails) {
52-
return (implementationDetails.isException()
53-
&& !implementationDetails.isInput()
54-
&& !implementationDetails.isOutput());
55-
}
56-
5748
private static boolean isPagedModel(ImplementationDetails implementationDetails) {
5849
return (implementationDetails.getUsages() != null
5950
&& implementationDetails.getUsages().contains(ImplementationDetails.Usage.PAGED));

0 commit comments

Comments
 (0)