Skip to content

Commit

Permalink
Fixes for generating openAPI clients:
Browse files Browse the repository at this point in the history
 - Add ability to disable generating `path` attribute in Client annotation
 - Changed basePathSeparator default value to `.` symbol
 - Add suffixes by class-name or clientId to client base path placeholders
  • Loading branch information
altro3 committed Mar 7, 2024
1 parent 575ea8c commit 6d5f0ea
Show file tree
Hide file tree
Showing 20 changed files with 122 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def openapiGenerate = tasks.register("generateOpenApi", OpenApiGeneratorTask) {
lang = "java"
generatedAnnotation = true
clientId = "myClient"
clientPath = true
ksp = false
classpath.from(configurations.openapiGenerator)
openApiDefinition.convention(layout.projectDirectory.file("petstore.json"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def openapiGenerate = tasks.register("generateOpenApi", OpenApiGeneratorTask) {
lang = "kotlin"
generatedAnnotation = true
clientId = "myClient"
clientPath = true
ksp = false
classpath.from(configurations.openapiGenerator)
openApiDefinition.convention(layout.projectDirectory.file("petstore.json"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def openapiGenerate = tasks.register("generateOpenApi", OpenApiGeneratorTask) {
lang = "kotlin"
generatedAnnotation = true
clientId = "myClient"
clientPath = true
ksp = true
classpath.from(configurations.openapiGenerator)
openApiDefinition.convention(layout.projectDirectory.file("petstore.json"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public abstract class OpenApiGeneratorTask extends DefaultTask {
@Input
public abstract Property<Boolean> getKsp();

@Input
public abstract Property<Boolean> getClientPath();

@Input
public abstract Property<String> getClientId();

Expand Down Expand Up @@ -140,6 +143,7 @@ public void execute() throws IOException {
args.add(lang.toUpperCase());
args.add(Boolean.toString(generatedAnnotation));
args.add(Boolean.toString(getKsp().get()));
args.add(Boolean.toString(getClientPath().get()));
args.add(getNameMapping().get().toString());
args.add(getClientId().getOrElse(""));
args.add(getApiNamePrefix().getOrElse(""));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ protected AbstractMicronautKotlinCodegen() {
importMapping.put("ZonedDateTime", "java.time.ZonedDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalTime", "java.time.LocalTime");
importMapping.put("BigDecimal", "java.math.BigDecimal");
}

public void setGenerateHttpResponseAlways(boolean generateHttpResponseAlways) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class JavaMicronautClientCodegen extends AbstractMicronautJavaCodegen<Jav
public static final String OPT_CONFIGURE_AUTH = "configureAuth";
public static final String OPT_CONFIGURE_AUTH_FILTER_PATTERN = "configureAuthFilterPattern";
public static final String OPT_CONFIGURE_CLIENT_ID = "configureClientId";
public static final String OPT_CLIENT_PATH = "clientPath";
public static final String ADDITIONAL_CLIENT_TYPE_ANNOTATIONS = "additionalClientTypeAnnotations";
public static final String AUTHORIZATION_FILTER_PATTERN = "authorizationFilterPattern";
public static final String BASE_PATH_SEPARATOR = "basePathSeparator";
Expand All @@ -43,8 +44,9 @@ public class JavaMicronautClientCodegen extends AbstractMicronautJavaCodegen<Jav
protected boolean configureAuthorization;
protected List<String> additionalClientTypeAnnotations;
protected String authorizationFilterPattern;
protected String basePathSeparator = "-";
protected String basePathSeparator = ".";
protected String clientId;
protected boolean clientPath;

JavaMicronautClientCodegen() {

Expand All @@ -60,6 +62,7 @@ public class JavaMicronautClientCodegen extends AbstractMicronautJavaCodegen<Jav
cliOptions.add(CliOption.newString(AUTHORIZATION_FILTER_PATTERN, "Configure the authorization filter pattern for the client. Generally defined when generating clients from multiple specification files"));
cliOptions.add(CliOption.newString(BASE_PATH_SEPARATOR, "Configure the separator to use between the application name and base path when referencing the property").defaultValue(basePathSeparator));
cliOptions.add(CliOption.newString(CLIENT_ID, "Configure the service ID for the Client"));
cliOptions.add(CliOption.newBoolean(OPT_CLIENT_PATH, "Generate code with @Client annotation path attribute", clientPath));

typeMapping.put("file", "byte[]");
typeMapping.put("responseFile", "InputStream");
Expand Down Expand Up @@ -144,6 +147,11 @@ public void processOpts() {
writePropertyBack(CLIENT_ID, this.clientId);
}

if (additionalProperties.containsKey(OPT_CLIENT_PATH)) {
clientPath = convertPropertyToBoolean(OPT_CLIENT_PATH);
}
writePropertyBack(OPT_CLIENT_PATH, clientPath);

var basePathSeparator = additionalProperties.get(BASE_PATH_SEPARATOR);
if (basePathSeparator != null) {
this.basePathSeparator = basePathSeparator.toString();
Expand Down Expand Up @@ -186,6 +194,10 @@ public void setClientId(final String clientId) {
this.clientId = clientId;
}

public void setClientPath(boolean clientPath) {
this.clientPath = clientPath;
}

public void setBasePathSeparator(final String basePathSeparator) {
this.basePathSeparator = basePathSeparator;
}
Expand All @@ -205,6 +217,7 @@ static class DefaultClientOptionsBuilder implements JavaMicronautClientOptionsBu
private String authorizationFilterPattern;
private String basePathSeparator;
private String clientId;
private boolean clientPath;
private boolean useAuth;
private boolean lombok;
private boolean plural;
Expand Down Expand Up @@ -265,12 +278,19 @@ public JavaMicronautClientOptionsBuilder withGeneratedAnnotation(boolean generat
return this;
}

@Override
public JavaMicronautClientOptionsBuilder withClientPath(boolean clientPath) {
this.clientPath = clientPath;
return this;
}

ClientOptions build() {
return new ClientOptions(
additionalClientTypeAnnotations,
authorizationFilterPattern,
basePathSeparator,
clientId,
clientPath,
useAuth,
lombok,
plural,
Expand All @@ -285,6 +305,7 @@ record ClientOptions(
String authorizationFilterPattern,
String basePathSeparator,
String clientId,
boolean clientPath,
boolean useAuth,
boolean lombok,
boolean plural,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,13 @@ public interface JavaMicronautClientOptionsBuilder extends GeneratorOptionsBuild
* @return this builder
*/
JavaMicronautClientOptionsBuilder withGeneratedAnnotation(boolean generatedAnnotation);

/**
* If set to true, Api annotation {@literal @}Client will be with `path` attribute.
*
* @param clientPath do we need add path attribute to {@literal @}Client annotation
*
* @return this builder
*/
JavaMicronautClientOptionsBuilder withClientPath(boolean clientPath);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class KotlinMicronautClientCodegen extends AbstractMicronautKotlinCodegen
public static final String OPT_CONFIGURE_AUTH = "configureAuth";
public static final String OPT_CONFIGURE_AUTH_FILTER_PATTERN = "configureAuthFilterPattern";
public static final String OPT_CONFIGURE_CLIENT_ID = "configureClientId";
public static final String OPT_CLIENT_PATH = "clientPath";
public static final String ADDITIONAL_CLIENT_TYPE_ANNOTATIONS = "additionalClientTypeAnnotations";
public static final String AUTHORIZATION_FILTER_PATTERN = "authorizationFilterPattern";
public static final String BASE_PATH_SEPARATOR = "basePathSeparator";
Expand All @@ -43,8 +44,9 @@ public class KotlinMicronautClientCodegen extends AbstractMicronautKotlinCodegen
protected boolean configureAuthorization;
protected List<String> additionalClientTypeAnnotations;
protected String authorizationFilterPattern;
protected String basePathSeparator = "-";
protected String basePathSeparator = ".";
protected String clientId;
protected boolean clientPath;

KotlinMicronautClientCodegen() {

Expand All @@ -60,6 +62,7 @@ public class KotlinMicronautClientCodegen extends AbstractMicronautKotlinCodegen
cliOptions.add(CliOption.newString(AUTHORIZATION_FILTER_PATTERN, "Configure the authorization filter pattern for the client. Generally defined when generating clients from multiple specification files"));
cliOptions.add(CliOption.newString(BASE_PATH_SEPARATOR, "Configure the separator to use between the application name and base path when referencing the property").defaultValue(basePathSeparator));
cliOptions.add(CliOption.newString(CLIENT_ID, "Configure the service ID for the Client"));
cliOptions.add(CliOption.newBoolean(OPT_CLIENT_PATH, "Generate code with @Client annotation path attribute", clientPath));

typeMapping.put("file", "ByteArray");
typeMapping.put("responseFile", "InputStream");
Expand Down Expand Up @@ -144,6 +147,11 @@ public void processOpts() {
writePropertyBack(CLIENT_ID, this.clientId);
}

if (additionalProperties.containsKey(OPT_CLIENT_PATH)) {
clientPath = convertPropertyToBoolean(OPT_CLIENT_PATH);
}
writePropertyBack(OPT_CLIENT_PATH, clientPath);

var basePathSeparator = additionalProperties.get(BASE_PATH_SEPARATOR);
if (basePathSeparator != null) {
this.basePathSeparator = basePathSeparator.toString();
Expand Down Expand Up @@ -184,6 +192,10 @@ public void setClientId(final String clientId) {
this.clientId = clientId;
}

public void setClientPath(boolean clientPath) {
this.clientPath = clientPath;
}

public void setBasePathSeparator(final String basePathSeparator) {
this.basePathSeparator = basePathSeparator;
}
Expand All @@ -203,6 +215,7 @@ static class DefaultClientOptionsBuilder implements KotlinMicronautClientOptions
private String authorizationFilterPattern;
private String basePathSeparator;
private String clientId;
private boolean clientPath;
private boolean plural;
private boolean useAuth;
private boolean fluxForArrays;
Expand Down Expand Up @@ -263,12 +276,19 @@ public KotlinMicronautClientOptionsBuilder withKsp(boolean ksp) {
return this;
}

@Override
public KotlinMicronautClientOptionsBuilder withClientPath(boolean clientPath) {
this.clientPath = clientPath;
return this;
}

ClientOptions build() {
return new ClientOptions(
additionalClientTypeAnnotations,
authorizationFilterPattern,
basePathSeparator,
clientId,
clientPath,
useAuth,
plural,
fluxForArrays,
Expand All @@ -283,6 +303,7 @@ record ClientOptions(
String authorizationFilterPattern,
String basePathSeparator,
String clientId,
boolean clientPath,
boolean useAuth,
boolean plural,
boolean fluxForArrays,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,13 @@ public interface KotlinMicronautClientOptionsBuilder extends GeneratorOptionsBui
* @return this builder
*/
KotlinMicronautClientOptionsBuilder withKsp(boolean ksp);

/**
* If set to true, Api annotation {@literal @}Client will be with `path` attribute.
*
* @param clientPath do we need add path attribute to {@literal @}Client annotation
*
* @return this builder
*/
KotlinMicronautClientOptionsBuilder withClientPath(boolean clientPath);
}
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,12 @@ public void configureJavaClientOptions() {
if (javaClientOptions.basePathSeparator() != null) {
javaClientCodegen.setBasePathSeparator(javaClientOptions.basePathSeparator());
}
javaClientCodegen.setClientPath(javaClientOptions.clientPath());
javaClientCodegen.setGeneratedAnnotation(javaClientOptions.generatedAnnotation());
javaClientCodegen.setConfigureAuthorization(javaClientOptions.useAuth());
javaClientCodegen.setLombok(javaClientOptions.lombok());
javaClientCodegen.setPlural(javaClientOptions.plural());
javaClientCodegen.setFluxForArrays(javaClientOptions.fluxForArrays());
javaClientCodegen.setGeneratedAnnotation(javaClientOptions.generatedAnnotation());
javaClientCodegen.setLombok(javaClientOptions.lombok());
}
}

Expand Down Expand Up @@ -327,11 +328,12 @@ public void configureKotlinClientOptions() {
if (kotlinClientOptions.basePathSeparator() != null) {
kotlinClientCodegen.setBasePathSeparator(kotlinClientOptions.basePathSeparator());
}
kotlinClientCodegen.setClientPath(kotlinClientOptions.clientPath());
kotlinClientCodegen.setGeneratedAnnotation(kotlinClientOptions.generatedAnnotation());
kotlinClientCodegen.setKsp(kotlinClientOptions.ksp());
kotlinClientCodegen.setConfigureAuthorization(kotlinClientOptions.useAuth());
kotlinClientCodegen.setPlural(kotlinClientOptions.plural());
kotlinClientCodegen.setFluxForArrays(kotlinClientOptions.fluxForArrays());
kotlinClientCodegen.setKsp(kotlinClientOptions.ksp());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ private Utils() {
}

public static void processGenericAnnotations(CodegenParameter parameter, boolean useBeanValidation, boolean isGenerateHardNullable,
boolean isNullable, boolean isRequired, boolean isReadonly, boolean withNullablePostfix) {
boolean isNullable, boolean isRequired, boolean isReadonly, boolean withNullablePostfix) {
CodegenProperty items = parameter.isMap ? parameter.additionalProperties : parameter.items;
String datatypeWithEnum = parameter.datatypeWithEnum == null ? parameter.dataType : parameter.datatypeWithEnum;
processGenericAnnotations(parameter.dataType, datatypeWithEnum, parameter.isArray, parameter.isMap, parameter.containerTypeMapped,
items, parameter.vendorExtensions, useBeanValidation, isGenerateHardNullable, isNullable, isRequired, isReadonly, withNullablePostfix);
}

public static void processGenericAnnotations(CodegenProperty property, boolean useBeanValidation, boolean isGenerateHardNullable,
boolean isNullable, boolean isRequired, boolean isReadonly, boolean withNullablePostfix) {
boolean isNullable, boolean isRequired, boolean isReadonly, boolean withNullablePostfix) {
CodegenProperty items = property.isMap ? property.additionalProperties : property.items;
String datatypeWithEnum = property.datatypeWithEnum == null ? property.dataType : property.datatypeWithEnum;
processGenericAnnotations(property.dataType, datatypeWithEnum, property.isArray, property.isMap, property.containerTypeMapped,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
{{#generatedAnnotation}}
{{>common/generatedAnnotation}}
{{/generatedAnnotation}}
@Client({{#configureClientId}}id = "{{clientId}}", path = {{/configureClientId}}"${{openbrace}}{{{applicationName}}}{{basePathSeparator}}base-path{{closebrace}}")
@Client({{#configureClientId}}{{#clientPath}}id = {{/clientPath}}{{/configureClientId}}"{{#configureClientId}}{{clientId}}{{/configureClientId}}{{^configureClientId}}${{openbrace}}{{{applicationName}}}{{basePathSeparator}}base-path{{closebrace}}{{/configureClientId}}"{{#configureClientId}}{{#clientPath}}, path = "${{openbrace}}{{#configureClientId}}{{{clientId}}}{{/configureClientId}}{{^configureClientId}}{{{applicationName}}}{{/configureClientId}}{{basePathSeparator}}base-path{{closebrace}}"{{/clientPath}}{{/configureClientId}})
public interface {{classname}} {
{{#operations}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement
{{#generatedAnnotation}}
{{>common/generatedAnnotation}}
{{/generatedAnnotation}}
@Client({{#configureClientId}}id = "{{clientId}}", path = {{/configureClientId}}"\${{openbrace}}{{{applicationName}}}{{basePathSeparator}}base-path{{closebrace}}")
@Client({{#configureClientId}}{{#clientPath}}id = {{/clientPath}}{{/configureClientId}}"{{#configureClientId}}{{clientId}}{{/configureClientId}}{{^configureClientId}}\${{openbrace}}{{{applicationName}}}{{basePathSeparator}}base-path{{closebrace}}{{/configureClientId}}"{{#configureClientId}}{{#clientPath}}, path = "\${{openbrace}}{{#configureClientId}}{{{clientId}}}{{/configureClientId}}{{^configureClientId}}{{{applicationName}}}{{/configureClientId}}{{basePathSeparator}}base-path{{closebrace}}"{{/clientPath}}{{/configureClientId}})
interface {{classname}} {
{{#operations}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ void testNoConfigureClientId() {
String outputPath = generateFiles(codegen, PETSTORE_PATH, CodegenConstants.APIS);

// Micronaut declarative http client should not specify a Client id
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client-base-path}\")");
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client.base-path}\")");
}

@Test
Expand All @@ -259,7 +259,18 @@ void testConfigureClientId() {
String outputPath = generateFiles(codegen, PETSTORE_PATH, CodegenConstants.APIS);

// Micronaut declarative http client should use the provided Client id
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(id = \"unit-test\", path = \"${openapi-micronaut-client-base-path}\")");
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"unit-test\")");
}

@Test
void testConfigureClientIdWithPath() {
var codegen = new JavaMicronautClientCodegen();
codegen.additionalProperties().put(JavaMicronautClientCodegen.CLIENT_ID, "unit-test");
codegen.additionalProperties().put(JavaMicronautClientCodegen.OPT_CLIENT_PATH, true);
String outputPath = generateFiles(codegen, PETSTORE_PATH, CodegenConstants.APIS);

// Micronaut declarative http client should use the provided Client id
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(id = \"unit-test\", path = \"${unit-test.base-path}\")");
}

@Test
Expand All @@ -268,17 +279,17 @@ void testDefaultPathSeparator() {
String outputPath = generateFiles(codegen, PETSTORE_PATH, CodegenConstants.APIS);

// Micronaut declarative http client should use the default path separator
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client-base-path}\")");
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client.base-path}\")");
}

@Test
void testConfigurePathSeparator() {
var codegen = new JavaMicronautClientCodegen();
codegen.additionalProperties().put(JavaMicronautClientCodegen.BASE_PATH_SEPARATOR, ".");
codegen.additionalProperties().put(JavaMicronautClientCodegen.BASE_PATH_SEPARATOR, "-");
String outputPath = generateFiles(codegen, PETSTORE_PATH, CodegenConstants.APIS);

// Micronaut declarative http client should use the provided path separator
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client.base-path}\")");
assertFileContains(outputPath + "/src/main/java/org/openapitools/api/PetApi.java", "@Client(\"${openapi-micronaut-client-base-path}\")");
}

@Test
Expand Down
Loading

0 comments on commit 6d5f0ea

Please sign in to comment.