Skip to content

Commit

Permalink
feat(java): Implement global timeout configuration for generated clie…
Browse files Browse the repository at this point in the history
…nts. (#5472)

* Implement global timeout configuration for generated clients.

* chore: update changelog

* Add docstring; minor fixes.

* Update snapshots.

* US

* Minor fixes.

* chore: update changelog

* US

---------

Co-authored-by: eyw520 <[email protected]>
Co-authored-by: fern-support <[email protected]>
  • Loading branch information
3 people authored Dec 23, 2024
1 parent 0883bb0 commit 2359122
Show file tree
Hide file tree
Showing 164 changed files with 2,027 additions and 290 deletions.
10 changes: 10 additions & 0 deletions fern/pages/changelogs/java-sdk/2024-12-23.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## 2.8.1
**`(feat):`** Implement global timeout configuration for generated clients.
```java
var client = Client.builder()
.apiKey("...")
.timeout(40)
.build();
```


Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public final class ClientOptionsGenerator extends AbstractFileGenerator {
OkHttpClient.class, "httpClient", Modifier.PRIVATE, Modifier.FINAL)
.build();

private static final FieldSpec TIMEOUT_FIELD = FieldSpec.builder(
TypeName.INT, "timeout", Modifier.PRIVATE, Modifier.FINAL)
.build();

private final ClassName builderClassName;
private final FieldSpec environmentField;
private final GeneratedJavaFile requestOptionsFile;
Expand Down Expand Up @@ -101,6 +105,7 @@ public GeneratedClientOptions generateFile() {
MethodSpec httpClientGetter = createGetter(OKHTTP_CLIENT_FIELD);
Map<VariableId, FieldSpec> variableFields = getVariableFields();
Map<VariableId, MethodSpec> variableGetters = getVariableGetters(variableFields);

String platformHeadersPutString = getPlatformHeadersEntries(
generatorContext.getIr().getSdkConfig().getPlatformHeaders(),
generatorContext.getGeneratorConfig())
Expand All @@ -109,7 +114,8 @@ public GeneratedClientOptions generateFile() {
.map(val -> CodeBlock.of("put($S, $S);", val.getKey(), val.getValue())
.toString())
.collect(Collectors.joining(""));
MethodSpec.Builder contructorBuilder = MethodSpec.constructorBuilder()

MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PRIVATE)
.addParameter(ParameterSpec.builder(environmentField.type, environmentField.name)
.build())
Expand All @@ -119,6 +125,8 @@ public GeneratedClientOptions generateFile() {
.build())
.addParameter(ParameterSpec.builder(OKHTTP_CLIENT_FIELD.type, OKHTTP_CLIENT_FIELD.name)
.build())
.addParameter(ParameterSpec.builder(TIMEOUT_FIELD.type, TIMEOUT_FIELD.name)
.build())
.addParameters(variableFields.values().stream()
.map(fieldSpec -> ParameterSpec.builder(fieldSpec.type, fieldSpec.name)
.build())
Expand All @@ -134,23 +142,28 @@ public GeneratedClientOptions generateFile() {
String.class,
platformHeadersPutString)
.addStatement("this.$L = $L", HEADER_SUPPLIERS_FIELD.name, HEADER_SUPPLIERS_FIELD.name)
.addStatement("this.$L = $L", OKHTTP_CLIENT_FIELD.name, OKHTTP_CLIENT_FIELD.name);
.addStatement("this.$L = $L", OKHTTP_CLIENT_FIELD.name, OKHTTP_CLIENT_FIELD.name)
.addStatement("this.$L = $L", TIMEOUT_FIELD.name, TIMEOUT_FIELD.name);

variableFields
.values()
.forEach(fieldSpec -> contructorBuilder.addStatement("this.$N = $N", fieldSpec, fieldSpec));
.forEach(fieldSpec -> constructorBuilder.addStatement("this.$N = $N", fieldSpec, fieldSpec));

TypeSpec.Builder clientOptionsBuilder = TypeSpec.classBuilder(className)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addField(environmentField)
.addField(HEADERS_FIELD)
.addField(HEADER_SUPPLIERS_FIELD)
.addField(OKHTTP_CLIENT_FIELD)
.addField(TIMEOUT_FIELD)
.addFields(variableFields.values())
.addMethod(contructorBuilder.build())
.addMethod(constructorBuilder.build())
.addMethod(environmentGetter)
.addMethod(headersFromRequestOptions);

if (headersFromIdempotentRequestOptions.isPresent()) {
clientOptionsBuilder.addMethod(headersFromIdempotentRequestOptions.get());

MethodSpec httpClientWithTimeoutGetter = MethodSpec.methodBuilder("httpClientWithTimeout")
.addModifiers(Modifier.PUBLIC)
.addParameter(
Expand Down Expand Up @@ -208,6 +221,7 @@ public GeneratedClientOptions generateFile() {
.build())
.addType(createBuilder(variableFields))
.build();

JavaFile environmentsFile =
JavaFile.builder(className.packageName(), clientOptions).build();

Expand Down Expand Up @@ -267,10 +281,21 @@ private TypeSpec createBuilder(Map<VariableId, FieldSpec> variableFields) {
.addField(HEADER_SUPPLIERS_FIELD.toBuilder()
.initializer("new $T<>()", HashMap.class)
.build())
.addField(FieldSpec.builder(TypeName.INT, TIMEOUT_FIELD.name, Modifier.PRIVATE)
.initializer("60")
.build())
.addFields(variableFields.values())
.addMethod(getEnvironmentBuilder())
.addMethod(getHeaderBuilder())
.addMethod(getHeaderSupplierBuilder())
.addMethod(MethodSpec.methodBuilder("timeout")
.addModifiers(Modifier.PUBLIC)
.addJavadoc("Override the timeout in seconds. Defaults to 60 seconds.")
.returns(builderClassName)
.addParameter(TypeName.INT, TIMEOUT_FIELD.name)
.addStatement("this.$L = $L", TIMEOUT_FIELD.name, TIMEOUT_FIELD.name)
.addStatement("return this")
.build())
.addMethods(getVariableBuilders(variableFields))
.addMethod(getBuildMethod(variableFields))
.build();
Expand Down Expand Up @@ -335,7 +360,7 @@ private List<MethodSpec> getVariableBuilders(Map<VariableId, FieldSpec> variable
.convertToTypeName(true, variableDeclaration.getType()),
variableParameterName)
.addStatement("this.$N = $L", variableField, variableParameterName)
.addStatement("return this", variableField)
.addStatement("return this")
.build();
})
.collect(Collectors.toList());
Expand Down Expand Up @@ -369,10 +394,11 @@ private MethodSpec getBuildMethod(Map<VariableId, FieldSpec> variableFields) {
clientGeneratorContext
.getPoetClassNameFactory()
.getRetryInterceptorClassName())
.add("\n .callTimeout(this.timeout, $T.SECONDS)", TimeUnit.class)
.add("\n .build()")
.build())
.addStatement(
"return new $T($L, $L, $L, $L)",
"return new $T($L, $L, $L, $L, this.timeout)",
className,
environmentField.name,
HEADERS_FIELD.name,
Expand All @@ -382,7 +408,7 @@ private MethodSpec getBuildMethod(Map<VariableId, FieldSpec> variableFields) {
} else {
String variableArgs = variableFields.values().stream()
.map(variableField -> "this." + variableField.name)
.collect(Collectors.joining(","));
.collect(Collectors.joining(", "));
return MethodSpec.methodBuilder("build")
.addModifiers(Modifier.PUBLIC)
.returns(className)
Expand All @@ -393,15 +419,17 @@ private MethodSpec getBuildMethod(Map<VariableId, FieldSpec> variableFields) {
clientGeneratorContext
.getPoetClassNameFactory()
.getRetryInterceptorClassName())
.add("\n .callTimeout(this.timeout, $T.SECONDS)", TimeUnit.class)
.add("\n .build()")
.build())
.addStatement(
"return new $T($L, $L, $L, $L," + variableArgs + ")",
"return new $T($L, $L, $L, $L, this.timeout, $L)",
className,
environmentField.name,
HEADERS_FIELD.name,
HEADER_SUPPLIERS_FIELD.name,
"okhttpClient")
"okhttpClient",
variableArgs)
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,15 @@ private TypeSpec getClientBuilder() {
.build());
}

clientBuilder.addMethod(MethodSpec.methodBuilder("timeout")
.addModifiers(Modifier.PUBLIC)
.addJavadoc("Sets the timeout (in seconds) for the client")
.addParameter(int.class, "timeout")
.returns(builderName)
.addStatement("this.$L.timeout(timeout)", CLIENT_OPTIONS_BUILDER_NAME)
.addStatement("return this")
.build());

generatorContext.getIr().getVariables().stream()
.map(variableDeclaration -> {
String variableName =
Expand Down
13 changes: 13 additions & 0 deletions generators/java/sdk/versions.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
- changelogEntry:
- summary: |
Implement global timeout configuration for generated clients.
```java
var client = Client.builder()
.apiKey("...")
.timeout(40)
.build();
```
type: feat
createdAt: '2024-12-23'
irVersion: 53
version: 2.8.1
- changelogEntry:
- summary: |
Generate inline request bodies with their path parameters in the object.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 2359122

Please sign in to comment.