diff --git a/README.md b/README.md
index 5fe9e74ec..d466e37ac 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,16 @@ It currently consists of
# Release Notes
BOAT is still under development and subject to change.
+## 0.18.0
+* openapi-generator `7.20.0` baseline (Spring Boot 4, Jackson 3)
+* moved Java and JavaSpring templates to `7.20.0` adding remaing custom features
+* removed custom `createApiComponent` in favor of the standard `generateClientAsBean` with default set to `true`
+* removed custom `useLombokAnnotations` in favor of built-in `lombokAnnotation` template
+* removed custom `useClassLevelBeanValidation` in favor of the standard `useSpringBuiltInValidation` property
+* removed custom `useWithModifiers`, fluent setters already included in generated classes (property name methods)
+* removed unused `useProtectedFields` property
+* removed unused `useDefaultApiClient` property
+
## 0.17.75
* Fixed duplicate serialization of the discriminator property in Jackson-based Java models by removing allowGetters = true from the @JsonIgnoreProperties annotation.
* In Spring generator added support for type-level validation in collections via the `x-not-null` vendor extension to allow `@NotNull` annotations on generic type arguments.
@@ -725,7 +735,6 @@ For the `spring` generator, the additional configuration options are:
| `useTags` | use tags for creating interface and controller classnames (Default: false) |
| `useBeanValidation` | Use BeanValidation API annotations (Default: true) |
| `performBeanValidation` | Use Bean Validation Impl. to perform BeanValidation (Default: false) |
-| `useClassLevelBeanValidation` | Adds @Validated annotation to API interfaces (Default: false) |
| `useLombokAnnotations` | Use Lombok annotations to generate properties accessors and `hashCode`/`equals` methods (Default: false) |
| `addServletRequest` | Adds ServletRequest objects to API method definitions (Default: false) |
| `addBindingResult` | Adds BindingResult to Api method definitions' request bodies if UseBeanValidation true, for this to be effective you must configure UseBeanValidation, this is not done automatically (Default: false)|
diff --git a/boat-engine/pom.xml b/boat-engine/pom.xml
index b3793d829..776bed88a 100644
--- a/boat-engine/pom.xml
+++ b/boat-engine/pom.xml
@@ -5,7 +5,7 @@
com.backbase.ossbackbase-openapi-tools
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOTboat-enginejar
diff --git a/boat-maven-plugin/README.md b/boat-maven-plugin/README.md
index 3197e9d3c..67b2202a5 100644
--- a/boat-maven-plugin/README.md
+++ b/boat-maven-plugin/README.md
@@ -37,7 +37,6 @@ Same with `generate` but with opinionated defaults for Spring
truetruetrue
- falsetruetruefalse
@@ -78,7 +77,6 @@ It will generate webhook interfaces with prehook and posthook request mapping fo
truetruetrue
- falsetruetruefalse
@@ -108,7 +106,6 @@ Same with `generate` but with opinionated defaults for Rest Template Client
truetruetrue
- falsetruetruefalse
@@ -122,7 +119,7 @@ Same with `generate` but with opinionated defaults for Rest Template Client
...
- createApiComponent=false
+ restTemplateBeanName=interServiceRestTemplate
@@ -198,7 +195,6 @@ Same with `generate` but with opinionated defaults for Web Client
truetruetrue
- falsetruetruefalse
diff --git a/boat-maven-plugin/pom.xml b/boat-maven-plugin/pom.xml
index 7286b5300..3c8e8aae0 100644
--- a/boat-maven-plugin/pom.xml
+++ b/boat-maven-plugin/pom.xml
@@ -5,7 +5,7 @@
com.backbase.ossbackbase-openapi-tools
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOTboat-maven-plugin
@@ -53,6 +53,18 @@
org.openapitools.openapidiffopenapi-diff-core2.1.7
+
+
+
+ org.apache.httpcomponents
+ httpclient
+
+
+ org.apache.httpcomponents
+ httpcore
+
+
@@ -360,7 +372,7 @@
com.backbase.ossboat-maven-plugin
- 0.17.50
+ 0.17.74
diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml
index 225944b0a..03dff88ab 100644
--- a/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml
+++ b/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml
@@ -15,7 +15,7 @@
BOAT :: Generate :: Java Client
- ApiClient.java,BeanValidationException.java,RFC3339DateFormat.java,ServerConfiguration.java,ServerVariable.java,StringUtil.java,Authentication.java,HttpBasicAuth.java,HttpBearerAuth.java,ApiKeyAuth.java,ApiException.java,Pair.java,ApiResponse.java,JavaTimeFormatter.java
+ ApiClient.java,BeanValidationException.java,RFC3339DateFormat.java,ServerConfiguration.java,ServerVariable.java,StringUtil.java,Authentication.java,HttpBasicAuth.java,HttpBearerAuth.java,ApiKeyAuth.java,ApiException.java,Pair.java,ApiResponse.java,JavaTimeFormatter.java,RFC3339JavaTimeModule.java,Configuration.java,RFC3339InstantDeserializer.java,JSON.java,AbstractOpenApiSchema.java
diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml
index d642577db..3b14a7f7e 100644
--- a/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml
+++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml
@@ -73,6 +73,11 @@
swagger-annotations2.2.7
+
+
+ org.springframework
+ spring-core
+ jar
diff --git a/boat-maven-plugin/src/it/example/pom.xml b/boat-maven-plugin/src/it/example/pom.xml
index 650561ff3..dc646eeb3 100644
--- a/boat-maven-plugin/src/it/example/pom.xml
+++ b/boat-maven-plugin/src/it/example/pom.xml
@@ -11,10 +11,10 @@
@pom.version@
-
- 0.2.3
+
+ 0.2.9
- 2.13.3
+ 2.18.2${jackson.version}${jackson.version}${jackson.version}
@@ -135,7 +135,7 @@
org.springframework.bootspring-boot-starter-webflux
- 2.7.2
+ 3.3.13
@@ -147,13 +147,13 @@
org.springframework.bootspring-boot-starter-web
- 2.7.2
+ 3.3.13org.springframeworkspring-core
- 6.1.14
+ 6.1.21compile
diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java
index 703529a0c..49da05e8f 100644
--- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java
+++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java
@@ -8,6 +8,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.openapitools.codegen.languages.SpringCodegen;
@Slf4j
public abstract class AbstractGenerateMojo extends GenerateMojo {
@@ -33,7 +34,6 @@ public void execute(String generatorName, String library, boolean isEmbedded, bo
options.put("interfaceOnly", TRUE);
options.put("useTags", TRUE);
options.put("useBeanValidation", TRUE);
- options.put("useClassLevelBeanValidation", FALSE);
options.put("useOptional", FALSE);
options.put("useJakartaEe", TRUE);
options.put("useSpringBoot3", TRUE);
@@ -64,7 +64,21 @@ public void execute(String generatorName, String library, boolean isEmbedded, bo
var merged = new HashMap<>();
merged.putAll(defaultOptions);
merged.putAll(overrides);
+ boolean sb3 = propertyToBool(merged.get(SpringCodegen.USE_SPRING_BOOT3));
+ boolean sb4 = propertyToBool(merged.get(SpringCodegen.USE_SPRING_BOOT4));
+ if (sb3 && sb4) {
+ merged.put(SpringCodegen.USE_SPRING_BOOT3, FALSE);
+ }
return merged;
}
+
+ private static boolean propertyToBool(Object value) {
+ if (value instanceof Boolean) {
+ return (Boolean) value;
+ } else if (value instanceof String) {
+ return Boolean.parseBoolean((String) value);
+ }
+ return false;
+ }
}
diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java
index 73ee45dc6..1329003c6 100644
--- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java
+++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java
@@ -15,7 +15,7 @@
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyLanguageSpecificPrimitivesCsv;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyLanguageSpecificPrimitivesCsvList;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyNameMappingsKvpList;
-import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyOpenAPINormalizerKvpList;
+import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyOpenapiNormalizerKvpList;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyReservedWordsMappingsKvp;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyReservedWordsMappingsKvpList;
import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applySchemaMappingsKvp;
@@ -880,7 +880,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
}
if (openapiNormalizer != null && (configOptions == null || !configOptions.containsKey("openapi-normalizer"))) {
- applyOpenAPINormalizerKvpList(openapiNormalizer, configurator);
+ applyOpenapiNormalizerKvpList(openapiNormalizer, configurator);
}
// Apply Schema Mappings
diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java
index d4b2d414e..d3e5bdb54 100644
--- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java
+++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateRestTemplateEmbeddedMojo.java
@@ -20,6 +20,6 @@ public void execute() throws MojoExecutionException, MojoFailureException {
@Override
protected Collection getGeneratorSpecificSupportingFiles() {
- return Set.of("BigDecimalCustomSerializer.java");
+ return Set.of("BigDecimalCustomSerializer.java", "BaseApi.java");
}
}
diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java
index 664959683..c282cdb6a 100644
--- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java
+++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GenerateMojoTests.java
@@ -94,7 +94,7 @@ void useJavaBoatForRestTemplateEmbedded() throws MojoExecutionException, MojoFai
);
assertThat(
mojo.getGeneratorSpecificSupportingFiles(),
- containsInAnyOrder("BigDecimalCustomSerializer.java")
+ containsInAnyOrder("BigDecimalCustomSerializer.java", "BaseApi.java")
);
}
@@ -146,7 +146,6 @@ void shouldApplyDefaultConfigOptionsForSpringBoot() throws MojoExecutionExceptio
expectedOpts.put("interfaceOnly", "true");
expectedOpts.put("useTags", "true");
expectedOpts.put("useBeanValidation", "true");
- expectedOpts.put("useClassLevelBeanValidation", "false");
expectedOpts.put("useOptional", "false");
expectedOpts.put("useJakartaEe", "true");
expectedOpts.put("useSpringBoot3", "true");
@@ -177,7 +176,6 @@ void shouldOverrideDefaultConfigOptionsForSpringBoot() throws MojoExecutionExcep
expectedOpts.put("interfaceOnly", "true");
expectedOpts.put("useTags", "true");
expectedOpts.put("useBeanValidation", "true");
- expectedOpts.put("useClassLevelBeanValidation", "false");
expectedOpts.put("useOptional", "true");
expectedOpts.put("useJakartaEe", "true");
expectedOpts.put("useSpringBoot3", "true");
@@ -189,6 +187,36 @@ void shouldOverrideDefaultConfigOptionsForSpringBoot() throws MojoExecutionExcep
});
}
+ @Test
+ void shouldResolveSpringBootOptions() throws MojoExecutionException, MojoFailureException {
+ GenerateMojo mojo = configure(new GenerateSpringBootEmbeddedMojo(), null);
+ // add overrides
+ mojo.configOptions = Map.of(
+ "useSpringBoot4", "true"
+ );
+
+ mojo.execute();
+
+ Map expectedOpts = new HashMap<>();
+ expectedOpts.put("java8", "true");
+ expectedOpts.put("dateLibrary", "java8");
+ expectedOpts.put("performBeanValidation", "true");
+ expectedOpts.put("skipDefaultInterface", "true");
+ expectedOpts.put("interfaceOnly", "true");
+ expectedOpts.put("useTags", "true");
+ expectedOpts.put("useBeanValidation", "true");
+ expectedOpts.put("useOptional", "false");
+ expectedOpts.put("useJakartaEe", "true");
+ expectedOpts.put("useSpringBoot3", "false");
+ expectedOpts.put("useSpringBoot4", "true");
+ expectedOpts.put("containerDefaultToNull", "false");
+
+ assertNotNull(mojo.configOptions);
+ expectedOpts.forEach((key, value) -> {
+ assertEquals(value, mojo.configOptions.get(key));
+ });
+ }
+
private T configure(T mojo, String generatorName) {
mojo.buildContext = buildContext;
mojo.project = project;
diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/radio/RadioMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/radio/RadioMojoTests.java
index 2b84379b0..374c8d924 100644
--- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/radio/RadioMojoTests.java
+++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/radio/RadioMojoTests.java
@@ -588,9 +588,10 @@ private List buildSampleBoatLintReports(String expectedDefaultKe
boatLintReport.setId(BigDecimal.TEN);
boatLintReport.setGrade(reportGrade);
boatLintReport.violations(
- List.of(BoatViolation.builder().severity(sampleSeverityInResponse).build()));
+ List.of(new BoatViolation().severity(sampleSeverityInResponse)));
boatLintReport.setSpec(
- BoatSpec.builder().key(expectedDefaultKey).description(description).changes(typeOfChange).build());
+ new BoatSpec().key(expectedDefaultKey).description(description).changes(typeOfChange));
+
return List.of(boatLintReport);
}
diff --git a/boat-quay/boat-quay-lint/pom.xml b/boat-quay/boat-quay-lint/pom.xml
index c20e60663..14df40cd7 100644
--- a/boat-quay/boat-quay-lint/pom.xml
+++ b/boat-quay/boat-quay-lint/pom.xml
@@ -5,7 +5,7 @@
com.backbase.ossboat-quay
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOTboat-quay-lint
diff --git a/boat-quay/boat-quay-rules/pom.xml b/boat-quay/boat-quay-rules/pom.xml
index 2adaed33a..0f48c13c5 100644
--- a/boat-quay/boat-quay-rules/pom.xml
+++ b/boat-quay/boat-quay-rules/pom.xml
@@ -5,7 +5,7 @@
com.backbase.ossboat-quay
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOTboat-quay-rules
diff --git a/boat-quay/pom.xml b/boat-quay/pom.xml
index 26415dbb1..7a2d7f695 100644
--- a/boat-quay/pom.xml
+++ b/boat-quay/pom.xml
@@ -5,7 +5,7 @@
com.backbase.ossbackbase-openapi-tools
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOT
diff --git a/boat-scaffold/README.md b/boat-scaffold/README.md
index 6738ccc1b..c34096e0b 100644
--- a/boat-scaffold/README.md
+++ b/boat-scaffold/README.md
@@ -9,20 +9,13 @@ The `boat` plugin has multiple goals:
|-|-|-|
| `addBindingResult` | `false` | Adds BindingResult to Api method definitions' request bodies if UseBeanValidation true, for this to be effective you must configure UseBeanValidation, this is not done automatically |
| `addServletRequest` | `false` | Adds ServletRequest objects to API method definitions |
-| `useClassLevelBeanValidation` | `false` | Adds @Validated annotation to API interfaces |
-| `useLombokAnnotations` | `false` | Use Lombok annotations to generate properties accessors and `hashCode`/`equals`/`toString` methods |
| `useSetForUniqueItems` | `false` | Use `java.util.Set` for arrays that has the attribute `uniqueItems` to `true` |
| `openApiNullable` | `true` | Whether to use the `jackson-databind-nullable` library |
-| `useWithModifiers` | `false` | Generates bean `with` modifiers for fluent style |
-| `useProtectedFields` | `false` | Whether to use protected visibility for model fields |
## Java Code Generator
| Option | Default | Description |
|-|-|-|
-| `createApiComponent` | `true` | Whether to generate the client as a Spring component (`resttemplate` only) |
| `restTemplateBeanName` | `none` | The qualifier of the `RestTemplate` used by the `ApiClient` (`resttemplate` only) |
-| `useClassLevelBeanValidation` | `false` | Adds @Validated annotation to API interfaces |
| `useJacksonConversion` | `false` | Use Jackson to convert query parameters (`resttemplate` only) |
| `useSetForUniqueItems` | `false` | Use `java.util.Set` for arrays that has the attribute `uniqueItems` to `true` |
-| `useProtectedFields` | `false` | "Whether to use protected visibility for model fields |
diff --git a/boat-scaffold/pom.xml b/boat-scaffold/pom.xml
index d62bb8924..479e70c16 100644
--- a/boat-scaffold/pom.xml
+++ b/boat-scaffold/pom.xml
@@ -5,7 +5,7 @@
com.backbase.ossbackbase-openapi-tools
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOTboat-scaffold
@@ -102,7 +102,7 @@
com.backbase.ossboat-trail-resources
- 0.17.75-SNAPSHOT
+ 0.18.0-SNAPSHOTtest
@@ -161,6 +161,7 @@
org.apache.maven.resolvermaven-resolver-transport-http${maven.resolver.version}
+ testcom.github.javaparser
diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java
index b1fc08324..15949b96b 100644
--- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java
+++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java
@@ -1,7 +1,6 @@
package com.backbase.oss.codegen.java;
import com.backbase.oss.codegen.java.BoatCodeGenUtils.CodegenValueType;
-import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import lombok.Getter;
import lombok.Setter;
@@ -19,31 +18,14 @@ public class BoatJavaCodeGen extends JavaClientCodegen {
public static final String NAME = "boat-java";
- public static final String USE_WITH_MODIFIERS = "useWithModifiers";
- public static final String USE_CLASS_LEVEL_BEAN_VALIDATION = "useClassLevelBeanValidation";
public static final String USE_JACKSON_CONVERSION = "useJacksonConversion";
- public static final String USE_DEFAULT_API_CLIENT = "useDefaultApiClient";
public static final String REST_TEMPLATE_BEAN_NAME = "restTemplateBeanName";
- public static final String CREATE_API_COMPONENT = "createApiComponent";
- public static final String USE_PROTECTED_FIELDS = "useProtectedFields";
- @Setter
- @Getter
- protected boolean useWithModifiers;
- @Setter
- @Getter
- protected boolean useClassLevelBeanValidation;
@Setter
@Getter
protected boolean useJacksonConversion;
@Getter
@Setter
- protected boolean useDefaultApiClient = true;
- @Getter
- @Setter
protected String restTemplateBeanName;
- @Getter
- @Setter
- protected boolean createApiComponent = true;
public BoatJavaCodeGen() {
this.useJakartaEe = true;
@@ -51,20 +33,13 @@ public BoatJavaCodeGen() {
this.embeddedTemplateDir = this.templateDir = NAME;
- this.cliOptions.add(CliOption.newBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION,
- "Add @Validated to class-level Api interfaces", this.useClassLevelBeanValidation));
- this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS,
- "Whether to use \"with\" prefix for POJO modifiers", this.useWithModifiers));
this.cliOptions.add(CliOption.newBoolean(USE_JACKSON_CONVERSION,
"Whether to use Jackson to convert query parameters to String", this.useJacksonConversion));
- this.cliOptions.add(CliOption.newBoolean(USE_DEFAULT_API_CLIENT,
- "Whether to use a default ApiClient with a builtin template", this.useDefaultApiClient));
this.cliOptions.add(CliOption.newString(REST_TEMPLATE_BEAN_NAME,
"An optional RestTemplate bean name"));
- this.cliOptions.add(CliOption.newString(CREATE_API_COMPONENT,
- "Whether to generate the client as a Spring component"));
- this.cliOptions.add(CliOption.newString(USE_PROTECTED_FIELDS,
- "Whether to use protected visibility for model fields"));
+
+ // change default to match creating @Component
+ this.setGenerateClientAsBean(true);
}
@Override
@@ -76,19 +51,9 @@ public String getName() {
public void processOpts() {
super.processOpts();
- if (this.additionalProperties.containsKey(USE_WITH_MODIFIERS)) {
- this.useWithModifiers = convertPropertyToBoolean(USE_WITH_MODIFIERS);
- }
- writePropertyBack(USE_WITH_MODIFIERS, this.useWithModifiers);
-
if (RESTTEMPLATE.equals(getLibrary())) {
processRestTemplateOpts();
}
- if (this.additionalProperties.containsKey(USE_PROTECTED_FIELDS)) {
- this.additionalProperties.put("modelFieldsVisibility", "protected");
- } else {
- this.additionalProperties.put("modelFieldsVisibility", "private");
- }
if (!getLibrary().startsWith("jersey")) {
this.supportingFiles.removeIf(f -> f.getTemplateFile().equals("ServerConfiguration.mustache"));
@@ -98,11 +63,6 @@ public void processOpts() {
}
private void processRestTemplateOpts() {
- if (this.additionalProperties.containsKey(USE_CLASS_LEVEL_BEAN_VALIDATION)) {
- this.useClassLevelBeanValidation = convertPropertyToBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION);
- }
- writePropertyBack(USE_CLASS_LEVEL_BEAN_VALIDATION, this.useClassLevelBeanValidation);
-
if (this.additionalProperties.containsKey(USE_JACKSON_CONVERSION)) {
this.useJacksonConversion = convertPropertyToBoolean(USE_JACKSON_CONVERSION);
}
@@ -111,18 +71,8 @@ private void processRestTemplateOpts() {
this.supportingFiles.removeIf(f -> f.getTemplateFile().equals("RFC3339DateFormat.mustache"));
}
- if (this.additionalProperties.containsKey(USE_DEFAULT_API_CLIENT)) {
- this.useDefaultApiClient = convertPropertyToBoolean(USE_DEFAULT_API_CLIENT);
- }
- writePropertyBack(USE_DEFAULT_API_CLIENT, this.useDefaultApiClient);
-
this.restTemplateBeanName = (String) this.additionalProperties.get(REST_TEMPLATE_BEAN_NAME);
- if (this.additionalProperties.containsKey(CREATE_API_COMPONENT)) {
- this.createApiComponent = convertPropertyToBoolean(CREATE_API_COMPONENT);
- }
- writePropertyBack(CREATE_API_COMPONENT, this.createApiComponent);
-
if (useJacksonConversion) {
final var serializerTemplate = "BigDecimalCustomSerializer";
String targetDir = (sourceFolder + File.separator + modelPackage).replace(".", java.io.File.separator);
@@ -157,11 +107,10 @@ private boolean isArrayTypeOfEnum(Schema s) {
if (!ModelUtils.isArraySchema(target)) {
return false;
}
- Schema items = getSchemaItems((ArraySchema) target);
+ Schema items = ModelUtils.getSchemaItems(target);
if (items.get$ref() != null) {
items = openAPI.getComponents().getSchemas().get(ModelUtils.getSimpleRef(items.get$ref()));
}
return items.getEnum() != null;
}
-
}
diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java
index 89e23ee2e..633651516 100644
--- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java
+++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java
@@ -46,12 +46,10 @@ public class BoatSpringCodeGen extends SpringCodegen {
public static final String NAME = "boat-spring";
- public static final String USE_CLASS_LEVEL_BEAN_VALIDATION = "useClassLevelBeanValidation";
public static final String ADD_SERVLET_REQUEST = "addServletRequest";
public static final String ADD_BINDING_RESULT = "addBindingResult";
- public static final String USE_LOMBOK_ANNOTATIONS = "useLombokAnnotations";
- public static final String USE_WITH_MODIFIERS = "useWithModifiers";
- public static final String USE_PROTECTED_FIELDS = "useProtectedFields";
+
+ private static final String VENDOR_EXTENSION_NOT_NULL = "x-not-null";
static class NewLineIndent implements Mustache.Lambda {
@@ -149,13 +147,6 @@ protected String postProcessLine(String line) {
}
}
- /**
- * Add @Validated to class-level Api interfaces. Defaults to false
- */
- @Setter
- @Getter
- protected boolean useClassLevelBeanValidation;
-
/**
* Adds a HttpServletRequest object to the API definition method.
*/
@@ -170,43 +161,16 @@ protected String postProcessLine(String line) {
@Getter
protected boolean addBindingResult;
- /**
- * Add Lombok to class-level Api models. Defaults to false
- */
- @Setter
- @Getter
- protected boolean useLombokAnnotations;
-
-
- /**
- * Whether to use {@code with} prefix for pojos modifiers.
- */
- @Setter
- @Getter
- protected boolean useWithModifiers;
-
- @Setter
- @Getter
- protected boolean useProtectedFields;
-
public BoatSpringCodeGen() {
super();
this.embeddedTemplateDir = this.templateDir = NAME;
this.openapiNormalizer.put("REF_AS_PARENT_IN_ALLOF", "true");
- this.cliOptions.add(CliOption.newBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION,
- "Add @Validated to class-level Api interfaces.", this.useClassLevelBeanValidation));
this.cliOptions.add(CliOption.newBoolean(ADD_SERVLET_REQUEST,
"Adds a HttpServletRequest object to the API definition method.", this.addServletRequest));
this.cliOptions.add(CliOption.newBoolean(ADD_BINDING_RESULT,
"Adds a Binding result as method perimeter. Only implemented if @validate is being used.",
this.addBindingResult));
- this.cliOptions.add(CliOption.newBoolean(USE_LOMBOK_ANNOTATIONS,
- "Add Lombok to class-level Api models. Defaults to false.", this.useLombokAnnotations));
- this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS,
- "Whether to use \"with\" prefix for POJO modifiers.", this.useWithModifiers));
- this.cliOptions.add(CliOption.newString(USE_PROTECTED_FIELDS,
- "Whether to use protected visibility for model fields"));
this.apiNameSuffix = "Api";
}
@@ -245,23 +209,29 @@ public CodegenProperty fromProperty(String name, Schema p, boolean required, boo
* "overridden" to fix invalid code when the data type is a collection of a fully qualified classname.
* eg. Set<@Valid com.backbase.dbs.arrangement.commons.model.TranslationItemDto>
*
- * @param codegenProperty
+ * @param itemsProperty
* @param dataType
* @return
*/
- String replaceBeanValidationCollectionType(CodegenProperty codegenProperty, String dataType) {
- if (!useBeanValidation || isEmpty(dataType) || !codegenProperty.isModel || isResponseType(codegenProperty)) {
+ String replaceBeanValidationCollectionType(CodegenProperty itemsProperty, String dataType) {
+ if (!useBeanValidation || isEmpty(dataType) || isResponseType(itemsProperty)) {
return dataType;
}
+
String result = dataType;
- if (!contains(dataType, "@Valid")) {
- result = dataType.replace("<", "<@Valid ");
- }
- Matcher m = Pattern.compile("^(.+\\<)(@Valid) ([a-z\\.]+)([A-Z].*)(\\>)$").matcher(dataType);
- if (m.matches()) {
- // Set<@Valid com.backbase.dbs.arrangement.commons.model.TranslationItemDto>
- result = m.group(1) + m.group(3) + m.group(2) + " " + m.group(4) + m.group(5);
+ if (itemsProperty.isModel) {
+ if (!contains(dataType, "@Valid")) {
+ result = dataType.replace("<", "<@Valid ");
+ }
+ Matcher m = Pattern.compile("^(.+\\<)(@Valid) ([a-z\\.]+)([A-Z].*)(\\>)$").matcher(dataType);
+ if (m.matches()) {
+ // Set<@Valid com.backbase.dbs.arrangement.commons.model.TranslationItemDto>
+ result = m.group(1) + m.group(3) + m.group(2) + " " + m.group(4) + m.group(5);
+ }
+ } else if (applyNotNullVendorExtension(itemsProperty, dataType)) {
+ result = dataType.replace("<", "<@NotNull ");
}
+
return result;
}
@@ -280,6 +250,26 @@ private static boolean isResponseType(CodegenProperty codegenProperty) {
return codegenProperty.baseName.toLowerCase(Locale.ROOT).contains("response");
}
+ private boolean applyNotNullVendorExtension(CodegenProperty itemsProperty, String dataType) {
+ if (contains(dataType, "@NotNull")) {
+ return false;
+ }
+
+ return booleanExtension(itemsProperty, VENDOR_EXTENSION_NOT_NULL);
+ }
+
+ private boolean booleanExtension(CodegenProperty itemsProperty, String name) {
+ if (itemsProperty == null || itemsProperty.getVendorExtensions() == null) {
+ return false;
+ }
+
+ try {
+ return Boolean.parseBoolean(String.valueOf(itemsProperty.getVendorExtensions().getOrDefault(name, "false")));
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
@Override
public String getName() {
return NAME;
@@ -324,35 +314,17 @@ public void processOpts() {
serializerTemplate + ".java"
));
this.importMapping.put(serializerTemplate, modelPackage + "." + serializerTemplate);
+ this.importMapping.put("JsonSerialize", "com.fasterxml.jackson.databind.annotation.JsonSerialize");
- if (this.additionalProperties.containsKey(USE_CLASS_LEVEL_BEAN_VALIDATION)) {
- this.useClassLevelBeanValidation = convertPropertyToBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION);
- }
if (this.additionalProperties.containsKey(ADD_SERVLET_REQUEST)) {
this.addServletRequest = convertPropertyToBoolean(ADD_SERVLET_REQUEST);
}
if (this.additionalProperties.containsKey(ADD_BINDING_RESULT)) {
this.addBindingResult = convertPropertyToBoolean(ADD_BINDING_RESULT);
}
- if (this.additionalProperties.containsKey(USE_LOMBOK_ANNOTATIONS)) {
- this.useLombokAnnotations = convertPropertyToBoolean(USE_LOMBOK_ANNOTATIONS);
- }
- if (this.additionalProperties.containsKey(USE_WITH_MODIFIERS)) {
- this.useWithModifiers = convertPropertyToBoolean(USE_WITH_MODIFIERS);
- }
- if (this.additionalProperties.containsKey(USE_PROTECTED_FIELDS)) {
- this.additionalProperties.put("modelFieldsVisibility", "protected");
- } else {
- this.additionalProperties.put("modelFieldsVisibility", "private");
- }
- writePropertyBack(USE_CLASS_LEVEL_BEAN_VALIDATION, this.useClassLevelBeanValidation);
writePropertyBack(ADD_SERVLET_REQUEST, this.addServletRequest);
writePropertyBack(ADD_BINDING_RESULT, this.addBindingResult);
- writePropertyBack(USE_LOMBOK_ANNOTATIONS, this.useLombokAnnotations);
- writePropertyBack(USE_WITH_MODIFIERS, this.useWithModifiers);
- writePropertyBack(USE_PROTECTED_FIELDS, this.useProtectedFields);
-
this.additionalProperties.put("indent4", new IndentedLambda(4, " ", true, true));
this.additionalProperties.put("newLine4", new NewLineIndent(4, " "));
diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodegenProperty.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodegenProperty.java
index 60f0a750c..d4c35a19a 100644
--- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodegenProperty.java
+++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodegenProperty.java
@@ -45,7 +45,6 @@ public BoatSpringCodegenProperty(CodegenProperty codegenProperty) {
super.exclusiveMaximum = codegenProperty.exclusiveMaximum;
super.required = codegenProperty.required;
super.deprecated = codegenProperty.deprecated;
- super.hasMoreNonReadOnly = codegenProperty.hasMoreNonReadOnly;
super.isPrimitiveType = codegenProperty.isPrimitiveType;
super.isModel = codegenProperty.isModel;
super.isContainer = codegenProperty.isContainer;
@@ -100,6 +99,7 @@ public BoatSpringCodegenProperty(CodegenProperty codegenProperty) {
super.nameInLowerCase = codegenProperty.nameInLowerCase;
super.nameInCamelCase = codegenProperty.nameInCamelCase;
super.nameInSnakeCase = codegenProperty.nameInSnakeCase;
+ super.nameInPascalCase = codegenProperty.nameInPascalCase;
super.enumName = codegenProperty.enumName;
super.maxItems = codegenProperty.maxItems;
super.minItems = codegenProperty.minItems;
diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatWebhooksCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatWebhooksCodeGen.java
index 9a325fc72..a9bb938ef 100644
--- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatWebhooksCodeGen.java
+++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatWebhooksCodeGen.java
@@ -20,8 +20,6 @@ public class BoatWebhooksCodeGen extends BoatSpringCodeGen {
public static final String ADD_SERVLET_REQUEST = "addServletRequest";
public static final String ADD_BINDING_RESULT = "addBindingResult";
public static final String USE_LOMBOK_ANNOTATIONS = "useLombokAnnotations";
- public static final String USE_WITH_MODIFIERS = "useWithModifiers";
- public static final String USE_PROTECTED_FIELDS = "useProtectedFields";
public static final String MUSTACHE_EXTENSION =".mustache";
public static final String JAVA_EXTENSION =".java";
@@ -32,19 +30,11 @@ public BoatWebhooksCodeGen() {
this.embeddedTemplateDir = this.templateDir = NAME;
this.openapiNormalizer.put("REF_AS_PARENT_IN_ALLOF", "true");
- this.cliOptions.add(CliOption.newBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION,
- "Add @Validated to class-level Api interfaces.", this.useClassLevelBeanValidation));
this.cliOptions.add(CliOption.newBoolean(ADD_SERVLET_REQUEST,
"Adds a HttpServletRequest object to the API definition method.", this.addServletRequest));
this.cliOptions.add(CliOption.newBoolean(ADD_BINDING_RESULT,
"Adds a Binding result as method perimeter. Only implemented if @validate is being used.",
this.addBindingResult));
- this.cliOptions.add(CliOption.newBoolean(USE_LOMBOK_ANNOTATIONS,
- "Add Lombok to class-level Api models. Defaults to false.", this.useLombokAnnotations));
- this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS,
- "Whether to use \"with\" prefix for POJO modifiers.", this.useWithModifiers));
- this.cliOptions.add(CliOption.newString(USE_PROTECTED_FIELDS,
- "Whether to use protected visibility for model fields"));
supportedLibraries.put(NAME, "Boat Webhooks codegen");
this.apiNameSuffix = "Api";
this.apiNamePrefix = "Webhook";
diff --git a/boat-scaffold/src/main/templates/boat-docs/js_json_schema_ref_parser.mustache b/boat-scaffold/src/main/templates/boat-docs/js_json_schema_ref_parser.mustache
index fb1bd144f..042c9b3c4 100644
--- a/boat-scaffold/src/main/templates/boat-docs/js_json_schema_ref_parser.mustache
+++ b/boat-scaffold/src/main/templates/boat-docs/js_json_schema_ref_parser.mustache
@@ -10663,7 +10663,7 @@ function crawl (obj, path, pathFromRoot, parents, $refs, options) {
/**
* Dereferences the given JSON Reference, and then crawls the resulting value.
*
- * @param {{$ref: string}} $ref - The JSON Reference to resolve
+ * @param $ref - The JSON Reference to resolve
* @param {string} path - The full path of `$ref`, possibly with a JSON Pointer in the hash
* @param {string} pathFromRoot - The path of `$ref` from the schema root
* @param {object[]} parents - An array of the parent objects that have already been dereferenced
@@ -12487,7 +12487,7 @@ function crawl (obj, path, $refs, options) {
/**
* Resolves the given JSON Reference, and then crawls the resulting value.
*
- * @param {{$ref: string}} $ref - The JSON Reference to resolve
+ * @param $ref - The JSON Reference to resolve
* @param {string} path - The full path of `$ref`, possibly with a JSON Pointer in the hash
* @param {$Refs} $refs
* @param {$RefParserOptions} options
diff --git a/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache
index 69494573c..c38f59dcb 100644
--- a/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache
@@ -8,7 +8,12 @@ import com.fasterxml.jackson.datatype.joda.JodaModule;
{{/joda}}
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.OffsetDateTime;
+{{#useJakartaEe}}
+import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
+{{/useJakartaEe}}
+{{^useJakartaEe}}
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+{{/useJakartaEe}}
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
@@ -21,9 +26,9 @@ import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.FileDataBodyPart;
-import javax.ws.rs.core.Cookie;
-import javax.ws.rs.core.Response.Status.Family;
-import javax.ws.rs.core.MediaType;
+import {{javaxPackage}}.ws.rs.core.Cookie;
+import {{javaxPackage}}.ws.rs.core.Response.Status.Family;
+import {{javaxPackage}}.ws.rs.core.MediaType;
import java.util.Collection;
import java.util.Collections;
@@ -59,10 +64,11 @@ import {{invokerPackage}}.auth.OAuth;
{{/hasOAuthMethods}}
{{>generatedAnnotation}}
+
public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
- private Map defaultHeaderMap = new HashMap();
- private Map defaultCookieMap = new HashMap();
- private String basePath = "{{{basePath}}}";
+ protected Map defaultHeaderMap = new HashMap();
+ protected Map defaultCookieMap = new HashMap();
+ protected String basePath = "{{{basePath}}}";
protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
{{/-first}} new ServerConfiguration(
"{{{url}}}",
@@ -90,18 +96,18 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map serverVariables = null;
- private boolean debugging = false;
- private int connectionTimeout = 0;
+ protected boolean debugging = false;
+ protected int connectionTimeout = 0;
- private Client httpClient;
- private ObjectMapper objectMapper;
+ protected Client httpClient;
+ protected ObjectMapper objectMapper;
- private Map authentications;
+ protected Map authentications;
- private int statusCode;
- private Map> responseHeaders;
+ protected int statusCode;
+ protected Map> responseHeaders;
- private DateFormat dateFormat;
+ protected DateFormat dateFormat;
public ApiClient() {
objectMapper = new ObjectMapper();
@@ -124,8 +130,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}}
- authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}}
- authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}}
+ authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{#isBasicBearer}}
+ authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}}
authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
@@ -192,6 +198,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
+ this.serverIndex = null;
return this;
}
@@ -528,11 +535,11 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @param value The value of the parameter.
* @return A list of {@code Pair} objects.
*/
- public List parameterToPairs(String collectionFormat, String name, Collection value) {
+ public List parameterToPairs(String collectionFormat, String name, Collection> value) {
List params = new ArrayList();
// preconditions
- if (name == null || name.isEmpty() || value == null) {
+ if (name == null || name.isEmpty() || value == null || value.isEmpty()) {
return params;
}
@@ -682,11 +689,12 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @param collectionQueryParams The collection query parameters
* @return The full URL
*/
- private String buildUrl(String path, List queryParams, List collectionQueryParams) {
+ protected String buildUrl(String path, List queryParams, List collectionQueryParams) {
String baseURL;
if (serverIndex != null) {
if (serverIndex < 0 || serverIndex >= servers.size()) {
throw new ArrayIndexOutOfBoundsException(String.format(
+ java.util.Locale.ROOT,
"Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size()
));
}
@@ -735,7 +743,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return url.toString();
}
- private ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException {
+ protected ClientResponse getAPIResponse(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames) throws ApiException {
if (body != null && !formParams.isEmpty()) {
throw new ApiException(500, "Cannot have body and form params");
}
@@ -848,7 +856,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @param headerParams Header parameters
* @param cookieParams Cookie parameters
*/
- private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) {
+ protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) {
for (String authName : authNames) {
Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
@@ -861,7 +869,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @param formParams Form parameters
* @return HTTP form encoded parameters
*/
- private String getXWWWFormUrlencodedParams(Map formParams) {
+ protected String getXWWWFormUrlencodedParams(Map formParams) {
StringBuilder formParamBuilder = new StringBuilder();
for (Entry param : formParams.entrySet()) {
@@ -883,4 +891,4 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return encodedFormParams;
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache b/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache
index 179abe2fa..d551902f8 100644
--- a/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache
@@ -1,15 +1,12 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import java.util.Set;
-{{^useJakartaEe}}
-import javax.validation.ConstraintViolation;
-import javax.validation.ValidationException;
-{{/useJakartaEe}}
-{{#useJakartaEe}}
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ValidationException;
-{{/useJakartaEe}}
+import {{javaxPackage}}.validation.ConstraintViolation;
+import {{javaxPackage}}.validation.ValidationException;
+
public class BeanValidationException extends ValidationException {
/**
*
@@ -29,4 +26,4 @@ public class BeanValidationException extends ValidationException {
this.violations = violations;
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/Configuration.mustache b/boat-scaffold/src/main/templates/boat-java/Configuration.mustache
index cb425df35..c932ddf99 100644
--- a/boat-scaffold/src/main/templates/boat-java/Configuration.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/Configuration.mustache
@@ -2,27 +2,52 @@
package {{invokerPackage}};
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
{{>generatedAnnotation}}
+
public class Configuration {
- private static ApiClient defaultApiClient = new ApiClient();
-
- /**
- * Get the default API client, which would be used when creating API
- * instances without providing an API client.
- *
- * @return Default API client
- */
- public static ApiClient getDefaultApiClient() {
- return defaultApiClient;
- }
+ public static final String VERSION = "{{{artifactVersion}}}";
+
+ private static final AtomicReference defaultApiClient = new AtomicReference<>();
+ private static volatile Supplier apiClientFactory = ApiClient::new;
- /**
- * Set the default API client, which would be used when creating API
- * instances without providing an API client.
- *
- * @param apiClient API client
- */
- public static void setDefaultApiClient(ApiClient apiClient) {
- defaultApiClient = apiClient;
+ /**
+ * Get the default API client, which would be used when creating API instances without providing an API client.
+ *
+ * @return Default API client
+ */
+ public static ApiClient getDefaultApiClient() {
+ ApiClient client = defaultApiClient.get();
+ if (client == null) {
+ client = defaultApiClient.updateAndGet(val -> {
+ if (val != null) { // changed by another thread
+ return val;
+ }
+ return apiClientFactory.get();
+ });
}
-}
+ return client;
+ }
+
+ /**
+ * Set the default API client, which would be used when creating API instances without providing an API client.
+ *
+ * @param apiClient API client
+ */
+ public static void setDefaultApiClient(ApiClient apiClient) {
+ defaultApiClient.set(apiClient);
+ }
+
+ /**
+ * set the callback used to create new ApiClient objects
+ */
+ public static void setApiClientFactory(Supplier factory) {
+ apiClientFactory = Objects.requireNonNull(factory);
+ }
+
+ private Configuration() {
+ }
+}
\ No newline at end of file
diff --git a/boat-scaffold/src/main/templates/boat-java/CustomInstantDeserializer.mustache b/boat-scaffold/src/main/templates/boat-java/CustomInstantDeserializer.mustache
index 5ebea810e..d4a3ca97e 100644
--- a/boat-scaffold/src/main/templates/boat-java/CustomInstantDeserializer.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/CustomInstantDeserializer.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import com.fasterxml.jackson.core.JsonParser;
diff --git a/boat-scaffold/src/main/templates/boat-java/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/JSON.mustache
index d315850bb..5ef02660d 100644
--- a/boat-scaffold/src/main/templates/boat-java/JSON.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/JSON.mustache
@@ -31,9 +31,11 @@ import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
+{{#jsr310}}
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
+{{/jsr310}}
import java.util.Date;
import java.util.Locale;
import java.util.Map;
@@ -536,4 +538,4 @@ public class JSON {
return this;
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache b/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache
index f3fb34e55..e96325c40 100644
--- a/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache
@@ -10,44 +10,49 @@ import java.time.format.DateTimeParseException;
* It's generated for java clients when {@code AbstractJavaCodegen#dateLibrary} specified as {@code java8}.
*/
{{>generatedAnnotation}}
+
public class JavaTimeFormatter {
+ private DateTimeFormatter offsetDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
- private DateTimeFormatter offsetDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+ /**
+ * Get the date format used to parse/format {@code OffsetDateTime} parameters.
+ *
+ * @return DateTimeFormatter
+ */
+ public DateTimeFormatter getOffsetDateTimeFormatter() {
+ return offsetDateTimeFormatter;
+ }
- /**
- * Get the date format used to parse/format {@code OffsetDateTime} parameters.
- * @return DateTimeFormatter
- */
- public DateTimeFormatter getOffsetDateTimeFormatter() {
- return offsetDateTimeFormatter;
- }
+ /**
+ * Set the date format used to parse/format {@code OffsetDateTime} parameters.
+ *
+ * @param offsetDateTimeFormatter {@code DateTimeFormatter}
+ */
+ public void setOffsetDateTimeFormatter(DateTimeFormatter offsetDateTimeFormatter) {
+ this.offsetDateTimeFormatter = offsetDateTimeFormatter;
+ }
- /**
- * Set the date format used to parse/format {@code OffsetDateTime} parameters.
- * @param offsetDateTimeFormatter {@code DateTimeFormatter}
- */
- public void setOffsetDateTimeFormatter(DateTimeFormatter offsetDateTimeFormatter) {
- this.offsetDateTimeFormatter = offsetDateTimeFormatter;
+ /**
+ * Parse the given string into {@code OffsetDateTime} object.
+ *
+ * @param str String
+ * @return {@code OffsetDateTime}
+ */
+ public OffsetDateTime parseOffsetDateTime(String str) {
+ try {
+ return OffsetDateTime.parse(str, offsetDateTimeFormatter);
+ } catch (DateTimeParseException e) {
+ throw new RuntimeException(e);
}
+ }
- /**
- * Parse the given string into {@code OffsetDateTime} object.
- * @param str String
- * @return {@code OffsetDateTime}
- */
- public OffsetDateTime parseOffsetDateTime(String str) {
- try {
- return OffsetDateTime.parse(str, offsetDateTimeFormatter);
- } catch (DateTimeParseException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * Format the given {@code OffsetDateTime} object into string.
- * @param offsetDateTime {@code OffsetDateTime}
- * @return {@code OffsetDateTime} in string format
- */
- public String formatOffsetDateTime(OffsetDateTime offsetDateTime) {
- return offsetDateTimeFormatter.format(offsetDateTime);
- }
-}
+ /**
+ * Format the given {@code OffsetDateTime} object into string.
+ *
+ * @param offsetDateTime {@code OffsetDateTime}
+ * @return {@code OffsetDateTime} in string format
+ */
+ public String formatOffsetDateTime(OffsetDateTime offsetDateTime) {
+ return offsetDateTimeFormatter.format(offsetDateTime);
+ }
+}
\ No newline at end of file
diff --git a/boat-scaffold/src/main/templates/boat-java/Pair.mustache b/boat-scaffold/src/main/templates/boat-java/Pair.mustache
index ff9e06b20..fc7d0568d 100644
--- a/boat-scaffold/src/main/templates/boat-java/Pair.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/Pair.mustache
@@ -3,48 +3,25 @@
package {{invokerPackage}};
{{>generatedAnnotation}}
-public class Pair {
- private String name = "";
- private String value = "";
-
- public Pair (String name, String value) {
- setName(name);
- setValue(value);
- }
-
- private void setName(String name) {
- if (!isValidString(name)) {
- return;
- }
-
- this.name = name;
- }
- private void setValue(String value) {
- if (!isValidString(value)) {
- return;
- }
-
- this.value = value;
- }
-
- public String getName() {
- return this.name;
- }
+public class Pair {
+ private final String name;
+ private final String value;
- public String getValue() {
- return this.value;
- }
+ public Pair(String name, String value) {
+ this.name = isValidString(name) ? name : "";
+ this.value = isValidString(value) ? value : "";
+ }
- private boolean isValidString(String arg) {
- if (arg == null) {
- return false;
- }
+ public String getName() {
+ return this.name;
+ }
- if (arg.trim().isEmpty()) {
- return false;
- }
+ public String getValue() {
+ return this.value;
+ }
- return true;
- }
+ private static boolean isValidString(String arg) {
+ return arg != null;
+ }
}
diff --git a/boat-scaffold/src/main/templates/boat-java/README.mustache b/boat-scaffold/src/main/templates/boat-java/README.mustache
index 777e2c860..157c8b6e0 100644
--- a/boat-scaffold/src/main/templates/boat-java/README.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/README.mustache
@@ -8,6 +8,8 @@
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
+- Generator version: {{generatorVersion}}
+
{{{appDescriptionWithNewLines}}}
{{#infoUrl}}
@@ -197,11 +199,14 @@ Class | Method | HTTP request | Description
{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md)
{{/model}}{{/models}}
+
## Documentation for Authorization
-{{^authMethods}}All endpoints do not require authorization.
-{{/authMethods}}Authentication schemes defined for the API:
-{{#authMethods}}### {{name}}
+{{^authMethods}}Endpoints do not require authorization.{{/authMethods}}
+{{#hasAuthMethods}}Authentication schemes defined for the API:{{/hasAuthMethods}}
+{{#authMethods}}
+
+### {{name}}
{{#isApiKey}}
@@ -209,10 +214,18 @@ Class | Method | HTTP request | Description
- **API key parameter name**: {{keyParamName}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
-{{#isBasic}}
+{{#isBasicBasic}}
- **Type**: HTTP basic authentication
-{{/isBasic}}
+{{/isBasicBasic}}
+{{#isBasicBearer}}
+
+- **Type**: HTTP Bearer Token authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
+{{/isBasicBearer}}
+{{#isHttpSignature}}
+
+- **Type**: HTTP signature authentication
+{{/isHttpSignature}}
{{#isOAuth}}
- **Type**: OAuth
@@ -232,4 +245,4 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea
## Author
{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
-{{/-last}}{{/apis}}{{/apiInfo}}
\ No newline at end of file
+{{/-last}}{{/apis}}{{/apiInfo}}
diff --git a/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache b/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache
index 311616a4e..c2c205c20 100644
--- a/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache
@@ -11,6 +11,8 @@ import java.text.DecimalFormat;
import java.util.GregorianCalendar;
import java.util.TimeZone;
+{{>generatedAnnotation}}
+
public class RFC3339DateFormat extends DateFormat {
private static final long serialVersionUID = 1L;
private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC");
@@ -43,4 +45,4 @@ public class RFC3339DateFormat extends DateFormat {
public Object clone() {
return super.clone();
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/RFC3339InstantDeserializer.mustache b/boat-scaffold/src/main/templates/boat-java/RFC3339InstantDeserializer.mustache
new file mode 100644
index 000000000..ea4b0799a
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/RFC3339InstantDeserializer.mustache
@@ -0,0 +1,90 @@
+{{>licenseInfo}}
+package {{invokerPackage}};
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAccessor;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeFeature;
+import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer;
+
+{{>generatedAnnotation}}
+
+public class RFC3339InstantDeserializer extends InstantDeserializer {
+ private static final long serialVersionUID = 1L;
+ private final static boolean DEFAULT_NORMALIZE_ZONE_ID = JavaTimeFeature.NORMALIZE_DESERIALIZED_ZONE_ID.enabledByDefault();
+ private final static boolean DEFAULT_ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS
+ = JavaTimeFeature.ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS.enabledByDefault();
+
+ public static final RFC3339InstantDeserializer INSTANT = new RFC3339InstantDeserializer<>(
+ Instant.class, DateTimeFormatter.ISO_INSTANT,
+ Instant::from,
+ a -> Instant.ofEpochMilli( a.value ),
+ a -> Instant.ofEpochSecond( a.integer, a.fraction ),
+ null,
+ true, // yes, replace zero offset with Z
+ DEFAULT_NORMALIZE_ZONE_ID,
+ DEFAULT_ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS
+ );
+
+ public static final RFC3339InstantDeserializer OFFSET_DATE_TIME = new RFC3339InstantDeserializer<>(
+ OffsetDateTime.class, DateTimeFormatter.ISO_OFFSET_DATE_TIME,
+ OffsetDateTime::from,
+ a -> OffsetDateTime.ofInstant( Instant.ofEpochMilli( a.value ), a.zoneId ),
+ a -> OffsetDateTime.ofInstant( Instant.ofEpochSecond( a.integer, a.fraction ), a.zoneId ),
+ (d, z) -> ( d.isEqual( OffsetDateTime.MIN ) || d.isEqual( OffsetDateTime.MAX ) ?
+ d :
+ d.withOffsetSameInstant( z.getRules().getOffset( d.toLocalDateTime() ) ) ),
+ true, // yes, replace zero offset with Z
+ DEFAULT_NORMALIZE_ZONE_ID,
+ DEFAULT_ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS
+ );
+
+ public static final RFC3339InstantDeserializer ZONED_DATE_TIME = new RFC3339InstantDeserializer<>(
+ ZonedDateTime.class, DateTimeFormatter.ISO_ZONED_DATE_TIME,
+ ZonedDateTime::from,
+ a -> ZonedDateTime.ofInstant( Instant.ofEpochMilli( a.value ), a.zoneId ),
+ a -> ZonedDateTime.ofInstant( Instant.ofEpochSecond( a.integer, a.fraction ), a.zoneId ),
+ ZonedDateTime::withZoneSameInstant,
+ false, // keep zero offset and Z separate since zones explicitly supported
+ DEFAULT_NORMALIZE_ZONE_ID,
+ DEFAULT_ALWAYS_ALLOW_STRINGIFIED_DATE_TIMESTAMPS
+ );
+
+ protected RFC3339InstantDeserializer(
+ Class supportedType,
+ DateTimeFormatter formatter,
+ Function parsedToValue,
+ Function fromMilliseconds,
+ Function fromNanoseconds,
+ BiFunction adjust,
+ boolean replaceZeroOffsetAsZ,
+ boolean normalizeZoneId,
+ boolean readNumericStringsAsTimestamp) {
+ super(
+ supportedType,
+ formatter,
+ parsedToValue,
+ fromMilliseconds,
+ fromNanoseconds,
+ adjust,
+ replaceZeroOffsetAsZ,
+ normalizeZoneId,
+ readNumericStringsAsTimestamp
+ );
+ }
+
+ @Override
+ protected T _fromString(JsonParser p, DeserializationContext ctxt, String string0) throws IOException {
+ return super._fromString(p, ctxt, string0.replace( ' ', 'T' ));
+ }
+}
\ No newline at end of file
diff --git a/boat-scaffold/src/main/templates/boat-java/RFC3339JavaTimeModule.mustache b/boat-scaffold/src/main/templates/boat-java/RFC3339JavaTimeModule.mustache
new file mode 100644
index 000000000..6b780cd43
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/RFC3339JavaTimeModule.mustache
@@ -0,0 +1,29 @@
+{{>licenseInfo}}
+package {{invokerPackage}};
+
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZonedDateTime;
+
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.Module.SetupContext;
+
+{{>generatedAnnotation}}
+
+public class RFC3339JavaTimeModule extends SimpleModule {
+ private static final long serialVersionUID = 1L;
+
+ public RFC3339JavaTimeModule() {
+ super("RFC3339JavaTimeModule");
+ }
+
+ @Override
+ public void setupModule(SetupContext context) {
+ super.setupModule(context);
+
+ addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT);
+ addDeserializer(OffsetDateTime.class, RFC3339InstantDeserializer.OFFSET_DATE_TIME);
+ addDeserializer(ZonedDateTime.class, RFC3339InstantDeserializer.ZONED_DATE_TIME);
+ }
+
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache b/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache
index e324da7a8..4c94d0bd0 100644
--- a/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import java.util.Map;
@@ -5,6 +7,8 @@ import java.util.Map;
/**
* Representing a Server configuration.
*/
+{{>generatedAnnotation}}
+
public class ServerConfiguration {
public String URL;
public String description;
@@ -55,4 +59,4 @@ public class ServerConfiguration {
public String URL() {
return URL(null);
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/ServerVariable.mustache b/boat-scaffold/src/main/templates/boat-java/ServerVariable.mustache
index 1978b1eb9..f8261c444 100644
--- a/boat-scaffold/src/main/templates/boat-java/ServerVariable.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/ServerVariable.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import java.util.HashSet;
@@ -5,6 +7,8 @@ import java.util.HashSet;
/**
* Representing a Server Variable for server URL template substitution.
*/
+{{>generatedAnnotation}}
+
public class ServerVariable {
public String description;
public String defaultValue;
diff --git a/boat-scaffold/src/main/templates/boat-java/StringUtil.mustache b/boat-scaffold/src/main/templates/boat-java/StringUtil.mustache
index ce52c8238..31af8371f 100644
--- a/boat-scaffold/src/main/templates/boat-java/StringUtil.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/StringUtil.mustache
@@ -2,7 +2,11 @@
package {{invokerPackage}};
+import java.util.Collection;
+import java.util.Iterator;
+
{{>generatedAnnotation}}
+
public class StringUtil {
/**
* Check if the given array contains the given value (with case-insensitive comparison).
@@ -47,4 +51,23 @@ public class StringUtil {
}
return out.toString();
}
+
+ /**
+ * Join a list of strings with the given separator.
+ *
+ * @param list The list of strings
+ * @param separator The separator
+ * @return the resulting string
+ */
+ public static String join(Collection list, String separator) {
+ Iterator iterator = list.iterator();
+ StringBuilder out = new StringBuilder();
+ if (iterator.hasNext()) {
+ out.append(iterator.next());
+ }
+ while (iterator.hasNext()) {
+ out.append(separator).append(iterator.next());
+ }
+ return out.toString();
+ }
}
diff --git a/boat-scaffold/src/main/templates/boat-java/additionalModelTypeAnnotations.mustache b/boat-scaffold/src/main/templates/boat-java/additionalModelTypeAnnotations.mustache
index e5dc1ac12..f4871c02c 100644
--- a/boat-scaffold/src/main/templates/boat-java/additionalModelTypeAnnotations.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/additionalModelTypeAnnotations.mustache
@@ -1,2 +1,2 @@
-{{#additionalModelTypeAnnotations}}{{.}}
+{{#additionalModelTypeAnnotations}}{{{.}}}
{{/additionalModelTypeAnnotations}}
\ No newline at end of file
diff --git a/boat-scaffold/src/main/templates/boat-java/additional_properties.mustache b/boat-scaffold/src/main/templates/boat-java/additional_properties.mustache
new file mode 100644
index 000000000..04c226bce
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/additional_properties.mustache
@@ -0,0 +1,34 @@
+{{#jackson}}
+{{#additionalPropertiesType}}
+ /**
+ * Set the additional (undeclared) property with the specified name and value.
+ * Creates the property if it does not already exist, otherwise replaces it.
+ * @param key the name of the property
+ * @param value the value of the property
+ * @return self reference
+ */
+ @JsonAnySetter
+ public {{classname}} putAdditionalProperty(String key, {{{.}}} value) {
+ this.put(key, value);
+ return this;
+ }
+
+ /**
+ * Return the additional (undeclared) properties.
+ * @return the additional (undeclared) properties
+ */
+ @JsonAnyGetter
+ public Map getAdditionalProperties() {
+ return this;
+ }
+
+ /**
+ * Return the additional (undeclared) property with the specified name.
+ * @param key the name of the property
+ * @return the additional (undeclared) property with the specified name
+ */
+ public {{{.}}} getAdditionalProperty(String key) {
+ return this.get(key);
+ }
+{{/additionalPropertiesType}}
+{{/jackson}}
diff --git a/boat-scaffold/src/main/templates/boat-java/api.mustache b/boat-scaffold/src/main/templates/boat-java/api.mustache
index 099d41cd2..3cfd92db0 100644
--- a/boat-scaffold/src/main/templates/boat-java/api.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/api.mustache
@@ -13,20 +13,14 @@ import {{invokerPackage}}.Pair;
{{/imports}}
-{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-{{/fullJavaUtil}}
{{>generatedAnnotation}}
+
{{#operations}}
-{{#useBeanValidation}}
-{{#useClassLevelBeanValidation}}
-@Validated
-{{/useClassLevelBeanValidation}}
-{{/useBeanValidation}}
public class {{classname}} {
private ApiClient apiClient;
@@ -51,7 +45,7 @@ public class {{classname}} {
* {{summary}}
* {{notes}}
{{#allParams}}
- * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}}
+ * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
{{/allParams}}
{{#returnType}}
* @return {{.}}
@@ -68,7 +62,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
+ public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException {
Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
{{#allParams}}{{#required}}
// verify the required parameter '{{paramName}}' is set
@@ -81,11 +75,11 @@ public class {{classname}} {
.replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
// query params
- {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList();
- {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList();
- {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap();
- {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap();
- {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap();
+ List localVarQueryParams = new ArrayList();
+ List localVarCollectionQueryParams = new ArrayList();
+ Map localVarHeaderParams = new HashMap();
+ Map localVarCookieParams = new HashMap();
+ Map localVarFormParams = new HashMap();
{{#queryParams}}
{{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{.}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}}));
@@ -124,4 +118,4 @@ public class {{classname}} {
}
{{/operation}}
}
-{{/operations}}
\ No newline at end of file
+{{/operations}}
diff --git a/boat-scaffold/src/main/templates/boat-java/apiException.mustache b/boat-scaffold/src/main/templates/boat-java/apiException.mustache
index 30e171fba..93e28ec89 100644
--- a/boat-scaffold/src/main/templates/boat-java/apiException.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/apiException.mustache
@@ -6,7 +6,10 @@ import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
+
public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{
+ private static final long serialVersionUID = 1L;
+
private int code = 0;
private Map> responseHeaders = null;
private String responseBody = null;
@@ -86,4 +89,4 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us
", responseBody='" + responseBody + '\'' +
'}';
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/api_doc.mustache
index 680095472..3d3203957 100644
--- a/boat-scaffold/src/main/templates/boat-java/api_doc.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/api_doc.mustache
@@ -105,4 +105,4 @@ public class Example {
{{/responses.0}}
{{/operation}}
-{{/operations}}
\ No newline at end of file
+{{/operations}}
diff --git a/boat-scaffold/src/main/templates/boat-java/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/api_test.mustache
index 176be8069..155f46e40 100644
--- a/boat-scaffold/src/main/templates/boat-java/api_test.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/api_test.mustache
@@ -5,23 +5,21 @@ package {{package}};
import {{invokerPackage}}.ApiException;
{{#imports}}import {{import}};
{{/imports}}
-import org.junit.Test;
-import org.junit.Ignore;
-import org.junit.Assert;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.OffsetDateTime;
-{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-{{/fullJavaUtil}}
/**
* API tests for {{classname}}
*/
-public class {{classname}}Test {
+class {{classname}}Test {
private final {{classname}} api = new {{classname}}();
@@ -40,7 +38,7 @@ public class {{classname}}Test {
* if the Api call fails
*/
@Test
- public void {{operationId}}Test() throws ApiException {
+ void {{operationId}}Test() throws ApiException {
//{{#allParams}}
//{{{dataType}}} {{paramName}} = null;
//{{/allParams}}
@@ -50,4 +48,4 @@ public class {{classname}}Test {
}
{{/operation}}
{{/operations}}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/auth/ApiKeyAuth.mustache b/boat-scaffold/src/main/templates/boat-java/auth/ApiKeyAuth.mustache
index 991ae2350..8703bedd3 100644
--- a/boat-scaffold/src/main/templates/boat-java/auth/ApiKeyAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/auth/ApiKeyAuth.mustache
@@ -8,6 +8,7 @@ import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
+
public class ApiKeyAuth implements Authentication {
private final String location;
private final String paramName;
diff --git a/boat-scaffold/src/main/templates/boat-java/auth/Authentication.mustache b/boat-scaffold/src/main/templates/boat-java/auth/Authentication.mustache
index 033de98d5..78bddebaf 100644
--- a/boat-scaffold/src/main/templates/boat-java/auth/Authentication.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/auth/Authentication.mustache
@@ -7,13 +7,15 @@ import {{invokerPackage}}.Pair;
import java.util.Map;
import java.util.List;
+{{>generatedAnnotation}}
+
public interface Authentication {
- /**
- * Apply authentication settings to header and query params.
- *
- * @param queryParams List of query parameters
- * @param headerParams Map of header parameters
- * @param cookieParams Map of cookie parameters
- */
- void applyToParams(List queryParams, Map headerParams, Map cookieParams);
+ /**
+ * Apply authentication settings to header and query params.
+ *
+ * @param queryParams List of query parameters
+ * @param headerParams Map of header parameters
+ * @param cookieParams Map of cookie parameters
+ */
+ void applyToParams(List queryParams, Map headerParams, Map cookieParams);
}
diff --git a/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache
index 9dfe714b5..be2863d62 100644
--- a/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache
@@ -11,6 +11,7 @@ import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
+
public class HttpBasicAuth implements Authentication {
private String username;
private String password;
@@ -39,4 +40,4 @@ public class HttpBasicAuth implements Authentication {
String str = (username == null ? "" : username) + ":" + (password == null ? "" : password);
headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8)));
}
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/auth/HttpBearerAuth.mustache b/boat-scaffold/src/main/templates/boat-java/auth/HttpBearerAuth.mustache
index 322281f87..5290e3fb7 100644
--- a/boat-scaffold/src/main/templates/boat-java/auth/HttpBearerAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/auth/HttpBearerAuth.mustache
@@ -4,16 +4,18 @@ package {{invokerPackage}}.auth;
import {{invokerPackage}}.Pair;
-import java.util.Map;
import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
{{>generatedAnnotation}}
+
public class HttpBearerAuth implements Authentication {
private final String scheme;
- private String bearerToken;
+ private Supplier tokenSupplier;
public HttpBearerAuth(String scheme) {
- this.scheme = scheme;
+ this.scheme = upperCaseBearer(scheme);
}
/**
@@ -22,7 +24,7 @@ public class HttpBearerAuth implements Authentication {
* @return The bearer token
*/
public String getBearerToken() {
- return bearerToken;
+ return tokenSupplier.get();
}
/**
@@ -31,19 +33,28 @@ public class HttpBearerAuth implements Authentication {
* @param bearerToken The bearer token to send in the Authorization header
*/
public void setBearerToken(String bearerToken) {
- this.bearerToken = bearerToken;
+ this.tokenSupplier = () -> bearerToken;
+ }
+
+ /**
+ * Sets the supplier of tokens, which together with the scheme, will be sent as the value of the Authorization header.
+ *
+ * @param tokenSupplier The supplier of bearer tokens to send in the Authorization header
+ */
+ public void setBearerToken(Supplier tokenSupplier) {
+ this.tokenSupplier = tokenSupplier;
}
@Override
public void applyToParams(List queryParams, Map headerParams, Map cookieParams) {
- if(bearerToken == null) {
+ String bearerToken = tokenSupplier != null ? tokenSupplier.get() : null;
+ if (bearerToken == null) {
return;
}
-
- headerParams.put("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken);
+ headerParams.put("Authorization", (scheme != null ? scheme + " " : "") + bearerToken);
}
private static String upperCaseBearer(String scheme) {
- return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme;
+ return "bearer".equalsIgnoreCase(scheme) ? "Bearer" : scheme;
}
}
diff --git a/boat-scaffold/src/main/templates/boat-java/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/auth/OAuth.mustache
index 5cb98e7cb..a500f67cf 100644
--- a/boat-scaffold/src/main/templates/boat-java/auth/OAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/auth/OAuth.mustache
@@ -8,6 +8,7 @@ import java.util.Map;
import java.util.List;
{{>generatedAnnotation}}
+
public class OAuth implements Authentication {
private String accessToken;
diff --git a/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache b/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache
index 3f14c64b1..8dd1cad4e 100644
--- a/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache
@@ -6,9 +6,10 @@ package {{invokerPackage}}.auth;
* OAuth flows that are supported by this client
*/
{{>generatedAnnotation}}
+
public enum OAuthFlow {
ACCESS_CODE, //called authorizationCode in OpenAPI 3.0
IMPLICIT,
PASSWORD,
APPLICATION //called clientCredentials in OpenAPI 3.0
-}
\ No newline at end of file
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache
index 4d3e795a0..d5094224f 100644
--- a/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache
@@ -57,16 +57,16 @@ if(hasProperty('target') && target == 'android') {
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
- task.from variant.javaCompile.destinationDir
- task.destinationDir = project.file("${project.buildDir}/outputs/jar")
- task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
+ task.from variant.javaCompile.destinationDirectory
+ task.destinationDirectory = project.file("${project.buildDir}/outputs/jar")
+ task.archiveFileName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
- classifier = 'sources'
+ archiveClassifier = 'sources'
}
artifacts {
@@ -97,12 +97,12 @@ if(hasProperty('target') && target == 'android') {
}
task sourcesJar(type: Jar, dependsOn: classes) {
- classifier = 'sources'
+ archiveClassifier = 'sources'
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: javadoc) {
- classifier = 'javadoc'
+ archiveClassifier = 'javadoc'
from javadoc.destinationDir
}
@@ -114,15 +114,21 @@ if(hasProperty('target') && target == 'android') {
ext {
swagger_annotations_version = "1.6.3"
- jackson_version = "2.12.6"
- jackson_databind_version = "2.12.6.1"
+ jackson_version = "2.19.2"
+ jackson_databind_version = "2.19.2"
{{#openApiNullable}}
- jackson_databind_nullable_version = "0.2.4"
+ jackson_databind_nullable_version = "0.2.9"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
+ {{#useBeanValidation}}
+ bean_validation_version = "3.0.2"
+ {{/useBeanValidation}}
jersey_version = "1.19.4"
jodatime_version = "2.9.9"
- junit_version = "4.13.2"
+ junit_version = "5.10.2"
+ {{#useReflectionEqualsHashCode}}
+ commons_lang3_version = "3.17.0"
+ {{/useReflectionEqualsHashCode}}
}
dependencies {
@@ -142,5 +148,27 @@ dependencies {
{{/joda}}
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
+ {{#useBeanValidation}}
+ implementation "jakarta.validation:jakarta.validation-api:$bean_validation_version"
+ {{/useBeanValidation}}
+ {{#useReflectionEqualsHashCode}}
+ implementation "org.apache.commons:commons-lang3:$commons_lang3_version"
+ {{/useReflectionEqualsHashCode}}
testImplementation "junit:junit:$junit_version"
-}
\ No newline at end of file
+ testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version"
+ testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version"
+}
+
+test {
+ // Enable JUnit 5 (Gradle 4.6+).
+ useJUnitPlatform()
+
+ // Always run tests, even when nothing changed.
+ dependsOn 'cleanTest'
+
+ // Show test results.
+ testLogging {
+ events "passed", "skipped", "failed"
+ }
+
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache
index b3147c04f..e05689d5f 100644
--- a/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache
@@ -1 +1 @@
-{{^hideGenerationTimestamp}}@{{^useJakartaEe}}javax{{/useJakartaEe}}{{#useJakartaEe}}jakarta{{/useJakartaEe}}.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}}
\ No newline at end of file
+@{{javaxPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}, comments = "Generator version: {{generatorVersion}}")
\ No newline at end of file
diff --git a/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache b/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache
old mode 100755
new mode 100644
index 9ff0e8c65..0e3776ae6
--- a/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache
@@ -54,4 +54,4 @@ git pull origin master
# Pushes (Forces) the changes in the local repository up to the remote repository
echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
-git push origin master 2>&1 | grep -v 'To https'
\ No newline at end of file
+git push origin master 2>&1 | grep -v 'To https'
diff --git a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar
index 7454180f2..e6441136f 100644
Binary files a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar and b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar differ
diff --git a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache
index 7c08e4f06..b82aa23a4 100644
--- a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
\ No newline at end of file
+zipStorePath=wrapper/dists
diff --git a/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache b/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache
index bf46cf4d6..095ab31d1 100644
--- a/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache
@@ -6,4 +6,4 @@
#target = android
{{#gradleProperties}}
{{{.}}}
-{{/gradleProperties}}
\ No newline at end of file
+{{/gradleProperties}}
diff --git a/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache b/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache
index 806627401..25da30dbd 100644
--- a/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -33,20 +34,20 @@ set APP_HOME=%DIRNAME%
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -75,15 +76,17 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
-:omega
\ No newline at end of file
+:omega
diff --git a/boat-scaffold/src/main/templates/boat-java/gradlew.mustache b/boat-scaffold/src/main/templates/boat-java/gradlew.mustache
old mode 100755
new mode 100644
index 1a33e4365..9d0ce634c
--- a/boat-scaffold/src/main/templates/boat-java/gradlew.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/gradlew.mustache
@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -69,37 +69,35 @@ app_path=$0
# Need this for daisy-chained symlinks.
while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
+APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+[ -h "$app_path" ]
do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
+ls=$( ls -ld "$app_path" )
+link=${ls#*' -> '}
+case $link in #(
+/*) app_path=$link ;; #(
+*) app_path=$APP_HOME$link ;;
+esac
done
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-APP_NAME="Gradle"
+# This is normally unused
+# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
- echo "$*"
+echo "$*"
} >&2
die () {
- echo
- echo "$*"
- echo
- exit 1
+echo
+echo "$*"
+echo
+exit 1
} >&2
# OS specific support (must be 'true' or 'false').
@@ -108,10 +106,10 @@ msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
+CYGWIN* ) cygwin=true ;; #(
+Darwin* ) darwin=true ;; #(
+MSYS* | MINGW* ) msys=true ;; #(
+NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -119,39 +117,46 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
- else
- JAVACMD=$JAVA_HOME/bin/java
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+# IBM's JDK on AIX uses strange locations for the executables
+JAVACMD=$JAVA_HOME/jre/sh/java
+else
+JAVACMD=$JAVA_HOME/bin/java
+fi
+if [ ! -x "$JAVACMD" ] ; then
+die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
- fi
+fi
else
- JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+JAVACMD=java
+if ! command -v java >/dev/null 2>&1
+then
+die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
+fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
+case $MAX_FD in #(
+max*)
+# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+# shellcheck disable=SC2039,SC3045
+MAX_FD=$( ulimit -H -n ) ||
+warn "Could not query maximum file descriptor limit"
+esac
+case $MAX_FD in #(
+'' | soft) :;; #(
+*)
+# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+# shellcheck disable=SC2039,SC3045
+ulimit -n "$MAX_FD" ||
+warn "Could not set maximum file descriptor limit to $MAX_FD"
+esac
fi
# Collect all arguments for the java command, stacking in reverse order:
@@ -164,46 +169,56 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
- fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
- done
+APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+# Now convert the arguments - kludge to limit ourselves to /bin/sh
+for arg do
+if
+case $arg in #(
+-*) false ;; # don't mess with options #(
+/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+[ -e "$t" ] ;; #(
+*) false ;;
+esac
+then
+arg=$( cygpath --path --ignore --mixed "$arg" )
+fi
+# Roll the args list around exactly as many times as the number of
+# args, so each arg winds up back in the position where it started, but
+# possibly modified.
+#
+# NB: a `for` loop captures its iteration list before it begins, so
+# changing the positional parameters here affects neither the number of
+# iterations, nor the values presented in `arg`.
+shift # remove old arg
+set -- "$@" "$arg" # push replacement arg
+done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
- "$@"
+"-Dorg.gradle.appname=$APP_BASE_NAME" \
+-classpath "$CLASSPATH" \
+org.gradle.wrapper.GradleWrapperMain \
+"$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+die "xargs is not available"
+fi
# Use "xargs" to parse quoted args.
#
@@ -225,10 +240,10 @@ set -- \
#
eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
+printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+xargs -n1 |
+sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+tr '\n' ' '
+)" '"$@"'
-exec "$JAVACMD" "$@"
\ No newline at end of file
+exec "$JAVACMD" "$@"
diff --git a/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache b/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache
index ccde126f5..08b43352e 100644
--- a/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache
@@ -4,16 +4,11 @@
* If the field is required, always include it, even if it is null.
* Else use custom behaviour, IOW use whatever is defined on the object mapper
}}
- @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
+ @JsonProperty(value = JSON_PROPERTY_{{nameInSnakeCase}}, required = {{#isNullable}}false{{/isNullable}}{{^isNullable}}{{required}}{{/isNullable}})
@JsonInclude({{#isMap}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMap}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}})
- {{#withXml}}
- {{^isContainer}}
- @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}")
- {{/isContainer}}
- {{#isContainer}}
- {{#isXmlWrapped}}
- // items.xmlName={{items.xmlName}}
- @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}")
- {{/isXmlWrapped}}
- {{/isContainer}}
- {{/withXml}}
\ No newline at end of file
+{{#withXml}}
+ @JacksonXmlProperty(localName = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#isXmlAttribute}}, isAttribute = true{{/isXmlAttribute}}{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
+ {{#isContainer}}
+ @JacksonXmlElementWrapper({{#isXmlWrapped}}localName = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}", {{#xmlNamespace}}namespace = "{{.}}", {{/xmlNamespace}}{{/isXmlWrapped}}useWrapping = {{isXmlWrapped}})
+ {{/isContainer}}
+{{/withXml}}
\ No newline at end of file
diff --git a/boat-scaffold/src/main/templates/boat-java/javaBuilder.mustache b/boat-scaffold/src/main/templates/boat-java/javaBuilder.mustache
new file mode 100644
index 000000000..4a0e102b8
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/javaBuilder.mustache
@@ -0,0 +1,82 @@
+public static class Builder {{#parentModel}}extends {{classname}}.Builder {{/parentModel}}{
+
+ private {{classname}} instance;
+
+ public Builder() {
+ this(new {{classname}}());
+ }
+
+ protected Builder({{classname}} instance) {
+ {{#parentModel}}
+ super(instance);
+ {{/parentModel}}
+ this.instance = instance;
+ }
+
+ {{#vars}}
+ public {{classname}}.Builder {{name}}({{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.instance.{{name}} = JsonNullable.<{{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}}>of({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.instance.{{name}} = {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ return this;
+ }
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ public {{classname}}.Builder {{name}}(JsonNullable<{{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}}> {{name}}) {
+ this.instance.{{name}} = {{name}};
+ return this;
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{/vars}}
+
+{{#parentVars}}
+ public {{classname}}.Builder {{name}}({{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}) { // inherited: {{isInherited}}
+ super.{{name}}({{name}});
+ return this;
+ }
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ public {{classname}}.Builder {{name}}(JsonNullable<{{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}}> {{name}}) {
+ this.instance.{{name}} = {{name}};
+ return this;
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{/parentVars}}
+
+ /**
+ * returns a built {{classname}} instance.
+ *
+ * The builder is not reusable.
+ */
+ public {{classname}} build() {
+ try {
+ return this.instance;
+ } finally {
+ // ensure that this.instance is not reused{{#parentModel}}
+ super.build();{{/parentModel}}
+ this.instance = null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass() + "=(" + instance + ")";
+ }
+ }
+
+ /**
+ * Create a builder with no initialized field.
+ */
+ public static {{classname}}.Builder builder() {
+ return new {{classname}}.Builder();
+ }
+
+ /**
+ * Create a builder with a shallow copy of this instance.
+ */
+ public {{classname}}.Builder toBuilder() {
+ return new {{classname}}.Builder(){{#allVars}}
+ .{{name}}({{getter}}()){{/allVars}};
+ }
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache
index 1a07e1cbd..f70c29c21 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache
@@ -8,34 +8,35 @@ import com.fasterxml.jackson.datatype.joda.JodaModule;
{{/joda}}
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.OffsetDateTime;
-import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.NameValuePair;
-import org.apache.http.ParseException;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.RequestBuilder;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.entity.ContentType;
-import org.apache.http.entity.FileEntity;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
-import org.apache.http.impl.client.BasicCookieStore;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.impl.cookie.BasicClientCookie;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.util.EntityUtils;
-import org.apache.http.cookie.Cookie;
+{{#openApiNullable}}
+import org.openapitools.jackson.nullable.JsonNullableModule;
+{{/openApiNullable}}
+
+import org.apache.hc.client5.http.cookie.BasicCookieStore;
+import org.apache.hc.client5.http.cookie.Cookie;
+import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.FileEntity;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
import java.util.Collection;
import java.util.Collections;
@@ -47,6 +48,7 @@ import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
+import java.util.function.Supplier;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -58,6 +60,8 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.Paths;
@@ -81,10 +85,11 @@ import {{invokerPackage}}.auth.OAuth;
{{/hasOAuthMethods}}
{{>generatedAnnotation}}
+
public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
- private Map defaultHeaderMap = new HashMap();
- private Map defaultCookieMap = new HashMap();
- private String basePath = "{{{basePath}}}";
+ protected Map defaultHeaderMap = new HashMap();
+ protected Map defaultCookieMap = new HashMap();
+ protected String basePath = "{{{basePath}}}";
protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
{{/-first}} new ServerConfiguration(
"{{{url}}}",
@@ -112,27 +117,27 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map serverVariables = null;
- private boolean debugging = false;
- private int connectionTimeout = 0;
+ protected boolean debugging = false;
+ protected int connectionTimeout = 0;
- private CloseableHttpClient httpClient;
- private ObjectMapper objectMapper;
+ protected CloseableHttpClient httpClient;
+ protected ObjectMapper objectMapper;
protected String tempFolderPath = null;
- private Map authentications;
+ protected Map authentications;
- private int statusCode;
- private Map> responseHeaders;
+ protected ThreadLocal lastStatusCode = new ThreadLocal<>();
+ protected ThreadLocal
{{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+
+ io.swagger.core.v3
+ swagger-annotations
+ ${swagger-annotations-version}
+
+ {{/swagger2AnnotationLibrary}}
@@ -232,13 +238,8 @@
- org.apache.httpcomponents
- httpclient
- ${httpclient-version}
-
-
- org.apache.httpcomponents
- httpmime
+ org.apache.httpcomponents.client5
+ httpclient5${httpclient-version}
@@ -258,58 +259,67 @@
jackson-databind${jackson-databind-version}
+ {{^useJakartaEe}}
com.fasterxml.jackson.jaxrsjackson-jaxrs-json-provider${jackson-version}
+ {{/useJakartaEe}}
+ {{#useJakartaEe}}
+
+ com.fasterxml.jackson.jakarta.rs
+ jackson-jakarta-rs-json-provider
+ ${jackson-version}
+
+ {{/useJakartaEe}}
{{#withXml}}
-
-
- com.fasterxml.jackson.dataformat
- jackson-dataformat-xml
- ${jackson-version}
-
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ ${jackson-version}
+
{{/withXml}}
{{#joda}}
-
- com.fasterxml.jackson.datatype
- jackson-datatype-joda
- ${jackson-version}
-
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-joda
+ ${jackson-version}
+
{{/joda}}
-
- com.fasterxml.jackson.datatype
- jackson-datatype-jsr310
- ${jackson-version}
-
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson-version}
+
{{#useBeanValidation}}
-
-
- jakarta.validation
- jakarta.validation-api
- ${beanvalidation-version}
- provided
-
+
+
+ jakarta.validation
+ jakarta.validation-api
+ ${beanvalidation-version}
+ provided
+
{{/useBeanValidation}}
{{#performBeanValidation}}
-
-
- org.hibernate
- hibernate-validator
- 5.4.3.Final
-
+
+
+ org.hibernate
+ hibernate-validator
+ 5.4.3.Final
+
{{/performBeanValidation}}
{{#parcelableModel}}
-
-
- com.google.android
- android
- 4.1.1.4
- provided
-
+
+
+ com.google.android
+ android
+ 4.1.1.4
+ provided
+
{{/parcelableModel}}
{{#openApiNullable}}
@@ -326,8 +336,8 @@
- junit
- junit
+ org.junit.jupiter
+ junit-jupiter-api${junit-version}test
@@ -337,16 +347,23 @@
{{#swagger1AnnotationLibrary}}
1.6.6
{{/swagger1AnnotationLibrary}}
- 4.5.13
- 2.14.1
- 2.14.1
+ {{#swagger2AnnotationLibrary}}
+ 2.2.15
+ {{/swagger2AnnotationLibrary}}
+ 5.2.1
+ 2.19.2
+ 2.19.2
{{#openApiNullable}}
- 0.2.4
+ 0.2.9
{{/openApiNullable}}
- 1.3.5
- {{#useBeanValidation}}
+ {{#useJakartaEe}}
+ 2.1.13.0.2
- {{/useBeanValidation}}
- 4.13.2
+ {{/useJakartaEe}}
+ {{^useJakartaEe}}
+ 1.3.5
+ 2.0.2
+ {{/useJakartaEe}}
+ 5.10.2
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache
index cc9599940..3e8a99abd 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache
@@ -1,33 +1,52 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
-import feign.okhttp.OkHttpClient;
-
+{{#jackson}}
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
{{#openApiNullable}}
import org.openapitools.jackson.nullable.JsonNullableModule;
{{/openApiNullable}}
+{{/jackson}}
{{#joda}}
import com.fasterxml.jackson.datatype.joda.JodaModule;
{{/joda}}
+{{#jackson}}
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+{{/jackson}}
import feign.Feign;
import feign.RequestInterceptor;
import feign.form.FormEncoder;
+{{#jackson}}
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
+{{/jackson}}
+{{#gson}}
+import feign.gson.GsonDecoder;
+import feign.gson.GsonEncoder;
+{{/gson}}
+{{#feign-okhttp}}
+import feign.okhttp.OkHttpClient;
+{{/feign-okhttp}}
+{{#feign-hc5}}
+import feign.hc5.ApacheHttp5Client;
+{{/feign-hc5}}
import feign.slf4j.Slf4jLogger;
import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.HttpBearerAuth;
import {{invokerPackage}}.auth.ApiKeyAuth;
+{{#jackson}}
import {{invokerPackage}}.ApiResponseDecoder;
+{{/jackson}}
{{#hasOAuthMethods}}
import {{invokerPackage}}.auth.ApiErrorDecoder;
@@ -40,21 +59,36 @@ import feign.Retryer;
{{/hasOAuthMethods}}
{{>generatedAnnotation}}
+
public class ApiClient {
- private static final Logger log = Logger.getLogger(ApiClient.class.getName());
+ protected static final Logger log = Logger.getLogger(ApiClient.class.getName());
public interface Api {}
+ {{#jackson}}
protected ObjectMapper objectMapper;
- private String basePath = "{{{basePath}}}";
- private Map apiAuthorizations;
- private Feign.Builder feignBuilder;
+ {{/jackson}}
+ protected String basePath = "{{{basePath}}}";
+ protected Map apiAuthorizations;
+ protected Feign.Builder feignBuilder;
+ {{#feign-okhttp}}
+ private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient();
+ {{/feign-okhttp}}
+ {{#feign-hc5}}
+ private static final ApacheHttp5Client APACHE_HTTP5_CLIENT = new ApacheHttp5Client();
+ {{/feign-hc5}}
public ApiClient() {
- objectMapper = createObjectMapper();
apiAuthorizations = new LinkedHashMap();
+ {{#jackson}}
+ objectMapper = createObjectMapper();
feignBuilder = Feign.builder()
- .client(new OkHttpClient())
+ {{#feign-okhttp}}
+ .client(OK_HTTP_CLIENT)
+ {{/feign-okhttp}}
+ {{#feign-hc5}}
+ .client(APACHE_HTTP5_CLIENT)
+ {{/feign-hc5}}
.encoder(new FormEncoder(new JacksonEncoder(objectMapper)))
.decoder(new ApiResponseDecoder(objectMapper))
{{#hasOAuthMethods}}
@@ -62,6 +96,23 @@ public class ApiClient {
.retryer(new Retryer.Default(0, 0, 2))
{{/hasOAuthMethods}}
.logger(new Slf4jLogger());
+ {{/jackson}}
+ {{#gson}}
+ feignBuilder = Feign.builder()
+ {{#feign-okhttp}}
+ .client(OK_HTTP_CLIENT)
+ {{/feign-okhttp}}
+ {{#feign-hc5}}
+ .client(APACHE_HTTP5_CLIENT)
+ {{/feign-hc5}}
+ .encoder(new FormEncoder(new GsonEncoder()))
+ .decoder(new GsonDecoder())
+ {{#hasOAuthMethods}}
+ .errorDecoder(new ApiErrorDecoder())
+ .retryer(new Retryer.Default(0, 0, 2))
+ {{/hasOAuthMethods}}
+ .logger(new Slf4jLogger());
+ {{/gson}}
}
public ApiClient(String[] authNames) {
@@ -69,16 +120,14 @@ public class ApiClient {
for(String authName : authNames) {
log.log(Level.FINE, "Creating authentication {0}", authName);
{{#hasAuthMethods}}
- RequestInterceptor auth;
+ RequestInterceptor auth = null;
{{#authMethods}}if ("{{name}}".equals(authName)) {
- {{#isBasic}}
{{#isBasicBasic}}
auth = new HttpBasicAuth();
{{/isBasicBasic}}
- {{^isBasicBasic}}
+ {{#isBasicBearer}}
auth = new HttpBearerAuth("{{scheme}}");
- {{/isBasicBasic}}
- {{/isBasic}}
+ {{/isBasicBearer}}
{{#isApiKey}}
auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}");
{{/isApiKey}}
@@ -88,7 +137,9 @@ public class ApiClient {
} else {{/authMethods}}{
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");
}
- addAuthorization(authName, auth);
+ if (auth != null) {
+ addAuthorization(authName, auth);
+ }
{{/hasAuthMethods}}
{{^hasAuthMethods}}
throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names");
@@ -140,11 +191,17 @@ public class ApiClient {
return this;
}
- private ObjectMapper createObjectMapper() {
+ {{#jackson}}
+ protected ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
+ {{#failOnUnknownProperties}}
+ objectMapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ {{/failOnUnknownProperties}}
+ {{^failOnUnknownProperties}}
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ {{/failOnUnknownProperties}}
objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setDateFormat(new RFC3339DateFormat());
@@ -152,15 +209,17 @@ public class ApiClient {
objectMapper.registerModule(new JodaModule());
{{/joda}}
objectMapper.registerModule(new JavaTimeModule());
+ objectMapper.registerModule(new RFC3339JavaTimeModule());
{{#openApiNullable}}
JsonNullableModule jnm = new JsonNullableModule();
objectMapper.registerModule(jnm);
{{/openApiNullable}}
return objectMapper;
}
+ {{/jackson}}
{{#hasOAuthMethods}}
- private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
+ protected RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
switch (flow) {
case PASSWORD:
return new OauthPasswordGrant(tokenUrl, scopes);
@@ -172,6 +231,8 @@ public class ApiClient {
}
{{/hasOAuthMethods}}
+
+ {{#jackson}}
public ObjectMapper getObjectMapper(){
return objectMapper;
}
@@ -179,6 +240,7 @@ public class ApiClient {
public void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
+ {{/jackson}}
/**
* Creates a feign client for given API interface.
@@ -235,6 +297,15 @@ public class ApiClient {
apiAuthorization.setBearerToken(bearerToken);
}
+ /**
+ * Helper method to configure the supplier of bearer tokens.
+ * @param tokenSupplier the supplier of bearer tokens.
+ */
+ public void setBearerToken(Supplier tokenSupplier) {
+ HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class);
+ apiAuthorization.setBearerToken(tokenSupplier);
+ }
+
/**
* Helper method to configure the first api key found
* @param apiKey API key
@@ -329,7 +400,7 @@ public class ApiClient {
feignBuilder.requestInterceptor(authorization);
}
- private T getAuthorization(Class type) {
+ protected T getAuthorization(Class type) {
return (T) apiAuthorizations.values()
.stream()
.filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass()))
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache
index 2ff7a3243..7eaf68cea 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -5,34 +7,99 @@ import feign.Response;
import feign.Types;
import feign.jackson.JacksonDecoder;
+import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import {{modelPackage}}.ApiResponse;
public class ApiResponseDecoder extends JacksonDecoder {
+ private static final Pattern FILENAME_PATTERN =
+ Pattern.compile("filename=\"([^\"]+)\"|filename=([^\\s;]+)");
+
public ApiResponseDecoder(ObjectMapper mapper) {
super(mapper);
}
@Override
public Object decode(Response response, Type type) throws IOException {
- Map> responseHeaders = Collections.unmodifiableMap(response.headers());
- //Detects if the type is an instance of the parameterized class ApiResponse
- Type responseBodyType;
if (type instanceof ParameterizedType && Types.getRawType(type).isAssignableFrom(ApiResponse.class)) {
- //The ApiResponse class has a single type parameter, the Dto class itself
- responseBodyType = ((ParameterizedType) type).getActualTypeArguments()[0];
- Object body = super.decode(response, responseBodyType);
- return new ApiResponse(response.status(), responseHeaders, body);
+ Type responseBodyType = ((ParameterizedType) type).getActualTypeArguments()[0];
+ Object body = isBinaryType(responseBodyType)
+ ? decodeBinary(response, responseBodyType)
+ : super.decode(response, responseBodyType);
+ Map> responseHeaders = Collections.unmodifiableMap(response.headers());
+ return new ApiResponse<>(response.status(), responseHeaders, body);
+ }
+
+ if (isBinaryType(type)) {
+ return decodeBinary(response, type);
+ }
+
+ return super.decode(response, type);
+ }
+
+ private boolean isBinaryType(Type type) {
+ Class> raw = Types.getRawType(type);
+ return File.class.isAssignableFrom(raw)
+ || byte[].class.isAssignableFrom(raw)
+ || InputStream.class.isAssignableFrom(raw);
+ }
+
+ private Object decodeBinary(Response response, Type type) throws IOException {
+ Class> raw = Types.getRawType(type);
+ if (response.body() == null) {
+ return null;
+ }
+ if (byte[].class.isAssignableFrom(raw)) {
+ return response.body().asInputStream().readAllBytes();
+ }
+ if (InputStream.class.isAssignableFrom(raw)) {
+ return response.body().asInputStream();
+ }
+ return downloadToTempFile(response);
+ }
+
+ private File downloadToTempFile(Response response) throws IOException {
+ String filename = extractFilename(response);
+ File file;
+ if (filename != null) {
+ // Sanitize: strip path components to prevent path traversal
+ String safeName = Paths.get(filename).getFileName().toString();
+ java.nio.file.Path tempDir = Files.createTempDirectory("feign-download");
+ file = Files.createFile(tempDir.resolve(safeName)).toFile();
+ tempDir.toFile().deleteOnExit();
} else {
- //The response is not encapsulated in the ApiResponse, decode the Dto as normal
- return super.decode(response, type);
+ file = Files.createTempFile("download-", "").toFile();
+ }
+ file.deleteOnExit();
+ try (InputStream is = response.body().asInputStream()) {
+ Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+ return file;
+ }
+
+ private String extractFilename(Response response) {
+ Collection dispositions = response.headers().get("Content-Disposition");
+ if (dispositions == null) return null;
+ for (String disposition : dispositions) {
+ Matcher m = FILENAME_PATTERN.matcher(disposition);
+ if (m.find()) {
+ // Group 1: quoted filename (may contain spaces), Group 2: unquoted token
+ return m.group(1) != null ? m.group(1) : m.group(2);
+ }
}
+ return null;
}
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/EncodingUtils.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/EncodingUtils.mustache
index 705eb6aa9..2312fc631 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/EncodingUtils.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/EncodingUtils.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import java.io.UnsupportedEncodingException;
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ParamExpander.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ParamExpander.mustache
index 2f5095d00..88f0ae22c 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ParamExpander.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ParamExpander.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import feign.Param;
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache
index fed3cbebd..c3d948749 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache
@@ -32,7 +32,7 @@ After the client library is installed/deployed, you can use it in your Maven pro
```
-And to use the api you can follow the examples bellow:
+And to use the api you can follow the examples below:
```java
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/additional_properties.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/additional_properties.mustache
new file mode 100644
index 000000000..8e7182792
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/additional_properties.mustache
@@ -0,0 +1,45 @@
+{{#additionalPropertiesType}}
+ /**
+ * A container for additional, undeclared properties.
+ * This is a holder for any undeclared properties as specified with
+ * the 'additionalProperties' keyword in the OAS document.
+ */
+ private Map additionalProperties;
+
+ /**
+ * Set the additional (undeclared) property with the specified name and value.
+ * If the property does not already exist, create it otherwise replace it.
+ * @param key the name of the property
+ * @param value the value of the property
+ * @return self reference
+ */
+ @JsonAnySetter
+ public {{classname}} putAdditionalProperty(String key, {{{.}}} value) {
+ if (this.additionalProperties == null) {
+ this.additionalProperties = new HashMap();
+ }
+ this.additionalProperties.put(key, value);
+ return this;
+ }
+
+ /**
+ * Return the additional (undeclared) properties.
+ * @return the additional (undeclared) properties
+ */
+ @JsonAnyGetter
+ public Map getAdditionalProperties() {
+ return additionalProperties;
+ }
+
+ /**
+ * Return the additional (undeclared) property with the specified name.
+ * @param key the name of the property
+ * @return the additional (undeclared) property with the specified name
+ */
+ public {{{.}}} getAdditionalProperty(String key) {
+ if (this.additionalProperties == null) {
+ return null;
+ }
+ return this.additionalProperties.get(key);
+ }
+{{/additionalPropertiesType}}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache
index d7789e6fe..0ec95e7a8 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache
@@ -10,15 +10,19 @@ import {{modelPackage}}.ApiResponse;
{{#imports}}import {{import}};
{{/imports}}
-{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-{{/fullJavaUtil}}
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+
+{{/useBeanValidation}}
import feign.*;
{{>generatedAnnotation}}
+
public interface {{classname}} extends ApiClient.Api {
{{#operations}}{{#operation}}
@@ -44,12 +48,12 @@ public interface {{classname}} extends ApiClient.Api {
{{/isDeprecated}}
@RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}")
@Headers({
-{{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}",
-{{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}}
+{{#vendorExtensions.x-content-type}} "Content-Type: {{{vendorExtensions.x-content-type}}}",
+{{/vendorExtensions.x-content-type}} "Accept: {{#vendorExtensions.x-accepts}}{{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-accepts}}",{{#headerParams}}
"{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}},
{{/-last}}{{/headerParams}}
})
- {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
/**
* {{summary}}
@@ -74,12 +78,12 @@ public interface {{classname}} extends ApiClient.Api {
{{/isDeprecated}}
@RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}")
@Headers({
-{{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}",
-{{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}}
+{{#vendorExtensions.x-content-type}} "Content-Type: {{{vendorExtensions.x-content-type}}}",
+{{/vendorExtensions.x-content-type}} "Accept: {{#vendorExtensions.x-accepts}}{{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-accepts}}",{{#headerParams}}
"{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}},
{{/-last}}{{/headerParams}}
})
- ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}WithHttpInfo({{#allParams}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}WithHttpInfo({{#allParams}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
{{#hasQueryParams}}
@@ -119,12 +123,12 @@ public interface {{classname}} extends ApiClient.Api {
{{/isDeprecated}}
@RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}")
@Headers({
-{{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}",
-{{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}}
+{{#vendorExtensions.x-content-type}} "Content-Type: {{{vendorExtensions.x-content-type}}}",
+{{/vendorExtensions.x-content-type}} "Accept: {{#vendorExtensions.x-accepts}}{{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-accepts}}",{{#headerParams}}
"{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}},
{{/-last}}{{/headerParams}}
})
- {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams);
+ {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) {{operationIdCamelCase}}QueryParams queryParams);
/**
* {{summary}}
@@ -159,12 +163,12 @@ public interface {{classname}} extends ApiClient.Api {
{{/isDeprecated}}
@RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}")
@Headers({
- {{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}",
- {{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}}
+ {{#vendorExtensions.x-content-type}} "Content-Type: {{{vendorExtensions.x-content-type}}}",
+ {{/vendorExtensions.x-content-type}} "Accept: {{#vendorExtensions.x-accepts}}{{{.}}}{{^-last}},{{/-last}}{{/vendorExtensions.x-accepts}}",{{#headerParams}}
"{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}},
{{/-last}}{{/headerParams}}
})
- ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}WithHttpInfo({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams);
+ ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}WithHttpInfo({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) {{operationIdCamelCase}}QueryParams queryParams);
/**
@@ -173,7 +177,7 @@ public interface {{classname}} extends ApiClient.Api {
*/
public static class {{operationIdCamelCase}}QueryParams extends HashMap {
{{#queryParams}}
- public {{operationIdCamelCase}}QueryParams {{paramName}}(final {{{dataType}}} value) {
+ public {{operationIdCamelCase}}QueryParams {{paramName}}({{>nullable_var_annotations}} final {{{dataType}}} value) {
{{#collectionFormat}}
put("{{baseName}}", EncodingUtils.encodeCollection(value, "{{collectionFormat}}"));
{{/collectionFormat}}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache
index c579a5c9d..62521123f 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache
@@ -8,13 +8,16 @@ import org.junit.jupiter.api.BeforeEach;
import java.time.LocalDate;
import java.time.OffsetDateTime;
-{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-{{/fullJavaUtil}}
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+
+{{/useBeanValidation}}
/**
* API tests for {{classname}}
*/
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache
index da87f2563..aeea7f97e 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache
@@ -1,5 +1,9 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
+import java.util.Date;
+
import feign.Response;
import feign.RetryableException;
import feign.codec.ErrorDecoder;
@@ -18,7 +22,7 @@ public class ApiErrorDecoder implements ErrorDecoder {
Exception httpException = defaultErrorDecoder.decode(methodKey, response);
if (response.status() == 401 || response.status() == 403) {
return new RetryableException(response.status(), "Received status " + response.status() + " trying to renew access token",
- response.request().httpMethod(), httpException, null, response.request());
+ response.request().httpMethod(), httpException, (Date) null, response.request());
}
return httpException;
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiKeyAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiKeyAuth.mustache
index c03fe5c0b..4a8da9e53 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiKeyAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiKeyAuth.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import feign.RequestInterceptor;
@@ -37,7 +39,7 @@ public class ApiKeyAuth implements RequestInterceptor {
} else if ("header".equals(location)) {
template.header(paramName, apiKey);
} else if ("cookie".equals(location)) {
- template.header("Cookie", String.format("%s=%s", paramName, apiKey));
+ template.header("Cookie", String.format(java.util.Locale.ROOT, "%s=%s", paramName, apiKey));
}
}
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache
index 72b0a0049..9fee98bd0 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import com.github.scribejava.core.builder.api.DefaultApi20;
@@ -10,6 +12,7 @@ import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthenticati
import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme;
{{>generatedAnnotation}}
+
public class DefaultApi20Impl extends DefaultApi20 {
private final String accessTokenEndpoint;
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache
index c308131e8..d95589b6f 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import feign.RequestInterceptor;
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBearerAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBearerAuth.mustache
index 2240a5518..466c1b2ad 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBearerAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBearerAuth.mustache
@@ -1,14 +1,18 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import feign.RequestInterceptor;
import feign.RequestTemplate;
+import java.util.Optional;
+import java.util.function.Supplier;
/**
* An interceptor that adds the request header needed to use HTTP bearer authentication.
*/
public class HttpBearerAuth implements RequestInterceptor {
private final String scheme;
- private String bearerToken;
+ private Supplier tokenSupplier;
public HttpBearerAuth(String scheme) {
this.scheme = scheme;
@@ -16,21 +20,35 @@ public class HttpBearerAuth implements RequestInterceptor {
/**
* Gets the token, which together with the scheme, will be sent as the value of the Authorization header.
+ *
+ * @return The bearer token
*/
public String getBearerToken() {
- return bearerToken;
+ return tokenSupplier.get();
}
/**
* Sets the token, which together with the scheme, will be sent as the value of the Authorization header.
+ *
+ * @param bearerToken The bearer token to send in the Authorization header
*/
public void setBearerToken(String bearerToken) {
- this.bearerToken = bearerToken;
+ this.tokenSupplier = () -> bearerToken;
+ }
+
+ /**
+ * Sets the supplier of tokens, which together with the scheme, will be sent as the value of the Authorization header.
+ *
+ * @param tokenSupplier The supplier of bearer tokens to send in the Authorization header
+ */
+ public void setBearerToken(Supplier tokenSupplier) {
+ this.tokenSupplier = tokenSupplier;
}
@Override
public void apply(RequestTemplate template) {
- if(bearerToken == null) {
+ String bearerToken = Optional.ofNullable(tokenSupplier).map(Supplier::get).orElse(null);
+ if (bearerToken == null) {
return;
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache
index 5416da238..1baa48c1a 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import com.github.scribejava.core.model.OAuth2AccessToken;
@@ -8,6 +10,7 @@ import feign.RequestTemplate;
import java.util.Collection;
{{>generatedAnnotation}}
+
public abstract class OAuth implements RequestInterceptor {
//https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache
index 2180273d0..95a6195a9 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache
@@ -1,9 +1,12 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth2AccessToken;
{{>generatedAnnotation}}
+
public class OauthClientCredentialsGrant extends OAuth {
public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) {
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache
index 522afa08e..cc3ceb8ef 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache
@@ -1,9 +1,12 @@
+{{>licenseInfo}}
+
package {{invokerPackage}}.auth;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth2AccessToken;
{{>generatedAnnotation}}
+
public class OauthPasswordGrant extends OAuth {
private String username;
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache
index bb35f8689..4186e0a0f 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache
@@ -57,9 +57,9 @@ if(hasProperty('target') && target == 'android') {
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
- task.from variant.javaCompile.destinationDir
- task.destinationDir = project.file("${project.buildDir}/outputs/jar")
- task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
+ task.from variant.javaCompile.destinationDirectory
+ task.destinationDirectory = project.file("${project.buildDir}/outputs/jar")
+ task.archiveFileName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
@@ -101,46 +101,63 @@ test {
}
ext {
- swagger_annotations_version = "1.5.24"
- jackson_version = "2.13.4"
- jackson_databind_version = "2.13.4.2"
+ swagger_annotations_version = "1.6.11"
+ {{#jackson}}
+ jackson_version = "2.19.2"
+ jackson_databind_version = "2.19.2"
+ {{/jackson}}
{{#openApiNullable}}
- jackson_databind_nullable_version = "0.2.4"
+ jackson_databind_nullable_version = "0.2.9"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
- feign_version = "10.11"
+ feign_version = "13.5"
feign_form_version = "3.8.0"
junit_version = "5.7.0"
scribejava_version = "8.0.0"
+ {{#useReflectionEqualsHashCode}}
+ commons_lang3_version = "3.17.0"
+ {{/useReflectionEqualsHashCode}}
}
dependencies {
implementation "io.swagger:swagger-annotations:$swagger_annotations_version"
implementation "com.google.code.findbugs:jsr305:3.0.2"
implementation "io.github.openfeign:feign-core:$feign_version"
+ {{#jackson}}
implementation "io.github.openfeign:feign-jackson:$feign_version"
+ {{/jackson}}
implementation "io.github.openfeign:feign-slf4j:$feign_version"
+ {{#feign-okhttp}}
implementation "io.github.openfeign:feign-okhttp:$feign_version"
+ {{/feign-okhttp}}
+ {{#feign-hc5}}
+ implementation "io.github.openfeign:feign-hc5:$feign_version"
+ {{/feign-hc5}}
implementation "io.github.openfeign.form:feign-form:$feign_form_version"
+ {{#jackson}}
+ {{#joda}}
+ implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version"
+ {{/joda}}
implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
+ implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
+ {{/jackson}}
{{#openApiNullable}}
implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version"
{{/openApiNullable}}
- {{#joda}}
- implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version"
- {{/joda}}
- implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
implementation "com.brsanthu:migbase64:2.2"
implementation "com.github.scribejava:scribejava-core:$scribejava_version"
implementation "com.brsanthu:migbase64:2.2"
implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"
+ {{#useReflectionEqualsHashCode}}
+ implementation "org.apache.commons:commons-lang3:$commons_lang3_version"
+ {{/useReflectionEqualsHashCode}}
testImplementation "org.junit.jupiter:junit-jupiter:$junit_version"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version"
testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version"
- testImplementation "com.github.tomakehurst:wiremock-jre8:2.27.2"
+ testImplementation "com.github.tomakehurst:wiremock-jre8:2.35.1"
testImplementation "org.hamcrest:hamcrest:2.2"
- testImplementation "commons-io:commons-io:2.8.0"
+ testImplementation "commons-io:commons-io:2.16.1"
testImplementation "ch.qos.logback:logback-classic:1.2.3"
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache
index da07dcf61..ca859f159 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache
@@ -3,32 +3,44 @@ lazy val root = (project in file(".")).
organization := "{{groupId}}",
name := "{{artifactId}}",
version := "{{artifactVersion}}",
- scalaVersion := "2.11.4",
+ scalaVersion := "2.11.12",
scalacOptions ++= Seq("-feature"),
- javacOptions in compile ++= Seq("-Xlint:deprecation"),
- publishArtifact in (Compile, packageDoc) := false,
+ compile / javacOptions ++= Seq("-Xlint:deprecation"),
+ Compile / packageDoc / publishArtifact := false,
resolvers += Resolver.mavenLocal,
libraryDependencies ++= Seq(
- "io.swagger" % "swagger-annotations" % "1.5.24" % "compile",
+ "io.swagger" % "swagger-annotations" % "1.6.11" % "compile",
"com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile",
- "io.github.openfeign" % "feign-core" % "10.11" % "compile",
- "io.github.openfeign" % "feign-jackson" % "10.11" % "compile",
- "io.github.openfeign" % "feign-slf4j" % "10.11" % "compile",
+ "io.github.openfeign" % "feign-core" % "13.5" % "compile",
+{{#jackson}}
+ "io.github.openfeign" % "feign-jackson" % "13.5" % "compile",
+{{/jackson}}
+ "io.github.openfeign" % "feign-slf4j" % "13.5" % "compile",
"io.github.openfeign.form" % "feign-form" % "3.8.0" % "compile",
- "io.github.openfeign" % "feign-okhttp" % "10.11" % "compile",
- "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4" % "compile",
- "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.4" % "compile",
- "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2" % "compile",
- "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile",
- "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile",
+{{#feign-okhttp}}
+ "io.github.openfeign" % "feign-okhttp" % "13.5" % "compile",
+{{/feign-okhttp}}
+{{#feign-hc5}}
+ "io.github.openfeign" % "feign-hc5" % "13.5" % "compile",
+{{/feign-hc5}}
+{{#jackson}}
+ "com.fasterxml.jackson.core" % "jackson-core" % "2.17.1" % "compile",
+ "com.fasterxml.jackson.core" % "jackson-annotations" % "2.17.1" % "compile",
+ "com.fasterxml.jackson.core" % "jackson-databind" % "2.17.1" % "compile",
+ "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.17.1" % "compile",
+ "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.15.2" % "compile",
+{{/jackson}}
"com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile",
"com.brsanthu" % "migbase64" % "2.2" % "compile",
"jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile",
+{{#useReflectionEqualsHashCode}}
+ "org.apache.commons" % "commons-lang3" % "3.17.0" % "compile",
+{{/useReflectionEqualsHashCode}}
"org.junit.jupiter" % "junit-jupiter" % "5.7.0" % "test",
"org.junit.jupiter" % "junit-jupiter-params" % "5.7.0" % "test",
- "com.github.tomakehurst" % "wiremock-jre8" % "2.27.2" % "test",
+ "com.github.tomakehurst" % "wiremock-jre8" % "2.35.1" % "test",
"org.hamcrest" % "hamcrest" % "2.2" % "test",
- "commons-io" % "commons-io" % "2.8.0" % "test",
+ "commons-io" % "commons-io" % "2.16.1" % "test",
"com.novocode" % "junit-interface" % "0.10" % "test"
)
)
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model.mustache
new file mode 100644
index 000000000..108748f60
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model.mustache
@@ -0,0 +1,78 @@
+{{>licenseInfo}}
+
+package {{package}};
+
+{{#useReflectionEqualsHashCode}}
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+{{/useReflectionEqualsHashCode}}
+{{#models}}
+{{#model}}
+{{#additionalPropertiesType}}
+import java.util.Map;
+import java.util.HashMap;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+{{/additionalPropertiesType}}
+{{/model}}
+{{/models}}
+import java.util.Objects;
+import java.util.Arrays;
+{{#imports}}
+import {{import}};
+{{/imports}}
+{{#serializableModel}}
+import java.io.Serializable;
+{{/serializableModel}}
+{{#jackson}}
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+{{#withXml}}
+import com.fasterxml.jackson.dataformat.xml.annotation.*;
+{{/withXml}}
+{{#vendorExtensions.x-has-readonly-properties}}
+import com.fasterxml.jackson.annotation.JsonCreator;
+{{/vendorExtensions.x-has-readonly-properties}}
+{{/jackson}}
+{{#withXml}}
+import {{javaxPackage}}.xml.bind.annotation.*;
+import {{javaxPackage}}.xml.bind.annotation.adapters.*;
+import io.github.threetenjaxb.core.*;
+{{/withXml}}
+{{#jsonb}}
+import java.lang.reflect.Type;
+import {{javaxPackage}}.json.bind.annotation.JsonbTypeDeserializer;
+import {{javaxPackage}}.json.bind.annotation.JsonbTypeSerializer;
+import {{javaxPackage}}.json.bind.serializer.DeserializationContext;
+import {{javaxPackage}}.json.bind.serializer.JsonbDeserializer;
+import {{javaxPackage}}.json.bind.serializer.JsonbSerializer;
+import {{javaxPackage}}.json.bind.serializer.SerializationContext;
+import {{javaxPackage}}.json.stream.JsonGenerator;
+import {{javaxPackage}}.json.stream.JsonParser;
+import {{javaxPackage}}.json.bind.annotation.JsonbProperty;
+{{#vendorExtensions.x-has-readonly-properties}}
+import {{javaxPackage}}.json.bind.annotation.JsonbCreator;
+{{/vendorExtensions.x-has-readonly-properties}}
+{{/jsonb}}
+{{#parcelableModel}}
+import android.os.Parcelable;
+import android.os.Parcel;
+{{/parcelableModel}}
+{{#useBeanValidation}}
+import {{javaxPackage}}.validation.constraints.*;
+import {{javaxPackage}}.validation.Valid;
+{{/useBeanValidation}}
+{{#performBeanValidation}}
+import org.hibernate.validator.constraints.*;
+{{/performBeanValidation}}
+{{#supportUrlQuery}}
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.StringJoiner;
+{{/supportUrlQuery}}
+
+{{#models}}
+{{#model}}
+{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache
index bc460dc59..9c9b10746 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache
@@ -1,19 +1,21 @@
+{{>licenseInfo}}
+
package {{modelPackage}};
import java.util.Map;
-import java.util.List;
+import java.util.Collection;
public class ApiResponse{
final private int statusCode;
- final private Map> headers;
+ final private Map> headers;
final private T data;
/**
* @param statusCode The status code of HTTP response
* @param headers The headers of HTTP response
*/
- public ApiResponse(int statusCode, Map> headers) {
+ public ApiResponse(int statusCode, Map> headers) {
this(statusCode, headers, null);
}
@@ -22,7 +24,7 @@ public class ApiResponse{
* @param headers The headers of HTTP response
* @param data The object deserialized from response bod
*/
- public ApiResponse(int statusCode, Map> headers, T data) {
+ public ApiResponse(int statusCode, Map> headers, T data) {
this.statusCode = statusCode;
this.headers = headers;
this.data = data;
@@ -32,7 +34,7 @@ public class ApiResponse{
return statusCode;
}
- public Map> getHeaders() {
+ public Map> getHeaders() {
return headers;
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache
index 0d75e120b..2759ff525 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache
@@ -6,13 +6,6 @@ package {{package}};
{{/imports}}
import org.junit.jupiter.api.Test;
-{{#fullJavaUtil}}
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-{{/fullJavaUtil}}
-
/**
* Model tests for {{classname}}
*/
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/pojo.mustache
new file mode 100644
index 000000000..515b37835
--- /dev/null
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/pojo.mustache
@@ -0,0 +1,580 @@
+/**
+ * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}}
+ * @deprecated{{/isDeprecated}}
+ */{{#isDeprecated}}
+@Deprecated{{/isDeprecated}}
+{{#swagger1AnnotationLibrary}}
+{{#description}}
+@ApiModel(description = "{{{.}}}")
+{{/description}}
+{{/swagger1AnnotationLibrary}}
+{{#jackson}}
+@JsonPropertyOrder({
+{{#vars}}
+ {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
+{{/vars}}
+})
+{{#isClassnameSanitized}}
+{{^hasDiscriminatorWithNonEmptyMapping}}
+@JsonTypeName("{{name}}")
+{{/hasDiscriminatorWithNonEmptyMapping}}
+{{/isClassnameSanitized}}
+{{/jackson}}
+{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
+{{#vendorExtensions.x-class-extra-annotation}}
+{{{vendorExtensions.x-class-extra-annotation}}}
+{{/vendorExtensions.x-class-extra-annotation}}
+public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{
+{{#serializableModel}}
+ private static final long serialVersionUID = 1L;
+
+{{/serializableModel}}
+ {{#vars}}
+ {{#isEnum}}
+ {{^isContainer}}
+{{>modelInnerEnum}}
+
+ {{/isContainer}}
+ {{#isContainer}}
+ {{#mostInnerItems}}
+{{>modelInnerEnum}}
+
+ {{/mostInnerItems}}
+ {{/isContainer}}
+ {{/isEnum}}
+ {{#gson}}
+ public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/gson}}
+ {{#jackson}}
+ public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
+ {{/jackson}}
+ {{#withXml}}
+ @Xml{{#isXmlAttribute}}Attribute{{/isXmlAttribute}}{{^isXmlAttribute}}Element{{/isXmlAttribute}}(name = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
+ {{#isXmlWrapped}}
+ @XmlElementWrapper(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
+ {{/isXmlWrapped}}
+ {{^isXmlAttribute}}
+ {{#isDateTime}}
+ @XmlJavaTypeAdapter(OffsetDateTimeXmlAdapter.class)
+ {{/isDateTime}}
+ {{/isXmlAttribute}}
+ {{/withXml}}
+ {{#gson}}
+ @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}})
+ {{/gson}}
+ {{#vendorExtensions.x-field-extra-annotation}}
+ {{{.}}}
+ {{/vendorExtensions.x-field-extra-annotation}}
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{#isContainer}}
+ private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
+ {{/isContainer}}
+ {{^isContainer}}
+ private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
+ {{/isContainer}}
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ {{>nullable_var_annotations}}{{! prevent indent}}
+ {{#isContainer}}
+ private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
+ {{/isContainer}}
+ {{^isContainer}}
+ {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
+ {{/isContainer}}
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{/vars}}
+ public {{classname}}() {
+ {{#parent}}
+ {{#parcelableModel}}
+ super();{{/parcelableModel}}
+ {{/parent}}
+ {{#gson}}
+ {{#discriminator}}
+ {{#discriminator.isEnum}}
+ this.{{{discriminatorName}}} = this.getClass().getSimpleName();
+ {{/discriminator.isEnum}}
+ {{/discriminator}}
+ {{/gson}}
+ }
+ {{#vendorExtensions.x-has-readonly-properties}}
+ {{^withXml}}
+
+ {{#jsonb}}@JsonbCreator{{/jsonb}}{{#jackson}}@JsonCreator{{/jackson}}
+ public {{classname}}(
+ {{#readOnlyVars}}
+ {{#jsonb}}@JsonbProperty(value = "{{baseName}}"{{^required}}, nullable = true{{/required}}){{/jsonb}}{{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}
+ {{/readOnlyVars}}
+ ) {
+ this();
+ {{#readOnlyVars}}
+ this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}};
+ {{/readOnlyVars}}
+ }
+ {{/withXml}}
+ {{/vendorExtensions.x-has-readonly-properties}}
+ {{#vars}}
+
+ {{^isReadOnly}}
+ public {{classname}} {{name}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}}
+ return this;
+ }
+ {{#isArray}}
+
+ public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null || !this.{{name}}.isPresent()) {
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}});
+ }
+ try {
+ this.{{name}}.get().add({{name}}Item);
+ } catch (java.util.NoSuchElementException e) {
+ // this can never happen, as we make sure above that the value is present
+ }
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
+ }
+ this.{{name}}.add({{name}}Item);
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isArray}}
+ {{#isMap}}
+
+ public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ if (this.{{name}} == null || !this.{{name}}.isPresent()) {
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}});
+ }
+ try {
+ this.{{name}}.get().put(key, {{name}}Item);
+ } catch (java.util.NoSuchElementException e) {
+ // this can never happen, as we make sure above that the value is present
+ }
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^required}}
+ if (this.{{name}} == null) {
+ this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
+ }
+ {{/required}}
+ this.{{name}}.put(key, {{name}}Item);
+ return this;
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isMap}}
+
+ {{/isReadOnly}}
+ /**
+ {{#description}}
+ * {{.}}
+ {{/description}}
+ {{^description}}
+ * Get {{name}}
+ {{/description}}
+ {{#minimum}}
+ * minimum: {{.}}
+ {{/minimum}}
+ {{#maximum}}
+ * maximum: {{.}}
+ {{/maximum}}
+ * @return {{name}}
+ {{#deprecated}}
+ * @deprecated
+ {{/deprecated}}
+ */
+{{#deprecated}}
+ @Deprecated
+{{/deprecated}}
+ {{>nullable_var_annotations}}{{! prevent indent}}
+{{#jsonb}}
+ @JsonbProperty("{{baseName}}")
+{{/jsonb}}
+{{#useBeanValidation}}
+{{>beanValidation}}
+
+{{/useBeanValidation}}
+{{#swagger1AnnotationLibrary}}
+ @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
+{{/swagger1AnnotationLibrary}}
+{{#vendorExtensions.x-extra-annotation}}
+ {{{vendorExtensions.x-extra-annotation}}}
+{{/vendorExtensions.x-extra-annotation}}
+{{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
+ @JsonIgnore
+{{/vendorExtensions.x-is-jackson-optional-nullable}}
+{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}}
+ public {{{datatypeWithEnum}}} {{getter}}() {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}}
+ if ({{name}} == null) {
+ {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
+ }
+ {{/isReadOnly}}
+ return {{name}}.orElse(null);
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ return {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+{{> jackson_annotations}}
+
+ public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
+ return {{name}};
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}}
+ @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}})
+ {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
+ {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}
+ this.{{name}} = {{name}};
+ }
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+
+ {{^isReadOnly}}
+{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
+{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
+ {{#vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ {{^vendorExtensions.x-is-jackson-optional-nullable}}
+ this.{{name}} = {{name}};
+ {{/vendorExtensions.x-is-jackson-optional-nullable}}
+ }
+ {{/isReadOnly}}
+
+ {{/vars}}
+{{>libraries/feign/additional_properties}}
+
+ @Override
+ public boolean equals(Object o) {
+ {{#useReflectionEqualsHashCode}}
+ return EqualsBuilder.reflectionEquals(this, o, false, null, true);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }{{#hasVars}}
+ {{classname}} {{classVarName}} = ({{classname}}) o;
+ return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} &&
+ {{/-last}}{{/vars}}{{#additionalPropertiesType}} &&
+ Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} &&
+ super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}}
+ return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}}
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static boolean equalsNullable(JsonNullable a, JsonNullable b) {
+ return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public int hashCode() {
+ {{#useReflectionEqualsHashCode}}
+ return HashCodeBuilder.reflectionHashCode(this);
+ {{/useReflectionEqualsHashCode}}
+ {{^useReflectionEqualsHashCode}}
+ return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}});
+ {{/useReflectionEqualsHashCode}}
+ }{{#vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ private static int hashCodeNullable(JsonNullable a) {
+ if (a == null) {
+ return 1;
+ }
+ return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
+ }{{/vendorExtensions.x-jackson-optional-nullable-helpers}}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("class {{classname}} {\n");
+ {{#parent}}
+ sb.append(" ").append(toIndentedString(super.toString())).append("\n");
+ {{/parent}}
+ {{#vars}}
+ sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
+ {{/vars}}
+ {{#additionalPropertiesType}}
+ sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
+ {{/additionalPropertiesType}}
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Convert the given object to string with each line indented by 4 spaces
+ * (except the first line).
+ */
+ private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) {
+ if (o == null) {
+ return "null";
+ }
+ return o.toString().replace("\n", "\n ");
+ }
+{{#supportUrlQuery}}
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @return URL query string
+ */
+ public String toUrlQueryString() {
+ return toUrlQueryString(null);
+ }
+
+ /**
+ * Convert the instance into URL query string.
+ *
+ * @param prefix prefix of the query string
+ * @return URL query string
+ */
+ public String toUrlQueryString(String prefix) {
+ String suffix = "";
+ String containerSuffix = "";
+ String containerPrefix = "";
+ if (prefix == null) {
+ // style=form, explode=true, e.g. /pet?name=cat&type=manx
+ prefix = "";
+ } else {
+ // deepObject style e.g. /pet?id[name]=cat&id[type]=manx
+ prefix = prefix + "[";
+ suffix = "]";
+ containerSuffix = "]";
+ containerPrefix = "[";
+ }
+
+ StringJoiner joiner = new StringJoiner("&");
+
+ {{#allVars}}
+ // add `{{baseName}}` to the URL query string
+ {{#isArray}}
+ {{#items.isPrimitiveType}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{items.dataType}} _item : {{getter}}()) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf(_item), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf({{getter}}().get(i)), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ {{#items.isModel}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{items.dataType}} _item : {{getter}}()) {
+ if (_item != null) {
+ joiner.add(_item.toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ i++;
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ if ({{getter}}().get(i) != null) {
+ joiner.add({{getter}}().get(i).toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix))));
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{^items.isModel}}
+ {{#uniqueItems}}
+ if ({{getter}}() != null) {
+ int i = 0;
+ for ({{items.dataType}} _item : {{getter}}()) {
+ if (_item != null) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf(_item), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ i++;
+ }
+ }
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ if ({{getter}}() != null) {
+ for (int i = 0; i < {{getter}}().size(); i++) {
+ if ({{getter}}().get(i) != null) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, i, containerSuffix),
+ URLEncoder.encode(String.valueOf({{getter}}().get(i)), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+ {{/uniqueItems}}
+ {{/items.isModel}}
+ {{/items.isPrimitiveType}}
+ {{/isArray}}
+ {{^isArray}}
+ {{#isMap}}
+ {{#items.isPrimitiveType}}
+ if ({{getter}}() != null) {
+ for (String _key : {{getter}}().keySet()) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s=%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, _key, containerSuffix),
+ {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ {{/items.isPrimitiveType}}
+ {{^items.isPrimitiveType}}
+ if ({{getter}}() != null) {
+ for (String _key : {{getter}}().keySet()) {
+ if ({{getter}}().get(_key) != null) {
+ joiner.add({{getter}}().get(_key).toUrlQueryString(String.format(java.util.Locale.ROOT, "%s{{baseName}}%s%s", prefix, suffix,
+ "".equals(suffix) ? "" : String.format(java.util.Locale.ROOT, "%s%d%s", containerPrefix, _key, containerSuffix))));
+ }
+ }
+ }
+ {{/items.isPrimitiveType}}
+ {{/isMap}}
+ {{^isMap}}
+ {{#isPrimitiveType}}
+ if ({{getter}}() != null) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ {{#isModel}}
+ if ({{getter}}() != null) {
+ joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix));
+ }
+ {{/isModel}}
+ {{^isModel}}
+ if ({{getter}}() != null) {
+ try {
+ joiner.add(String.format(java.util.Locale.ROOT, "%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), "UTF-8").replaceAll("\\+", "%20")));
+ } catch (UnsupportedEncodingException e) {
+ // Should never happen, UTF-8 is always supported
+ throw new RuntimeException(e);
+ }
+ }
+ {{/isModel}}
+ {{/isPrimitiveType}}
+ {{/isMap}}
+ {{/isArray}}
+
+ {{/allVars}}
+ return joiner.toString();
+ }
+{{/supportUrlQuery}}
+{{#parcelableModel}}
+
+ public void writeToParcel(Parcel out, int flags) {
+{{#model}}
+{{#isArray}}
+ out.writeList(this);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super.writeToParcel(out, flags);
+{{/parent}}
+{{#vars}}
+ out.writeValue({{name}});
+{{/vars}}
+{{/isArray}}
+{{/model}}
+ }
+
+ {{classname}}(Parcel in) {
+{{#isArray}}
+ in.readTypedList(this, {{arrayModelType}}.CREATOR);
+{{/isArray}}
+{{^isArray}}
+{{#parent}}
+ super(in);
+{{/parent}}
+{{#vars}}
+{{#isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue(null);
+{{/isPrimitiveType}}
+{{^isPrimitiveType}}
+ {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader());
+{{/isPrimitiveType}}
+{{/vars}}
+{{/isArray}}
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() {
+ public {{classname}} createFromParcel(Parcel in) {
+{{#model}}
+{{#isArray}}
+ {{classname}} result = new {{classname}}();
+ result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader()));
+ return result;
+{{/isArray}}
+{{^isArray}}
+ return new {{classname}}(in);
+{{/isArray}}
+{{/model}}
+ }
+ public {{classname}}[] newArray(int size) {
+ return new {{classname}}[size];
+ }
+ };
+{{/parcelableModel}}
+
+}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache
index 5a122b321..a5e1ee278 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache
@@ -65,12 +65,12 @@
maven-surefire-plugin3.0.0-M4
-
+ loggerPathconf/log4j.properties
-
+
-Xms512m -Xmx1500mmethods10
@@ -220,6 +220,13 @@
${swagger-annotations-version}
{{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+
+ io.swagger.core.v3
+ swagger-annotations
+ ${swagger-annotations-version}
+
+ {{/swagger2AnnotationLibrary}}
@@ -234,11 +241,20 @@
feign-core${feign-version}
+ {{#jackson}}
io.github.openfeignfeign-jackson${feign-version}
+ {{/jackson}}
+ {{#gson}}
+
+ io.github.openfeign
+ feign-gson
+ ${feign-version}
+
+ {{/gson}}
io.github.openfeignfeign-slf4j
@@ -249,12 +265,22 @@
feign-form${feign-form-version}
+ {{#feign-okhttp}}
io.github.openfeignfeign-okhttp${feign-version}
+ {{/feign-okhttp}}
+ {{#feign-hc5}}
+
+ io.github.openfeign
+ feign-hc5
+ ${feign-version}
+
+ {{/feign-hc5}}
+ {{#jackson}}
com.fasterxml.jackson.core
@@ -271,6 +297,14 @@
jackson-databind${jackson-databind-version}
+ {{/jackson}}
+ {{#gson}}
+
+ com.google.code.gson
+ gson
+ ${gson-version}
+
+ {{/gson}}
{{#openApiNullable}}
org.openapitools
@@ -293,11 +327,13 @@
${jackson-version}
{{/joda}}
+ {{#jackson}}
com.fasterxml.jackson.datatypejackson-datatype-jsr310${jackson-version}
+ {{/jackson}}
com.github.scribejavascribejava-core
@@ -309,12 +345,29 @@
${jakarta-annotation-version}provided
+ {{#useBeanValidation}}
+
+
+ jakarta.validation
+ jakarta.validation-api
+ ${beanvalidation-version}
+ provided
+
+ {{/useBeanValidation}}
+ {{#useReflectionEqualsHashCode}}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3-version}
+
+ {{/useReflectionEqualsHashCode}}
ch.qos.logbacklogback-classic
- 1.2.10
+ 1.3.13test
@@ -338,13 +391,7 @@
com.github.tomakehurstwiremock-jre8
- 2.27.2
- test
-
-
- commons-io
- commons-io
- 2.8.0
+ 2.35.1test
@@ -353,17 +400,37 @@
1.8${java.version}${java.version}
- 1.6.6
- 10.11
+ {{#swagger1AnnotationLibrary}}
+ 1.6.11
+ {{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+ 2.2.15
+ {{/swagger2AnnotationLibrary}}
+ 13.2.13.8.0
- 2.13.4
+ {{#jackson}}
+ 2.17.1
+ 2.17.1
+ {{/jackson}}
+ {{#gson}}
+ 2.10.1
+ {{/gson}}
{{#openApiNullable}}
- 0.2.4
+ 0.2.9
{{/openApiNullable}}
- 2.13.4.2
+ {{#useJakartaEe}}
+ 2.1.1
+ 3.0.2
+ {{/useJakartaEe}}
+ {{^useJakartaEe}}
1.3.5
- 5.7.0
+ 2.0.2
+ {{/useJakartaEe}}
+ {{#useReflectionEqualsHashCode}}
+ 3.17.0
+ {{/useReflectionEqualsHashCode}}
+ 5.10.01.0.0
- 8.0.0
+ 8.3.3
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache
index c1b8e1fdd..32b3cae75 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache
@@ -1,3 +1,5 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
import {{apiPackage}}.*;
@@ -22,17 +24,23 @@ import java.io.IOException;
import java.io.OutputStream;
{{>generatedAnnotation}}
+
public class ApiClient {
- private final String basePath;
- private final HttpRequestFactory httpRequestFactory;
- private final ObjectMapper objectMapper;
+ protected final String basePath;
+ protected final HttpRequestFactory httpRequestFactory;
+ protected final ObjectMapper objectMapper;
- private static final String defaultBasePath = "{{basePath}}";
+ protected static final String defaultBasePath = "{{basePath}}";
// A reasonable default object mapper. Client can pass in a chosen ObjectMapper anyway, this is just for reasonable defaults.
- private static ObjectMapper createDefaultObjectMapper() {
+ protected static ObjectMapper createDefaultObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper()
+ {{#failOnUnknownProperties}}
+ .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ {{/failOnUnknownProperties}}
+ {{^failOnUnknownProperties}}
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ {{/failOnUnknownProperties}}
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.setDateFormat(new RFC3339DateFormat());
{{#joda}}
@@ -77,7 +85,7 @@ public class ApiClient {
public class JacksonJsonHttpContent extends AbstractHttpContent {
/* A POJO that can be serialized with a com.fasterxml Jackson ObjectMapper */
- private final Object data;
+ protected final Object data;
public JacksonJsonHttpContent(Object data) {
super(Json.MEDIA_TYPE);
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache
index f9af1a4a9..2b4365bbf 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache
@@ -14,7 +14,7 @@ import com.google.api.client.http.HttpMethods;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.json.Json;
-import javax.ws.rs.core.UriBuilder;
+import {{javaxPackage}}.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.ArrayList;
{{>generatedAnnotation}}
+
{{#operations}}
public class {{classname}} {
private ApiClient apiClient;
@@ -61,7 +62,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException {
+ public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException {
{{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}}
TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {};
return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}}
@@ -85,7 +86,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException {
+ public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException {
{{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}}
TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {};
return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}}
@@ -94,7 +95,7 @@ public class {{classname}} {
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException {
+ public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException {
{{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) {
throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}");
@@ -122,13 +123,19 @@ public class {{classname}} {
GenericUrl genericUrl = new GenericUrl(localVarUrl);
HttpContent content = {{#isBodyAllowed}}{{#bodyParam}}apiClient.new JacksonJsonHttpContent({{paramName}}){{/bodyParam}}{{^bodyParam}}new EmptyContent(){{/bodyParam}}{{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}};
- return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute();
+ com.google.api.client.http.HttpRequest httpRequest = apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content);
+ {{#headerParams}}
+ if ({{paramName}} != null) {
+ httpRequest.getHeaders().set("{{baseName}}", {{paramName}});
+ }
+ {{/headerParams}}
+ return httpRequest.execute();
}{{#bodyParam}}
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{^-last}}, {{/-last}}{{/allParams}}, String mediaType) throws IOException {
+ public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{/isBodyParam}}{{^-last}}, {{/-last}}{{/allParams}}, String mediaType) throws IOException {
{{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) {
throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}");
@@ -158,13 +165,19 @@ public class {{classname}} {
HttpContent content = {{#bodyParam}}{{paramName}} == null ?
apiClient.new JacksonJsonHttpContent(null) :
new InputStreamContent(mediaType == null ? Json.MEDIA_TYPE : mediaType, {{paramName}}){{/bodyParam}};
- return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute();
+ com.google.api.client.http.HttpRequest httpRequest = apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content);
+ {{#headerParams}}
+ if ({{paramName}} != null) {
+ httpRequest.getHeaders().set("{{baseName}}", {{paramName}});
+ }
+ {{/headerParams}}
+ return httpRequest.execute();
}{{/bodyParam}}
{{#isDeprecated}}
@Deprecated
{{/isDeprecated}}
- public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException {
+ public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{>nullable_var_annotations}} {{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException {
{{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set
if ({{paramName}} == null) {
throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}");
@@ -200,7 +213,21 @@ public class {{classname}} {
GenericUrl genericUrl = new GenericUrl(localVarUrl);
HttpContent content = {{#isBodyAllowed}}{{#bodyParam}}apiClient.new JacksonJsonHttpContent({{paramName}}){{/bodyParam}}{{^bodyParam}}new EmptyContent(){{/bodyParam}}{{/isBodyAllowed}}{{^isBodyAllowed}}null{{/isBodyAllowed}};
- return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute();
+ com.google.api.client.http.HttpRequest httpRequest = apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content);
+ {{#hasHeaderParams}}
+ // Note: Header params passed via 'params' map are handled below
+ for (Map.Entry entry: params.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ // Check if this is a header parameter by name
+ {{#headerParams}}
+ if ("{{baseName}}".equals(key) && value != null) {
+ httpRequest.getHeaders().set(key, value);
+ }
+ {{/headerParams}}
+ }
+ {{/hasHeaderParams}}
+ return httpRequest.execute();
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache
index e81a6cf29..bfb939f95 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache
@@ -4,28 +4,26 @@ package {{package}};
{{#imports}}import {{import}};
{{/imports}}
-import org.junit.Test;
-import org.junit.Ignore;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.time.LocalDate;
import java.time.OffsetDateTime;
-{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-{{/fullJavaUtil}}
/**
* API tests for {{classname}}
*/
-@Ignore
public class {{classname}}Test {
private final {{classname}} api = new {{classname}}();
- {{#operations}}{{#operation}}
+ {{#operations}}
+ {{#operation}}
/**
* {{summary}}
*
@@ -39,9 +37,12 @@ public class {{classname}}Test {
{{#allParams}}
{{{dataType}}} {{paramName}} = null;
{{/allParams}}
- {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
+ // uncomment below to test the API function
+ //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
// TODO: test validations
}
- {{/operation}}{{/operations}}
+
+ {{/operation}}
+ {{/operations}}
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache
index c14b05a57..3dbb1f667 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache
@@ -57,9 +57,9 @@ if(hasProperty('target') && target == 'android') {
def task = project.tasks.create "jar${variant.name.capitalize()}", Jar
task.description = "Create jar artifact for ${variant.name}"
task.dependsOn variant.javaCompile
- task.from variant.javaCompile.destinationDir
- task.destinationDir = project.file("${project.buildDir}/outputs/jar")
- task.archiveName = "${project.name}-${variant.baseName}-${version}.jar"
+ task.from variant.javaCompile.destinationDirectory
+ task.destinationDirectory = project.file("${project.buildDir}/outputs/jar")
+ task.archiveFileName = "${project.name}-${variant.baseName}-${version}.jar"
artifacts.add('archives', task);
}
}
@@ -98,10 +98,10 @@ if(hasProperty('target') && target == 'android') {
ext {
swagger_annotations_version = "1.6.3"
- jackson_version = "2.13.4"
- jackson_databind_version = "2.13.4.2"
+ jackson_version = "2.19.2"
+ jackson_databind_version = "2.19.2"
{{#openApiNullable}}
- jackson_databind_nullable_version = "0.2.4"
+ jackson_databind_nullable_version = "0.2.9"
{{/openApiNullable}}
jakarta_annotation_version = "1.3.5"
google_api_client_version = "1.32.2"
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache
index 78da21f2e..a849d22be 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache
@@ -3,10 +3,10 @@ lazy val root = (project in file(".")).
organization := "{{groupId}}",
name := "{{artifactId}}",
version := "{{artifactVersion}}",
- scalaVersion := "2.11.4",
+ scalaVersion := "2.11.12",
scalacOptions ++= Seq("-feature"),
- javacOptions in compile ++= Seq("-Xlint:deprecation"),
- publishArtifact in (Compile, packageDoc) := false,
+ compile / javacOptions ++= Seq("-Xlint:deprecation"),
+ Compile / packageDoc / publishArtifact := false,
resolvers += Resolver.mavenLocal,
libraryDependencies ++= Seq(
"io.swagger" % "swagger-annotations" % "1.5.22",
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache
index efd1199b2..3c0378942 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache
@@ -63,17 +63,16 @@
org.apache.maven.pluginsmaven-surefire-plugin
- 2.12
+ 2.22.2
-
+ loggerPathconf/log4j.properties
-
+
-Xms512m -Xmx1500mmethods
- pertest
@@ -213,6 +212,13 @@
${swagger-annotations-version}
{{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+
+ io.swagger.core.v3
+ swagger-annotations
+ ${swagger-annotations-version}
+
+ {{/swagger2AnnotationLibrary}}
com.google.code.findbugs
@@ -288,27 +294,37 @@
- junit
- junit
+ org.junit.jupiter
+ junit-jupiter-api${junit-version}testUTF-8
+ {{#swagger1AnnotationLibrary}}
1.6.6
- 1.32.2
- 2.25.1
- 2.13.4
- 2.13.4.2
+ {{/swagger1AnnotationLibrary}}
+ {{#swagger2AnnotationLibrary}}
+ 2.2.15
+ {{/swagger2AnnotationLibrary}}
+ 2.2.0
+ 2.40
+ 2.19.2
+ 2.19.2
{{#openApiNullable}}
- 0.2.4
+ 0.2.9
{{/openApiNullable}}
{{#joda}}
2.9.9
{{/joda}}
+ {{#useJakartaEe}}
+ 2.1.1
+ {{/useJakartaEe}}
+ {{^useJakartaEe}}
1.3.5
+ {{/useJakartaEe}}
1.0.0
- 4.13.2
+ 5.10.2
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache
index 00253ccee..8e5c32da7 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache
@@ -6,14 +6,15 @@ import {{invokerPackage}}.ApiException;
import java.util.Objects;
import java.lang.reflect.Type;
import java.util.Map;
-import javax.ws.rs.core.GenericType;
+import {{javaxPackage}}.ws.rs.core.GenericType;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* Abstract class for oneOf,anyOf schemas defined in OpenAPI spec
*/
-{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}
+{{>generatedAnnotation}}
+
public abstract class AbstractOpenApiSchema {
// store the actual instance of the schema/object
@@ -35,7 +36,7 @@ public abstract class AbstractOpenApiSchema {
*
* @return an instance of the actual schema/object
*/
- public abstract Map getSchemas();
+ public abstract Map> getSchemas();
/**
* Get the actual instance
@@ -135,4 +136,5 @@ public abstract class AbstractOpenApiSchema {
{{>libraries/jersey2/additional_properties}}
+
}
diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache
index 2a027220d..2de6367d9 100644
--- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache
+++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache
@@ -1,15 +1,17 @@
+{{>licenseInfo}}
+
package {{invokerPackage}};
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.Invocation;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.GenericType;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import {{javaxPackage}}.ws.rs.client.Client;
+import {{javaxPackage}}.ws.rs.client.ClientBuilder;
+import {{javaxPackage}}.ws.rs.client.Entity;
+import {{javaxPackage}}.ws.rs.client.Invocation;
+import {{javaxPackage}}.ws.rs.client.WebTarget;
+import {{javaxPackage}}.ws.rs.core.Form;
+import {{javaxPackage}}.ws.rs.core.GenericType;
+import {{javaxPackage}}.ws.rs.core.MediaType;
+import {{javaxPackage}}.ws.rs.core.Response;
+import {{javaxPackage}}.ws.rs.core.Response.Status;
{{#hasOAuthMethods}}
import com.github.scribejava.core.model.OAuth2AccessToken;
@@ -38,6 +40,7 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.glassfish.jersey.logging.LoggingFeature;
+import java.util.AbstractMap.SimpleEntry;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Collection;
@@ -45,11 +48,14 @@ import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Date;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
{{#jsr310}}
import java.time.OffsetDateTime;
{{/jsr310}}
@@ -78,85 +84,99 @@ import {{invokerPackage}}.auth.OAuth;
*
ApiClient class.
*/
{{>generatedAnnotation}}
+
public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
- protected Map defaultHeaderMap = new HashMap();
- protected Map defaultCookieMap = new HashMap();
+ protected static final Pattern JSON_MIME_PATTERN = Pattern.compile("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$");
+
+ protected Map defaultHeaderMap = new HashMap<>();
+ protected Map defaultCookieMap = new HashMap<>();
protected String basePath = "{{{basePath}}}";
protected String userAgent;
- private static final Logger log = Logger.getLogger(ApiClient.class.getName());
-
- protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList(
-{{/-first}} new ServerConfiguration(
- "{{{url}}}",
- "{{{description}}}{{^description}}No description provided{{/description}}",
- new HashMap(){{#variables}}{{#-first}} {{
-{{/-first}} put("{{{name}}}", new ServerVariable(
- "{{{description}}}{{^description}}No description provided{{/description}}",
- "{{{defaultValue}}}",
- new HashSet(
- {{#enumValues}}
- {{#-first}}
- Arrays.asList(
- {{/-first}}
- "{{{.}}}"{{^-last}},{{/-last}}
- {{#-last}}
- )
- {{/-last}}
- {{/enumValues}}
- )
- ));
- {{#-last}}
- }}{{/-last}}{{/variables}}
- ){{^-last}},{{/-last}}
+ protected static final Logger log = Logger.getLogger(ApiClient.class.getName());
+
+ protected List servers = new ArrayList<>({{#servers}}{{#-first}}Arrays.asList(
+{{/-first}} new ServerConfiguration(
+ "{{{url}}}",
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ {{^variables}}
+ new LinkedHashMap<>()
+ {{/variables}}
+ {{#variables}}
+ {{#-first}}
+ Stream.>of(
+ {{/-first}}
+ new SimpleEntry<>("{{{name}}}", new ServerVariable(
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ "{{{defaultValue}}}",
+ new LinkedHashSet<>({{#enumValues}}{{#-first}}Arrays.asList({{/-first}}
+ "{{{.}}}"{{^-last}},{{/-last}}{{#-last}}
+ ){{/-last}}{{/enumValues}})
+ )){{^-last}},{{/-last}}
+ {{#-last}}
+ ).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> a, LinkedHashMap::new))
+ {{/-last}}
+ {{/variables}}
+ ){{^-last}},{{/-last}}
{{#-last}}
){{/-last}}{{/servers}});
protected Integer serverIndex = 0;
protected Map serverVariables = null;
- protected Map> operationServers = new HashMap>() {{
+ {{^hasOperationServers}}
+ protected Map> operationServers = new HashMap<>();
+ {{/hasOperationServers}}
+ {{#hasOperationServers}}
+ protected Map> operationServers;
+
+ {
+ Map> operationServers = new HashMap<>();
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{#operation}}
{{#servers}}
{{#-first}}
- put("{{{classname}}}.{{{operationId}}}", new ArrayList(Arrays.asList(
+ operationServers.put("{{{classname}}}.{{{operationId}}}", new ArrayList<>(Arrays.asList(
{{/-first}}
- new ServerConfiguration(
- "{{{url}}}",
- "{{{description}}}{{^description}}No description provided{{/description}}",
- new HashMap(){{#variables}}{{#-first}} {{
-{{/-first}} put("{{{name}}}", new ServerVariable(
- "{{{description}}}{{^description}}No description provided{{/description}}",
- "{{{defaultValue}}}",
- new HashSet(
- {{#enumValues}}
- {{#-first}}
- Arrays.asList(
- {{/-first}}
- "{{{.}}}"{{^-last}},{{/-last}}
- {{#-last}}
- )
- {{/-last}}
- {{/enumValues}}
- )
- ));
- {{#-last}}
- }}{{/-last}}{{/variables}}
- ){{^-last}},{{/-last}}
+ new ServerConfiguration(
+ "{{{url}}}",
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ {{^variables}}
+ new LinkedHashMap<>()
+ {{/variables}}
+ {{#variables}}
+ {{#-first}}
+ Stream.>of(
+ {{/-first}}
+ new SimpleEntry<>("{{{name}}}", new ServerVariable(
+ "{{{description}}}{{^description}}No description provided{{/description}}",
+ "{{{defaultValue}}}",
+ new LinkedHashSet<>({{#enumValues}}{{#-first}}Arrays.asList({{/-first}}
+ "{{{.}}}"{{^-last}},{{/-last}}{{#-last}}
+ ){{/-last}}{{/enumValues}})
+ )){{^-last}},{{/-last}}
+ {{#-last}}
+ ).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> a, LinkedHashMap::new))
+ {{/-last}}
+ {{/variables}}
+ ){{^-last}},{{/-last}}
{{#-last}}
- )));{{/-last}}
+ )));
+ {{/-last}}
{{/servers}}
{{/operation}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
- }};
- protected Map operationServerIndex = new HashMap();
- protected Map> operationServerVariables = new HashMap>();
+ this.operationServers = operationServers;
+ }
+
+ {{/hasOperationServers}}
+ protected Map operationServerIndex = new HashMap<>();
+ protected Map> operationServerVariables = new HashMap<>();
protected boolean debugging = false;
protected ClientConfig clientConfig;
protected int connectionTimeout = 0;
- private int readTimeout = 0;
+ protected int readTimeout = 0;
protected Client httpClient;
protected JSON json;
@@ -189,7 +209,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
- authentications = new HashMap();
+ authentications = new HashMap<>();
Authentication auth = null;
{{#authMethods}}
if (authMap != null) {
@@ -235,7 +255,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
authentications = Collections.unmodifiableMap(authentications);
// Setup authentication lookup (key: authentication alias, value: authentication name)
- authenticationLookup = new HashMap();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}}
+ authenticationLookup = new HashMap<>();{{#authMethods}}{{#vendorExtensions.x-auth-id-alias}}
authenticationLookup.put("{{name}}", "{{.}}");{{/vendorExtensions.x-auth-id-alias}}{{/authMethods}}
}
@@ -251,7 +271,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
*
Getter for the field httpClient.
*
- * @return a {@link javax.ws.rs.client.Client} object.
+ * @return a {@link {{javaxPackage}}.ws.rs.client.Client} object.
*/
public Client getHttpClient() {
return httpClient;
@@ -260,8 +280,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
/**
*
Setter for the field httpClient.
*
- * @param httpClient a {@link javax.ws.rs.client.Client} object.
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @param httpClient a {@link {{javaxPackage}}.ws.rs.client.Client} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setHttpClient(Client httpClient) {
this.httpClient = httpClient;
@@ -281,7 +301,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Sets the base URL to the location where the OpenAPI document is being served.
*
* @param basePath The base URL to the target host.
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setBasePath(String basePath) {
this.basePath = basePath;
@@ -304,7 +324,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
Setter for the field servers.
*
* @param servers a {@link java.util.List} of servers.
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setServers(List servers) {
this.servers = servers;
@@ -325,7 +345,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
Setter for the field serverIndex.
*
* @param serverIndex the server index
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setServerIndex(Integer serverIndex) {
this.serverIndex = serverIndex;
@@ -346,7 +366,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
Setter for the field serverVariables.
*
* @param serverVariables a {@link java.util.Map} of server variables.
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setServerVariables(Map serverVariables) {
this.serverVariables = serverVariables;
@@ -354,14 +374,14 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return this;
}
- private void updateBasePath() {
+ protected void updateBasePath() {
if (serverIndex != null) {
setBasePath(servers.get(serverIndex).URL(serverVariables));
}
}
{{#hasOAuthMethods}}
- private void setOauthBasePath(String basePath) {
+ protected void setOauthBasePath(String basePath) {
for(Authentication auth : authentications.values()) {
if (auth instanceof OAuth) {
((OAuth) auth).setBasePath(basePath);
@@ -393,7 +413,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set username for the first HTTP basic authentication.
*
* @param username Username
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setUsername(String username) {
for (Authentication auth : authentications.values()) {
@@ -409,7 +429,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set password for the first HTTP basic authentication.
*
* @param password Password
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setPassword(String password) {
for (Authentication auth : authentications.values()) {
@@ -425,7 +445,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set API key value for the first API key authentication.
*
* @param apiKey API key
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
@@ -441,7 +461,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to configure authentications which respects aliases of API keys.
*
* @param secrets Hash map from authentication name to its secret.
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient configureApiKeys(Map secrets) {
for (Map.Entry authEntry : authentications.entrySet()) {
@@ -449,9 +469,10 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
if (auth instanceof ApiKeyAuth) {
String name = authEntry.getKey();
// respect x-auth-id-alias property
- name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name;
- if (secrets.containsKey(name)) {
- ((ApiKeyAuth) auth).setApiKey(secrets.get(name));
+ name = authenticationLookup.getOrDefault(name, name);
+ String secret = secrets.get(name);
+ if (secret != null) {
+ ((ApiKeyAuth) auth).setApiKey(secret);
}
}
}
@@ -462,7 +483,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set API key prefix for the first API key authentication.
*
* @param apiKeyPrefix API key prefix
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setApiKeyPrefix(String apiKeyPrefix) {
for (Authentication auth : authentications.values()) {
@@ -478,7 +499,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set bearer token for the first Bearer authentication.
*
* @param bearerToken Bearer token
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setBearerToken(String bearerToken) {
for (Authentication auth : authentications.values()) {
@@ -495,7 +516,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set access token for the first OAuth2 authentication.
*
* @param accessToken Access token
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setAccessToken(String accessToken) {
for (Authentication auth : authentications.values()) {
@@ -512,7 +533,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
* @param clientId the client ID
* @param clientSecret the client secret
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setOauthCredentials(String clientId, String clientSecret) {
for (Authentication auth : authentications.values()) {
@@ -528,7 +549,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set the credentials of a public client for the first OAuth2 authentication.
*
* @param clientId the client ID
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setOauthCredentialsForPublicClient(String clientId) {
for (Authentication auth : authentications.values()) {
@@ -545,7 +566,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
* @param username the user name
* @param password the user password
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setOauthPasswordFlow(String username, String password) {
for (Authentication auth : authentications.values()) {
@@ -561,7 +582,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set the authorization code flow for the first OAuth2 authentication.
*
* @param code the authorization code
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setOauthAuthorizationCodeFlow(String code) {
for (Authentication auth : authentications.values()) {
@@ -577,7 +598,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Helper method to set the scopes for the first OAuth2 authentication.
*
* @param scope the oauth scope
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setOauthScope(String scope) {
for (Authentication auth : authentications.values()) {
@@ -594,7 +615,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Set the User-Agent header's value (by adding to the default header map).
*
* @param userAgent Http user agent
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setUserAgent(String userAgent) {
this.userAgent = userAgent;
@@ -616,7 +637,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
* @param key The header's key
* @param value The header's value
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient addDefaultHeader(String key, String value) {
defaultHeaderMap.put(key, value);
@@ -628,7 +649,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
*
* @param key The cookie's key
* @param value The cookie's value
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient addDefaultCookie(String key, String value) {
defaultCookieMap.put(key, value);
@@ -648,7 +669,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Set the client config.
*
* @param clientConfig Set the client config
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setClientConfig(ClientConfig clientConfig) {
this.clientConfig = clientConfig;
@@ -670,10 +691,11 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Enable/disable debugging for this API client.
*
* @param debugging To enable (true) or disable (false) debugging
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setDebugging(boolean debugging) {
this.debugging = debugging;
+ applyDebugSetting(this.clientConfig);
// Rebuild HTTP Client according to the new "debugging" value.
this.httpClient = buildHttpClient();
return this;
@@ -694,7 +716,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Set temp folder path
*
* @param tempFolderPath Temp folder path
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setTempFolderPath(String tempFolderPath) {
this.tempFolderPath = tempFolderPath;
@@ -716,7 +738,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* {@link Integer#MAX_VALUE}.
*
* @param connectionTimeout Connection timeout in milliseconds
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setConnectTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
@@ -739,7 +761,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* {@link Integer#MAX_VALUE}.
*
* @param readTimeout Read timeout in milliseconds
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
@@ -760,7 +782,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* Set the date format used to parse/format date parameters.
*
* @param dateFormat Date format
- * @return a {@link org.openapitools.client.ApiClient} object.
+ * @return a {@link ApiClient} object.
*/
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
@@ -806,9 +828,9 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return formatDate((Date) param);
} {{#jsr310}}else if (param instanceof OffsetDateTime) {
return formatOffsetDateTime((OffsetDateTime) param);
- } {{/jsr310}}else if (param instanceof Collection) {
+ } {{/jsr310}}else if (param instanceof Collection>) {
StringBuilder b = new StringBuilder();
- for(Object o : (Collection)param) {
+ for(Object o : (Collection>)param) {
if(b.length() > 0) {
b.append(',');
}
@@ -829,14 +851,14 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @return List of pairs
*/
public List parameterToPairs(String collectionFormat, String name, Object value){
- List params = new ArrayList();
+ List params = new ArrayList<>();
// preconditions
if (name == null || name.isEmpty() || value == null) return params;
- Collection valueCollection;
- if (value instanceof Collection) {
- valueCollection = (Collection) value;
+ Collection> valueCollection;
+ if (value instanceof Collection>) {
+ valueCollection = (Collection>) value;
} else {
params.add(new Pair(name, parameterToString(value)));
return params;
@@ -888,14 +910,13 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* application/json; charset=UTF8
* APPLICATION/JSON
* application/vnd.company+json
- * "* / *" is also default to JSON
+ * "*{@literal /}*" is also considered JSON by this method.
*
* @param mime MIME
* @return True if the MIME type is JSON
*/
public boolean isJsonMime(String mime) {
- String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$";
- return mime != null && (mime.matches(jsonMime) || mime.equals("*/*"));
+ return mime != null && (mime.equals("*/*") || JSON_MIME_PATTERN.matcher(mime).matches());
}
/**
@@ -907,8 +928,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @return The Accept header to use. If the given array is empty,
* null will be returned (not to set the Accept header explicitly).
*/
- public String selectHeaderAccept(String[] accepts) {
- if (accepts.length == 0) {
+ public String selectHeaderAccept(String... accepts) {
+ if (accepts == null || accepts.length == 0) {
return null;
}
for (String accept : accepts) {
@@ -928,8 +949,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
* @return The Content-Type header to use. If the given array is empty,
* JSON will be used.
*/
- public String selectHeaderContentType(String[] contentTypes) {
- if (contentTypes.length == 0) {
+ public String selectHeaderContentType(String... contentTypes) {
+ if (contentTypes == null || contentTypes.length == 0) {
return "application/json";
}
for (String contentType : contentTypes) {
@@ -969,14 +990,10 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
if (contentType.startsWith("multipart/form-data")) {
MultiPart multiPart = new MultiPart();
for (Entry param: formParams.entrySet()) {
- if (param.getValue() instanceof File) {
- File file = (File) param.getValue();
- FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey())
- .fileName(file.getName()).size(file.length()).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
+ if (param.getValue() instanceof Iterable>) {
+ ((Iterable>)param.getValue()).forEach(v -> addParamToMultipart(v, param.getKey(), multiPart));
} else {
- FormDataContentDisposition contentDisp = FormDataContentDisposition.name(param.getKey()).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(param.getValue())));
+ addParamToMultipart(param.getValue(), param.getKey(), multiPart);
}
}
entity = Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE);
@@ -1005,6 +1022,36 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return entity;
}
+ /**
+ * Adds the object with the provided key to the MultiPart.
+ * Based on the object type sets Content-Disposition and Content-Type.
+ *
+ * @param obj Object
+ * @param key Key of the object
+ * @param multiPart MultiPart to add the form param to
+ */
+ protected void addParamToMultipart(Object value, String key, MultiPart multiPart) {
+ if (value instanceof File) {
+ File file = (File) value;
+ FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key)
+ .fileName(file.getName()).size(file.length()).build();
+
+ // Attempt to probe the content type for the file so that the form part is more correctly
+ // and precisely identified, but fall back to application/octet-stream if that fails.
+ MediaType type;
+ try {
+ type = MediaType.valueOf(Files.probeContentType(file.toPath()));
+ } catch (IOException | IllegalArgumentException e) {
+ type = MediaType.APPLICATION_OCTET_STREAM_TYPE;
+ }
+
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, file, type));
+ } else {
+ FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ }
+ }
+
/**
* Serialize the given Java object into string according the given
* Content-Type (only JSON, HTTP form is supported for now).
@@ -1067,11 +1114,6 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return file;
}
- String contentType = null;
- List