mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-05-12 12:40:53 +00:00
Support Helidon SE 4 generation (clients and servers) (#19150)
* Save work-in-progress * Incoming param handling generating well exc. for file upload * Revise generated test for v3 vs v4 differences * Leave details of multi-part handling to the user for now * change default version to use the highest version known * SE client changes for Helidon 4 * A few fixes; add new v4 SE samples * Fix v3/v4 routing prep * Improve version handling if web site is inaccessible; add test * Reworking parameter conversion and required and validation handling * Add generation of a return value record per response for each operation * Improvements to the result record generation * More changes * Remove change in whitespace in v3 output * More progress on parameter handling * WIP - refactor parameter-returning methods to inner class along with return records * Reorg of op helpers * Use no-op for handling map in path, query, header, cookie - need to revise later * Binary form param handling * Clean-up and consistency check bt useAbstractClass and not * Improve result builders * Add new samples files * Fix a few issues * Update samples after rebase; add build steps for v3 and v4 uac github actions * Remove v3 se useAbstractClass test - creates some bad code * Generated doc updates * Fix missing newline * Improve Javadoc for generated Result; add convenience Result.send method * Add bean val. for body param if needed * Restructure generated records for declared responses; add Generated annotation selectively * Fix typo * In sample generation, force a stable generatorVersion value to avoid confusing builds and up-to-date samples checking * Fix up white space in older generation * Generate PartsUtils only with useAbstractClass = true * Adopt some review comments; more to come * Review comments; notably, switch to using the first path segment to group operations rather than the tags items * Improve status handling a bit * Add new generated sample files * Add missing new samples files * Quite a few updates, esp. to generated samples * New config file for sample * Updates samples * Add updates to .openapi-generator/FILES contents
This commit is contained in:
parent
af94bde2ce
commit
8f1d59fb0a
@ -18,7 +18,10 @@ jobs:
|
||||
matrix:
|
||||
sample:
|
||||
- samples/client/petstore/java-helidon-client/v4/mp
|
||||
- samples/client/petstore/java-helidon-client/v4/se
|
||||
- samples/server/petstore/java-helidon-server/v4/mp
|
||||
- samples/server/petstore/java-helidon-server/v4/se
|
||||
- samples/server/petstore/java-helidon-server/v4/se-uac
|
||||
version: [21]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
6
.github/workflows/samples-jdk21.yaml
vendored
6
.github/workflows/samples-jdk21.yaml
vendored
@ -4,14 +4,18 @@ on:
|
||||
paths:
|
||||
# clients
|
||||
- samples/client/petstore/java-helidon-client/v4/mp/**
|
||||
- samples/client/petstore/java-helidon-client/v4/se/**
|
||||
# servers
|
||||
- samples/server/petstore/java-helidon-server/v4/mp/**
|
||||
- samples/server/petstore/java-helidon-server/v4/se/**
|
||||
pull_request:
|
||||
paths:
|
||||
# clients
|
||||
- samples/client/petstore/java-helidon-client/v4/mp/**
|
||||
- samples/client/petstore/java-helidon-client/v4/se/**
|
||||
# servers
|
||||
- samples/server/petstore/java-helidon-server/v4/mp/**
|
||||
- samples/server/petstore/java-helidon-server/v4/se/**
|
||||
jobs:
|
||||
build:
|
||||
name: Build with JDK21
|
||||
@ -22,8 +26,10 @@ jobs:
|
||||
sample:
|
||||
# clients
|
||||
- samples/client/petstore/java-helidon-client/v4/mp/
|
||||
- samples/client/petstore/java-helidon-client/v4/se/
|
||||
# servers
|
||||
- samples/server/petstore/java-helidon-server/v4/mp/
|
||||
- samples/server/petstore/java-helidon-server/v4/se/
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
|
@ -3,7 +3,7 @@ library: mp
|
||||
outputDir: samples/client/petstore/java-helidon-client/v4/mp
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
|
||||
additionalProperties:
|
||||
helidonVersion: 4.0.8
|
||||
helidonVersion: 4.0.11
|
||||
artifactId: petstore-helidon-client-mp
|
||||
hideGenerationTimestamp: "true"
|
||||
configureAuth: "false"
|
||||
|
14
bin/configs/java-helidon-client-se_4.yaml
Normal file
14
bin/configs/java-helidon-client-se_4.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
generatorName: java-helidon-client
|
||||
library: se
|
||||
outputDir: samples/client/petstore/java-helidon-client/v4/se
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
|
||||
additionalProperties:
|
||||
helidonVersion: 4.0.11
|
||||
artifactId: petstore-helidon-client-se
|
||||
hideGenerationTimestamp: "true"
|
||||
configureAuth: "false"
|
||||
build: "all"
|
||||
test: "spock"
|
||||
requiredPropertiesInConstructor: "false"
|
||||
visitable: "true"
|
||||
fullProject: "true"
|
@ -4,7 +4,7 @@ outputDir: samples/server/petstore/java-helidon-server/v4/mp
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/java-helidon/server
|
||||
additionalProperties:
|
||||
helidonVersion: 4.0.8
|
||||
helidonVersion: 4.0.11
|
||||
artifactId: petstore-helidon-server-mp
|
||||
hideGenerationTimestamp: "true"
|
||||
build: "all"
|
||||
|
@ -0,0 +1,13 @@
|
||||
generatorName: java-helidon-server
|
||||
library: se
|
||||
outputDir: samples/server/petstore/java-helidon-server/v4/se-uac-group-by-file-path
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/java-helidon/server
|
||||
additionalProperties:
|
||||
helidonVersion: 4.0.11
|
||||
artifactId: petstore-helidon-server-se
|
||||
hideGenerationTimestamp: "true"
|
||||
fullProject: "true"
|
||||
useAbstractClass: "true"
|
||||
generatorVersion: "stable"
|
||||
x-helidon-groupBy: first-path-segment
|
12
bin/configs/java-helidon-server-se_4-uac.yaml
Normal file
12
bin/configs/java-helidon-server-se_4-uac.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
generatorName: java-helidon-server
|
||||
library: se
|
||||
outputDir: samples/server/petstore/java-helidon-server/v4/se-uac
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/java-helidon/server
|
||||
additionalProperties:
|
||||
helidonVersion: 4.0.11
|
||||
artifactId: petstore-helidon-server-se
|
||||
hideGenerationTimestamp: "true"
|
||||
fullProject: "true"
|
||||
useAbstractClass: "true"
|
||||
generatorVersion: "stable"
|
12
bin/configs/java-helidon-server-se_4.yaml
Normal file
12
bin/configs/java-helidon-server-se_4.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
generatorName: java-helidon-server
|
||||
library: se
|
||||
outputDir: samples/server/petstore/java-helidon-server/v4/se
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/java-helidon/server
|
||||
additionalProperties:
|
||||
helidonVersion: 4.0.11
|
||||
artifactId: petstore-helidon-server-se
|
||||
hideGenerationTimestamp: "true"
|
||||
fullProject: "true"
|
||||
x-helidon-useOptional: "true"
|
||||
generatorVersion: "stable"
|
@ -65,6 +65,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|
||||
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
|
||||
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|
||||
|x-helidon-groupBy|Selects how to group operations into APIs|<dl><dt>**tags**</dt><dd>Use the 'tags' settings on each operation</dd><dt>**first-path-segment**</dt><dd>Use the first segment of the path</dd></dl>|tags|
|
||||
|x-helidon-useOptional|Wrap optional parameters in an Optional (Helidon 4 and later)| |true|
|
||||
|
||||
## SUPPORTED VENDOR EXTENSIONS
|
||||
|
||||
|
@ -68,6 +68,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|
||||
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |false|
|
||||
|withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false|
|
||||
|x-helidon-groupBy|Selects how to group operations into APIs|<dl><dt>**tags**</dt><dd>Use the 'tags' settings on each operation</dd><dt>**first-path-segment**</dt><dd>Use the first segment of the path</dd></dl>|tags|
|
||||
|x-helidon-useOptional|Wrap optional parameters in an Optional (Helidon 4 and later)| |true|
|
||||
|
||||
## SUPPORTED VENDOR EXTENSIONS
|
||||
|
||||
|
@ -65,6 +65,7 @@ public class JavaHelidonClientCodegen extends JavaHelidonCommonCodegen {
|
||||
|
||||
private static final String X_HELIDON_REQUIRED_IMPL_IMPORTS = "x-helidon-requiredImplImports";
|
||||
private static final String X_HELIDON_IMPL_IMPORTS = "x-helidon-implImports";
|
||||
private static final String X_CLIENT_STYLE_V3 = "x-helidon-client-style-v3";
|
||||
public static final String CONFIG_KEY = "configKey";
|
||||
|
||||
@Setter protected String configKey = null;
|
||||
@ -173,6 +174,8 @@ public class JavaHelidonClientCodegen extends JavaHelidonCommonCodegen {
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
// Not intended for users to set; we compute this based on the major version.
|
||||
additionalProperties.put(X_CLIENT_STYLE_V3, helidonMajorVersion == 3);
|
||||
convertPropertyToStringAndWriteBack(SERIALIZATION_LIBRARY, this::setSerializationLibrary);
|
||||
|
||||
convertPropertyToStringAndWriteBack(CONFIG_KEY, this::setConfigKey);
|
||||
@ -199,7 +202,12 @@ public class JavaHelidonClientCodegen extends JavaHelidonCommonCodegen {
|
||||
} else if (isLibrary(HELIDON_SE)) {
|
||||
apiTemplateFiles.put("api_impl.mustache", ".java");
|
||||
importMapping.put("StringJoiner", "java.util.StringJoiner");
|
||||
importMapping.put("WebClientRequestHeaders", "io.helidon.webclient.WebClientRequestHeaders");
|
||||
if (helidonMajorVersion == 3) {
|
||||
importMapping.put("WebClientRequestHeaders", "io.helidon.webclient.WebClientRequestHeaders");
|
||||
} else {
|
||||
importMapping.put("ClientRequestHeaders", "io.helidon.http.ClientRequestHeaders");
|
||||
importMapping.put("HeaderNames", "io.helidon.http.HeaderNames");
|
||||
}
|
||||
importMapping.put("Pair", invokerPackage + ".Pair");
|
||||
|
||||
|
||||
@ -309,7 +317,10 @@ public class JavaHelidonClientCodegen extends JavaHelidonCommonCodegen {
|
||||
requiredImplImports.add("Pair");
|
||||
}
|
||||
if (op.getHasHeaderParams()) {
|
||||
requiredImplImports.add("WebClientRequestHeaders");
|
||||
requiredImplImports.add(helidonMajorVersion == 3 ? "WebClientRequestHeaders" : "ClientRequestHeaders");
|
||||
if (helidonMajorVersion > 3) {
|
||||
requiredImplImports.add("HeaderNames");
|
||||
}
|
||||
}
|
||||
if (op.getHasFormParams()) {
|
||||
requiredImplImports.add("StringJoiner");
|
||||
|
@ -19,11 +19,13 @@ package org.openapitools.codegen.languages;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
@ -33,7 +35,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
@ -42,7 +46,11 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.servers.Server;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.aether.util.version.GenericVersionScheme;
|
||||
import org.eclipse.aether.version.InvalidVersionSpecificationException;
|
||||
import org.eclipse.aether.version.Version;
|
||||
@ -51,9 +59,17 @@ import org.eclipse.aether.version.VersionScheme;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenResponse;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
|
||||
import org.openapitools.codegen.languages.features.PerformBeanValidationFeatures;
|
||||
import org.openapitools.codegen.model.ModelMap;
|
||||
import org.openapitools.codegen.model.OperationMap;
|
||||
import org.openapitools.codegen.model.OperationsMap;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.openapitools.codegen.CodegenConstants.DEVELOPER_EMAIL;
|
||||
import static org.openapitools.codegen.CodegenConstants.DEVELOPER_NAME;
|
||||
@ -76,15 +92,31 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
static final String MICROPROFILE_ROOT_DEP_PREFIX = "x-helidon-rootJavaEEDepPrefix";
|
||||
static final String X_USE_MP_TESTING = "x-helidon-useMpTesting";
|
||||
static final String X_USE_SMALLRYE_JANDEX_PLUGIN = "x-helidon-useSmallRyeJandexPlugin";
|
||||
static final String X_HAS_RESPONSE_PROPS = "x-helidon-hasResponseProps";
|
||||
static final String X_ALL_RESPONSE_PROPS = "x-helidon-allResponseProps";
|
||||
static final String X_OPTIONAL_RESPONSE_PROPS = "x-helidon-optionalResponseProps";
|
||||
static final String X_REQUIRED_RESPONSE_PROPS = "x-helidon-requiredResponseProps";
|
||||
static final String X_HAS_REQUIRED_RESPONSE_PROPS = "x-helidon-hasRequiredResponseProps";
|
||||
static final String X_RESULT_BUILDER_NEEDS_CTOR = "x-helidon-resultBuilderNeedsCtor";
|
||||
static final String X_IS_MULTIPART_FORM_PARAM = "x-helidon-isMultipartFormParam";
|
||||
static final String X_HAS_RETURN_TYPE = "x-helidon-hasReturnType";
|
||||
static final String X_RETURN_TYPE_EXAMPLE_VALUE = "x-helidon-exampleReturnTypeValue";
|
||||
static final String X_MEDIA_SUPPORT_PACKAGE_PREFIX = "x-helidon-media-support-package-prefix";
|
||||
static final String X_MEDIA_COMMON_MEDIA_TYPE_PACKAGE_PREFIX = "x-helidon-common-media-type-package-prefix";
|
||||
static final String X_USE_REACTIVE = "x-helidon-use-reactive";
|
||||
static final String X_USE_OPTIONAL = "x-helidon-use-optional";
|
||||
static final String MICROPROFILE_ROOT_PACKAGE_DESC = "Root package name for Java EE";
|
||||
static final String MICROPROFILE_ROOT_PACKAGE_JAVAX = "javax";
|
||||
static final String MICROPROFILE_ROOT_PACKAGE_JAKARTA = "jakarta";
|
||||
static final String HELIDON_ENUM_CLASS = "x-helidon-hasEnumClass";
|
||||
private static final String VALIDATION_ARTIFACT_PREFIX_KEY = "x-helidon-validationArtifactPrefix";
|
||||
private static final String X_PATH_SUFFIX = "x-helidon-pathSuffix";
|
||||
private static final String X_FIXUP_PATH = "x-helidon-fixupPath";
|
||||
private static final String VALIDATION_ARTIFACT_PREFIX_JAVAX = "";
|
||||
private static final String VALIDATION_ARTIFACT_PREFIX_JAKARTA = MICROPROFILE_ROOT_PACKAGE_JAKARTA + ".";
|
||||
private static final Map<String, String> EXAMPLE_RETURN_VALUES = new HashMap<String, String>();
|
||||
private final Logger LOGGER = LoggerFactory.getLogger(JavaHelidonCommonCodegen.class);
|
||||
|
||||
// for generated doc
|
||||
static final String MICROPROFILE_ROOT_PACKAGE_DEFAULT =
|
||||
"Helidon 2.x and earlier: " + MICROPROFILE_ROOT_PACKAGE_JAVAX
|
||||
@ -93,20 +125,33 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
static final String SERIALIZATION_LIBRARY_JACKSON = "jackson";
|
||||
static final String SERIALIZATION_LIBRARY_JSONB = "jsonb";
|
||||
|
||||
public static final String DEFAULT_HELIDON_VERSION = "3.0.1";
|
||||
public static final String HELIDON_VERSION = "helidonVersion";
|
||||
|
||||
// Helidon 3 featured reactive style; more recent releases feature synchronous.
|
||||
static final String V3_STYLE = "x-helidon-v3";
|
||||
|
||||
static final String HELIDON_VERSION_DESC = "Helidon complete version identifier or major version number. "
|
||||
+ "The specified exact Helidon release or, if specified as a major version the latest release of that major version, "
|
||||
+ " is used in the generated code.";
|
||||
|
||||
static final String X_HELIDON_USE_OPTIONAL = "x-helidon-useOptional";
|
||||
static final String X_HELIDON_USE_OPTIONAL_DESC = "Wrap optional parameters in an Optional (Helidon 4 and later)";
|
||||
|
||||
static final String FULL_PROJECT = "fullProject";
|
||||
static final String FULL_PROJECT_DESC = "If set to true, it will generate all files; if set to false, " +
|
||||
"it will only generate API files. If unspecified, the behavior depends on whether a project " +
|
||||
"exists or not: if it does not, same as true; if it does, same as false. Note that test files " +
|
||||
"are never overwritten.";
|
||||
|
||||
private String helidonVersion;
|
||||
private int helidonMajorVersion;
|
||||
static final String HELIDON_GROUP_BY = "x-helidon-groupBy";
|
||||
static final String HELIDON_GROUP_BY_DESC = "Selects how to group operations into APIs";
|
||||
|
||||
protected String helidonVersion;
|
||||
protected int helidonMajorVersion;
|
||||
protected boolean useReactive;
|
||||
protected boolean useOptional = true; // effective with Helidon 4
|
||||
protected final GenericTypeDeclarations genericTypeDeclarations = new GenericTypeDeclarations();
|
||||
protected Map<String, List<CodegenOperation>> tagToOperations;
|
||||
|
||||
private String rootJavaEEPackage;
|
||||
private String rootJavaEEDepPrefix;
|
||||
@ -114,6 +159,33 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
private String mpTestsArtifact;
|
||||
private String jandexGroup;
|
||||
private String jandexArtifact;
|
||||
private final Map<String, String> knownHttpStatusMap;
|
||||
protected GroupBy groupBy = GroupBy.DEFAULT;
|
||||
|
||||
protected enum GroupBy {
|
||||
TAGS("tags", "Use the 'tags' settings on each operation"),
|
||||
FIRST_PATH_SEGMENT("first-path-segment", "Use the first segment of the path");
|
||||
|
||||
static GroupBy DEFAULT = TAGS;
|
||||
|
||||
static final Map<String, String> OPTION_VALUES = Arrays.stream(values())
|
||||
.collect(HashMap::new, (map, value) -> map.put(value.groupingName, value.desc), Map::putAll);
|
||||
|
||||
static GroupBy from(String value) {
|
||||
return Arrays.stream(values())
|
||||
.filter(candidate -> candidate.groupingName.equals(value))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
private final String groupingName;
|
||||
private final String desc;
|
||||
|
||||
GroupBy(String groupingName, String desc) {
|
||||
this.groupingName = groupingName;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
|
||||
public static String defaultHelidonVersion() {
|
||||
return VersionUtil.instance().defaultVersion();
|
||||
@ -136,12 +208,21 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
.defaultValue(MICROPROFILE_ROOT_PACKAGE_DEFAULT));
|
||||
cliOptions.add(new CliOption(FULL_PROJECT, FULL_PROJECT_DESC)
|
||||
.defaultValue("")); // depends on project state
|
||||
cliOptions.add(new CliOption(X_HELIDON_USE_OPTIONAL, X_HELIDON_USE_OPTIONAL_DESC)
|
||||
.defaultValue("true"));
|
||||
addOption(HELIDON_GROUP_BY, HELIDON_GROUP_BY_DESC, GroupBy.DEFAULT.groupingName, GroupBy.OPTION_VALUES);
|
||||
|
||||
knownHttpStatusMap = loadKnownHttpStatusMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
importMapping.put("Headers", helidonMajorVersion == 3 ? "io.helidon.http.common.Headers" : "io.helidon.http.Headers");
|
||||
importMapping.put("Optional", "java.util.Optional");
|
||||
importMapping.put("Collectors", "java.util.stream.Collectors");
|
||||
|
||||
String userHelidonVersion = "";
|
||||
String userParentVersion = "";
|
||||
|
||||
@ -169,21 +250,154 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
setHelidonVersion(VersionUtil.instance().defaultVersion());
|
||||
}
|
||||
|
||||
if (helidonMajorVersion > 3) {
|
||||
importMapping.put("Status", "io.helidon.http.Status");
|
||||
importMapping.put("HexFormat", "java.util.HexFormat");
|
||||
}
|
||||
|
||||
additionalProperties.put(HELIDON_VERSION, helidonVersion);
|
||||
additionalProperties.put(V3_STYLE, (helidonMajorVersion == 3));
|
||||
|
||||
setEEPackageAndDependencies(helidonVersion);
|
||||
setMpTestDependency(helidonVersion);
|
||||
setJandexPluginDependency(helidonVersion);
|
||||
setMediaPackageInfo();
|
||||
setUseReactive();
|
||||
setUseOptional();
|
||||
convertPropertyToTypeAndWriteBack(HELIDON_GROUP_BY, GroupBy::from, (value) -> this.groupBy = value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOperationToGroup(String tag,
|
||||
String resourcePath,
|
||||
Operation operation,
|
||||
CodegenOperation co,
|
||||
Map<String, List<CodegenOperation>> operations) {
|
||||
|
||||
if (helidonMajorVersion <= 3) {
|
||||
super.addOperationToGroup(tag, resourcePath, operation, co, operations);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
By convention, the operation's baseName is assigned the name of the group (API) in which it is placed.
|
||||
*/
|
||||
String pathPrefixWithoutLeadingSlash = StringUtils.substringBefore(StringUtils.removeStart(resourcePath, "/"),
|
||||
"/");
|
||||
String groupName = (groupBy == GroupBy.TAGS)
|
||||
? tag
|
||||
: sanitizeName(pathPrefixWithoutLeadingSlash);
|
||||
if (groupName.isEmpty()) {
|
||||
groupName = "Default";
|
||||
}
|
||||
co.baseName = groupName;
|
||||
// Invoke the superclass with our chosen group name as the "tag".
|
||||
super.addOperationToGroup(groupName, resourcePath, operation, co, operations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
|
||||
CodegenOperation op = super.fromOperation(path, httpMethod, operation, servers);
|
||||
|
||||
op.allParams.forEach(p -> p.vendorExtensions.put(X_IS_MULTIPART_FORM_PARAM, op.isMultipart && p.isFormParam));
|
||||
op.vendorExtensions.put(X_HAS_RETURN_TYPE, op.returnType != null && !op.returnType.equals("void"));
|
||||
op.vendorExtensions.put(X_RETURN_TYPE_EXAMPLE_VALUE, chooseExampleReturnTypeValue(op));
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenParameter fromParameter(Parameter parameter, Set<String> imports) {
|
||||
CodegenParameter result = super.fromParameter(parameter, imports);
|
||||
if (!result.required && helidonMajorVersion > 3) {
|
||||
imports.add("Optional");
|
||||
}
|
||||
if (helidonMajorVersion > 3 && result.containerTypeMapped != null) {
|
||||
imports.add(result.containerTypeMapped);
|
||||
}
|
||||
if (result.items != null && result.items.getRef() != null) {
|
||||
result.vendorExtensions.put(HELIDON_ENUM_CLASS, true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenResponse fromResponse(String responseCode, ApiResponse response) {
|
||||
CodegenResponse result = super.fromResponse(responseCode, response);
|
||||
result.vendorExtensions.put(X_HAS_RESPONSE_PROPS, result.hasHeaders || result.dataType != null);
|
||||
List<CodegenProperty> allResponseProps = new ArrayList<>(result.headers);
|
||||
List<CodegenProperty> requiredResponseProps = new ArrayList<>();
|
||||
List<CodegenProperty> optionalResponseProps = new ArrayList<>();
|
||||
if (result.returnProperty != null) {
|
||||
allResponseProps.add(result.returnProperty);
|
||||
}
|
||||
result.vendorExtensions.put(X_ALL_RESPONSE_PROPS, allResponseProps);
|
||||
for (CodegenProperty responseProp : allResponseProps) {
|
||||
if (responseProp.required) {
|
||||
requiredResponseProps.add(responseProp);
|
||||
} else {
|
||||
optionalResponseProps.add(responseProp);
|
||||
}
|
||||
}
|
||||
|
||||
result.vendorExtensions.put(X_REQUIRED_RESPONSE_PROPS, requiredResponseProps);
|
||||
result.vendorExtensions.put(X_OPTIONAL_RESPONSE_PROPS, optionalResponseProps);
|
||||
result.vendorExtensions.put(X_HAS_REQUIRED_RESPONSE_PROPS, !allResponseProps.equals(optionalResponseProps));
|
||||
result.vendorExtensions.put(X_RESULT_BUILDER_NEEDS_CTOR, result.isDefault || !requiredResponseProps.isEmpty());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
|
||||
/*
|
||||
Scan the paths of all the operations, computing the longest common prefix. Then compute and set the path suffix
|
||||
for each operation.
|
||||
*/
|
||||
String commonPathPrefixForApi = StringUtils.getCommonPrefix(objs.getOperations().getOperation()
|
||||
.stream()
|
||||
.map(op -> op.path)
|
||||
.map(path -> path.charAt(0) != '/' ? "/" + path : path )
|
||||
.toArray(String[]::new));
|
||||
String commonPathPrefix;
|
||||
if (commonPathPrefixForApi.equals("/")) {
|
||||
commonPathPrefix = "/";
|
||||
objs.getOperations().put(X_FIXUP_PATH, "TODO - fix path or operation grouping for better performance");
|
||||
} else {
|
||||
int end = commonPathPrefixForApi.charAt(commonPathPrefixForApi.length() - 1) == '/'
|
||||
? commonPathPrefixForApi.length() - 1
|
||||
: commonPathPrefixForApi.length();
|
||||
commonPathPrefix = commonPathPrefixForApi.substring(0, end);
|
||||
}
|
||||
|
||||
objs.getOperations().setPathPrefix(commonPathPrefix);
|
||||
List<String> mismatchedOperations = new ArrayList<>();
|
||||
objs.getOperations().getOperation().forEach(op -> {
|
||||
if (commonPathPrefix.length() > 1) {
|
||||
op.vendorExtensions.put(X_PATH_SUFFIX,
|
||||
op.path.equals(commonPathPrefix) ? "/" : op.path.substring(commonPathPrefix.length()));
|
||||
} else {
|
||||
op.vendorExtensions.put(X_PATH_SUFFIX, op.path);
|
||||
mismatchedOperations.add("operation = " + op.operationId + ", path = " + op.path);
|
||||
}});
|
||||
|
||||
if (!mismatchedOperations.isEmpty()) {
|
||||
LOGGER.warn(
|
||||
"Grouping operations by tag has placed operations into API '{}' for which the generated "
|
||||
+ "routing works inefficiently because the operation paths do not share a common path prefix. "
|
||||
+ "Consider specifying the generator option '"
|
||||
+ HELIDON_GROUP_BY
|
||||
+ " {}' or changing the tag settings or path in your OpenAPI document for the following operations: {}{}",
|
||||
objs.getOperations().getClassname(),
|
||||
GroupBy.FIRST_PATH_SEGMENT.groupingName,
|
||||
System.lineSeparator(),
|
||||
mismatchedOperations);
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
protected String statusDeclaration(String code) {
|
||||
return "Status." + knownHttpStatusMap.getOrDefault(code, ".create(" + code + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove set of options not currently used by any Helidon generator. Should be
|
||||
* called during construction but only on leaf classes.
|
||||
@ -236,6 +450,38 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
return rootJavaEEPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a map of predefined HTTP status code constants.
|
||||
* <p>
|
||||
* Helidon uses its own HTTP status type, and the Helidon code predefines many HTTP status code constants but also allows
|
||||
* ad hoc creation of other values based on the numeric status value. It's more efficient at runtime to use a constant
|
||||
* if it exists.
|
||||
* <p>
|
||||
* This method scans a copy of the Helidon Java file which contains the predefined constants and prepares a map
|
||||
* from the string representation of the numeric code to the Helidon constant name. This table allows us, when we are
|
||||
* generating the Response records for an operation, to use the Helidon predefined constant--if it exists--for the
|
||||
* response code declared for an operation in the OpenAPI document.
|
||||
* </p>
|
||||
* @return prepared map
|
||||
*/
|
||||
private HashMap<String, String> loadKnownHttpStatusMap() {
|
||||
try (InputStream is = getClass().getResourceAsStream("/java-helidon/common/Status.java")) {
|
||||
if (is == null) {
|
||||
throw new RuntimeException("Unable to locate /java-helidon/common/Status.java to discover known HTTP statuses");
|
||||
}
|
||||
Pattern statusPattern = Pattern.compile("public static final Status (\\w+)\\s*=\\s*new\\s*Status\\((\\d+)",
|
||||
Pattern.MULTILINE);
|
||||
return new Scanner(is, StandardCharsets.UTF_8)
|
||||
.findAll(statusPattern)
|
||||
.collect(HashMap::new,
|
||||
(map, match) -> map.put(match.group(2), match.group(1)),
|
||||
Map::putAll);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setHelidonVersion(String version) {
|
||||
helidonVersion = VersionUtil.instance().chooseVersion(version);
|
||||
setParentVersion(helidonVersion);
|
||||
@ -269,6 +515,30 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
additionalProperties.put(X_USE_SMALLRYE_JANDEX_PLUGIN, helidonMajorVersion >= 4);
|
||||
}
|
||||
|
||||
private void setMediaPackageInfo() {
|
||||
additionalProperties.put(X_MEDIA_SUPPORT_PACKAGE_PREFIX,
|
||||
(helidonMajorVersion >= 4) ? "io.helidon.http.media" : "io.helidon.media");
|
||||
additionalProperties.put(X_MEDIA_COMMON_MEDIA_TYPE_PACKAGE_PREFIX,
|
||||
(helidonMajorVersion >= 4) ? "io.helidon.common.media.type" : "io.helidon.common.http");
|
||||
}
|
||||
|
||||
private void setUseReactive() {
|
||||
useReactive = (helidonMajorVersion < 4);
|
||||
additionalProperties.put(X_USE_REACTIVE, useReactive);
|
||||
}
|
||||
|
||||
private void setUseOptional() {
|
||||
Object useOptionalSetting = additionalProperties.get(X_USE_OPTIONAL);
|
||||
if (useOptionalSetting == null) {
|
||||
useOptional = true;
|
||||
} else if (useOptionalSetting instanceof Boolean) {
|
||||
useOptional = (Boolean) useOptionalSetting;
|
||||
} else if (useOptionalSetting instanceof String) {
|
||||
useOptional = Boolean.parseBoolean((String) useOptionalSetting);
|
||||
}
|
||||
additionalProperties.put(X_USE_OPTIONAL, useOptional);
|
||||
}
|
||||
|
||||
private String checkAndSelectRootEEPackage(String version) {
|
||||
String packagePrefixImpliedByVersion = usesJakartaPackages(version)
|
||||
? MICROPROFILE_ROOT_PACKAGE_JAKARTA
|
||||
@ -331,6 +601,18 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
forRemoval.forEach(cliOptions::remove);
|
||||
}
|
||||
|
||||
protected String apiFolder() {
|
||||
return folder(apiPackage);
|
||||
}
|
||||
|
||||
protected String modelFolder() {
|
||||
return folder(modelPackage);
|
||||
}
|
||||
|
||||
private String folder(String packageName) {
|
||||
return (sourceFolder + File.separator + packageName).replace(".", java.io.File.separator);
|
||||
}
|
||||
|
||||
private String chooseExampleReturnTypeValue(CodegenOperation op) {
|
||||
|
||||
|
||||
@ -374,6 +656,50 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
}
|
||||
}
|
||||
|
||||
public static class GenericTypeDeclaration {
|
||||
@Getter private final String collectionType;
|
||||
@Getter private final String baseType;
|
||||
public GenericTypeDeclaration(String collectionType, String baseType) {
|
||||
this.collectionType = collectionType;
|
||||
this.baseType = baseType;
|
||||
}
|
||||
|
||||
public boolean isMap() {
|
||||
return collectionType.equals("Map");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures information about the model types for which we need GenericType declarations.
|
||||
*/
|
||||
public static class GenericTypeDeclarations {
|
||||
|
||||
protected static final String ATTR_NAME = "x-helidon-genericTypeDeclarations";
|
||||
protected static final String HAS_ATTR_NAME = "x-helidon-hasGenericTypeDeclarations";
|
||||
|
||||
// Maps collection type (array or map) to an inner map of base type to declaration. This structure makes it easy to
|
||||
// avoid duplicate declarations for the same collection and base type.
|
||||
private final Map<String, Map<String, GenericTypeDeclaration>> declarations = new HashMap<>();
|
||||
|
||||
protected void register(OperationsMap opns) {
|
||||
OperationMap ops = opns.getOperations();
|
||||
ops.getOperation().stream()
|
||||
.flatMap(op -> op.allParams.stream())
|
||||
.filter(p -> p.isArray || p.isMap)
|
||||
.forEach(p -> {
|
||||
String collectionType = p.isArray ? "List" : "Map";
|
||||
declarations.computeIfAbsent(collectionType, ct -> new TreeMap<>())
|
||||
.computeIfAbsent(p.baseType, bt -> new GenericTypeDeclaration(collectionType, bt));
|
||||
});
|
||||
}
|
||||
|
||||
public List<GenericTypeDeclaration> genericTypeDeclarations() {
|
||||
return declarations.values().stream()
|
||||
.flatMap(m -> m.values().stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic for determining the Helidon versions available for user selection, either from helidon.io
|
||||
* or from local preferences or from hard-coded values as a last-chance fallback.
|
||||
@ -386,13 +712,13 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
private static final Duration CONNECTION_TIMEOUT = Duration.ofSeconds(10);
|
||||
private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(5);
|
||||
|
||||
private static final System.Logger LOGGER = System.getLogger(VersionUtil.class.getName());
|
||||
private final System.Logger LOGGER = System.getLogger(VersionUtil.class.getName());
|
||||
|
||||
private static final String DEFAULT_VERSIONS = "<data>\n" +
|
||||
" <archetypes>\n" +
|
||||
" <version>2.6.5</version>\n" +
|
||||
" <version>3.2.6</version>\n" +
|
||||
" <version>4.0.5</version>\n" +
|
||||
" <version>3.2.7</version>\n" +
|
||||
" <version>4.0.9</version>\n" +
|
||||
" </archetypes>\n" +
|
||||
"</data>";
|
||||
|
||||
@ -420,7 +746,7 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
}
|
||||
|
||||
String defaultVersion() {
|
||||
return DEFAULT_HELIDON_VERSION;
|
||||
return versions.get(versions.size() - 1);
|
||||
}
|
||||
|
||||
static int majorVersion(String fullVersion) {
|
||||
@ -481,7 +807,10 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestMatch != null ? bestMatch.toString() : null;
|
||||
// The user might have requested a legal version we cannot fully validate because of a network outage
|
||||
// that prevents us from retrieving the current full list of versions, for example. In such cases return the
|
||||
// requested version itself as the best match.
|
||||
return bestMatch != null ? bestMatch.toString() : requestedVersion;
|
||||
}
|
||||
|
||||
private VersionConstraint constraint(VersionScheme versionScheme, String requestedVersion) {
|
||||
@ -517,7 +846,7 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
|
||||
* @return list of supported versions
|
||||
* @throws IOException in case of error accessing the web site and reading the local file
|
||||
*/
|
||||
private static List<String> versions() throws IOException, BackingStoreException {
|
||||
private List<String> versions() throws IOException, BackingStoreException {
|
||||
|
||||
HttpClient httpClient = HttpClient.newBuilder()
|
||||
.connectTimeout(CONNECTION_TIMEOUT)
|
||||
|
@ -25,16 +25,23 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.servers.Server;
|
||||
import lombok.Getter;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenResponse;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.meta.GeneratorMetadata;
|
||||
@ -54,6 +61,7 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
|
||||
public static final String USE_ABSTRACT_CLASS = "useAbstractClass";
|
||||
public static final String GRADLE_PROJECT = "gradleProject";
|
||||
public static final String X_RESULT_STATUS_DECL = "x-helidon-resultStatusDecl";
|
||||
|
||||
protected String implFolder = "src/main/java";
|
||||
@Getter protected String serializationLibrary = null;
|
||||
@ -129,6 +137,22 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
importMapping.put("InputStream", "java.io.InputStream");
|
||||
if (helidonMajorVersion > 3) {
|
||||
importMapping.put("HeaderNames", "io.helidon.http.HeaderNames");
|
||||
importMapping.put("Parameters", "io.helidon.common.parameters.Parameters");
|
||||
importMapping.put("Value", "io.helidon.common.mapper.Value");
|
||||
importMapping.put("MultiPart", "io.helidon.http.media.multipart.MultiPart");
|
||||
importMapping.put("Path", "java.nio.file.Path");
|
||||
importMapping.put("Files", "java.nio.file.Files");
|
||||
importMapping.put("StandardCopyOption", "java.nio.file.StandardCopyOption");
|
||||
importMapping.put("UncheckedIOException", "java.io.UncheckedIOException");
|
||||
importMapping.put("Status", "io.helidon.http.Status");
|
||||
importMapping.put("Objects", "java.util.Objects");
|
||||
importMapping.put("Valid", "jakarta.validation.Valid");
|
||||
importMapping.put("List", "java.util.List");
|
||||
importMapping.put("Map", "java.util.Map");
|
||||
}
|
||||
supportingFiles.clear();
|
||||
dateLibrary = "java8";
|
||||
|
||||
@ -190,13 +214,15 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator),
|
||||
"Main.java"));
|
||||
unmodifiable.add(new SupportingFile("validatorUtils.mustache",
|
||||
(sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator),
|
||||
"ValidatorUtils.java"));
|
||||
apiFolder(),
|
||||
"ValidatorUtils.java"));
|
||||
if (helidonMajorVersion > 3 && useAbstractClass) {
|
||||
unmodifiable.add(new SupportingFile("partsUtils.mustache",
|
||||
apiFolder(),
|
||||
"PartsUtils.java"));
|
||||
}
|
||||
if (useAbstractClass) {
|
||||
importMapping.put("Map", "java.util.Map");
|
||||
importMapping.put("HashMap", "java.util.HashMap");
|
||||
importMapping.put("InputStream", "java.io.InputStream");
|
||||
importMapping.put("ReadableBodyPart", "io.helidon.media.multipart.ReadableBodyPart");
|
||||
importMapping.put("ArrayList", "java.util.ArrayList");
|
||||
importMapping.put("ByteArrayOutputStream", "java.io.ByteArrayOutputStream");
|
||||
importMapping.put("DataChunk", "io.helidon.common.http.DataChunk");
|
||||
@ -204,7 +230,15 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
importMapping.put("IOException", "java.io.IOException");
|
||||
importMapping.put("ByteArrayInputStream", "java.io.ByteArrayInputStream");
|
||||
}
|
||||
importMapping.put("Handler", "io.helidon.webserver.Handler");
|
||||
importMapping.put("Map", "java.util.Map");
|
||||
importMapping.put("ReadableBodyPart", // use the old ReadableBodyPart name for backward compatibility
|
||||
(helidonMajorVersion <= 3)
|
||||
? "io.helidon.media.multipart.ReadableBodyPart"
|
||||
: "io.helidon.http.media.multipart.ReadablePart");
|
||||
importMapping.put("Handler", "io.helidon.webserver." + (helidonMajorVersion != 3 ? "http." : "") + "Handler");
|
||||
importMapping.put("GenericType", "io.helidon.common.GenericType");
|
||||
importMapping.put("GenericTypes", modelPackage + ".GenericTypes");
|
||||
importMapping.put("Optional", "java.util.Optional");
|
||||
processSupportingFiles(modifiable, unmodifiable);
|
||||
} else {
|
||||
LOGGER.error("Unknown library option (-l/--library): {}", getLibrary());
|
||||
@ -255,6 +289,13 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenResponse fromResponse(String responseCode, ApiResponse response) {
|
||||
var result = super.fromResponse(responseCode, response);
|
||||
result.vendorExtensions.put(X_RESULT_STATUS_DECL, statusDeclaration(result.code));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
|
||||
CodegenOperation codegenOperation = super.fromOperation(path, httpMethod, operation, servers);
|
||||
@ -266,8 +307,64 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
codegenOperation.imports.add("Jsonb");
|
||||
codegenOperation.imports.add("JsonbBuilder");
|
||||
}
|
||||
if (codegenOperation.bodyParam != null) {
|
||||
codegenOperation.imports.add("Handler");
|
||||
if (helidonMajorVersion > 3) {
|
||||
codegenOperation.imports.add("Status");
|
||||
codegenOperation.imports.add("HexFormat");
|
||||
if (codegenOperation.allParams.stream()
|
||||
.anyMatch(p -> p.isContainer)) {
|
||||
codegenOperation.imports.add("Collectors");
|
||||
}
|
||||
if (codegenOperation.allParams.stream()
|
||||
.anyMatch(p -> p.dataType.contains("@Valid"))) {
|
||||
codegenOperation.imports.add("Valid");
|
||||
}
|
||||
}
|
||||
if (codegenOperation.getHasBodyParam()) {
|
||||
if (helidonMajorVersion == 3) {
|
||||
codegenOperation.imports.add("Handler");
|
||||
} else {
|
||||
if (codegenOperation.bodyParam.isContainer) {
|
||||
codegenOperation.imports.add("GenericTypes");
|
||||
}
|
||||
if (codegenOperation.bodyParam.isFile) {
|
||||
codegenOperation.imports.add("InputStream");
|
||||
codegenOperation.imports.add("Path");
|
||||
codegenOperation.imports.add("Files");
|
||||
codegenOperation.imports.add("IOException");
|
||||
codegenOperation.imports.add("UncheckedIOException");
|
||||
codegenOperation.imports.add("Status");
|
||||
codegenOperation.imports.add("Objects");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (codegenOperation.getHasHeaderParams()) {
|
||||
if (helidonMajorVersion > 3) {
|
||||
codegenOperation.imports.add("Headers");
|
||||
codegenOperation.imports.add("HeaderNames");
|
||||
}
|
||||
}
|
||||
if (codegenOperation.isMultipart) {
|
||||
if (helidonMajorVersion > 3) {
|
||||
codegenOperation.imports.add("MultiPart");
|
||||
if (useAbstractClass) {
|
||||
codegenOperation.formParams.forEach(fp -> {
|
||||
if (!fp.required) {
|
||||
codegenOperation.imports.add("Optional");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (codegenOperation.getHasFormParams()) {
|
||||
if (helidonMajorVersion > 3) {
|
||||
codegenOperation.imports.add("Parameters");
|
||||
codegenOperation.imports.add("Value");
|
||||
codegenOperation.formParams.forEach(fp -> {
|
||||
if (!fp.required) {
|
||||
codegenOperation.imports.add("Optional");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (codegenOperation.queryParams.size() > 0 && useAbstractClass) {
|
||||
codegenOperation.imports.add("List");
|
||||
@ -278,11 +375,23 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
codegenOperation.imports.add("InputStream");
|
||||
codegenOperation.imports.add("ReadableBodyPart");
|
||||
codegenOperation.imports.add("ArrayList");
|
||||
codegenOperation.imports.add("DataChunk");
|
||||
codegenOperation.imports.add("ByteArrayOutputStream");
|
||||
if (helidonMajorVersion <= 3) {
|
||||
codegenOperation.imports.add("DataChunk");
|
||||
codegenOperation.imports.add("ByteArrayOutputStream");
|
||||
codegenOperation.imports.add("ByteArrayInputStream");
|
||||
}
|
||||
codegenOperation.imports.add("IOException");
|
||||
codegenOperation.imports.add("UncheckedIOException");
|
||||
codegenOperation.imports.add("ByteArrayInputStream");
|
||||
if (helidonMajorVersion > 3) {
|
||||
codegenOperation.imports.add("Parameters");
|
||||
}
|
||||
}
|
||||
if (!codegenOperation.formParams.isEmpty() && helidonMajorVersion > 3) {
|
||||
// Need to add it to both the API (abstract class or interface) and the implementation for Helidon 4 and later.
|
||||
codegenOperation.imports.add("ReadableBodyPart");
|
||||
}
|
||||
if (codegenOperation.isMultipart && helidonMajorVersion > 3) {
|
||||
codegenOperation.imports.add("Map");
|
||||
}
|
||||
}
|
||||
return codegenOperation;
|
||||
@ -315,11 +424,23 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
|
||||
|
||||
@Override
|
||||
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
|
||||
objs = super.postProcessOperationsWithModels(objs, allModels);
|
||||
OperationMap operations = objs.getOperations();
|
||||
if (HELIDON_MP.equals(getLibrary())) {
|
||||
return AbstractJavaJAXRSServerCodegen.jaxrsPostProcessOperations(objs);
|
||||
}
|
||||
if (operations != null && HELIDON_SE.equals(getLibrary())) {
|
||||
genericTypeDeclarations.register(objs);
|
||||
if (HELIDON_SE.equals(getLibrary())
|
||||
&& helidonMajorVersion > 3
|
||||
&& !genericTypeDeclarations.genericTypeDeclarations().isEmpty()) {
|
||||
additionalProperties.put(GenericTypeDeclarations.HAS_ATTR_NAME, true);
|
||||
additionalProperties.put(GenericTypeDeclarations.ATTR_NAME, genericTypeDeclarations.genericTypeDeclarations());
|
||||
if (helidonMajorVersion > 3) {
|
||||
supportingFiles.add(new SupportingFile("genericTypes.mustache", modelFolder(), "GenericTypes.java"));
|
||||
supportingFiles.add(new SupportingFile("hcollectors.mustache", apiFolder(), "HCollectors.java"));
|
||||
}
|
||||
}
|
||||
List<CodegenOperation> ops = operations.getOperation();
|
||||
for (CodegenOperation operation : ops) {
|
||||
if (operation.formParams.size() > 0) {
|
||||
|
@ -3,8 +3,6 @@ package {{package}};
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import {{rootJavaEEPackage}}.ws.rs.*;
|
||||
|
@ -16,10 +16,16 @@ import io.helidon.config.Config;
|
||||
{{#jsonb}}
|
||||
import io.helidon.media.jsonb.JsonbSupport;
|
||||
{{/jsonb}}
|
||||
{{#jackson}}
|
||||
import io.helidon.media.jackson.JacksonSupport;
|
||||
{{/jackson}}
|
||||
import io.helidon.webclient.WebClient;
|
||||
{{#jackson}}{{#x-helidon-v3}}{{!
|
||||
}}import io.helidon.media.jackson.JacksonSupport;
|
||||
{{/x-helidon-v3}}{{^x-helidon-v3}}{{!
|
||||
}}import io.helidon.http.media.jackson.JacksonSupport;
|
||||
{{/x-helidon-v3}}{{/jackson}}{{!
|
||||
}}{{#x-helidon-v3}}import io.helidon.webclient.WebClient;
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}import io.helidon.webclient.api.WebClient;
|
||||
import io.helidon.webclient.api.WebClientConfig;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
@ -170,13 +176,13 @@ public class ApiClient {
|
||||
* Builder for creating a new {@code ApiClient} instance.
|
||||
*
|
||||
* <p>
|
||||
* The builder accepts a {@link WebClient.Builder} via the {@code webClientBuilder} method but will provide a default one
|
||||
* The builder accepts a {@link WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder} via the {@code webClientBuilder} method but will provide a default one
|
||||
* using available configuration (the {@code client} node) and the base URI set in the OpenAPI document.
|
||||
* </p>
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
private WebClient.Builder webClientBuilder;
|
||||
private WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder webClientBuilder;
|
||||
private Config clientConfig;
|
||||
{{#jsonb}}
|
||||
private JsonbConfig jsonbConfig;
|
||||
@ -190,19 +196,19 @@ public class ApiClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code WebClient.Builder} which the {@code ApiClient.Builder} uses. Any previous setting is discarded.
|
||||
* Sets the {@code WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder} which the {@code ApiClient.Builder} uses. Any previous setting is discarded.
|
||||
*
|
||||
* @param webClientBuilder the {@code WebClient.Builder} to be used going forward
|
||||
* @param webClientBuilder the {@code WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder} to be used going forward
|
||||
* @return the updated builder
|
||||
*/
|
||||
public Builder webClientBuilder(WebClient.Builder webClientBuilder) {
|
||||
public Builder webClientBuilder(WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder webClientBuilder) {
|
||||
this.webClientBuilder = webClientBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client {@code Config} which the {@code ApiClient.Builder} uses in preparing a default {@code WebClient.Builder}.
|
||||
* The builder ignores this setting if you provide your own {@code WebClient.Builder} by invoking the
|
||||
* Sets the client {@code Config} which the {@code ApiClient.Builder} uses in preparing a default {@code WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder}.
|
||||
* The builder ignores this setting if you provide your own {@code WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder} by invoking the
|
||||
* {@code webClientBuilder} method.
|
||||
*
|
||||
* @param clientConfig the {@code Config} node containing client settings
|
||||
@ -217,7 +223,7 @@ public class ApiClient {
|
||||
* @return the previously-stored web client builder or, if none, a default one using the provided or defaulted
|
||||
* client configuration
|
||||
*/
|
||||
public WebClient.Builder webClientBuilder() {
|
||||
public WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder webClientBuilder() {
|
||||
if (webClientBuilder == null) {
|
||||
webClientBuilder = defaultWebClientBuilder();
|
||||
}
|
||||
@ -249,8 +255,8 @@ public class ApiClient {
|
||||
}
|
||||
{{/jackson}}
|
||||
|
||||
private WebClient.Builder defaultWebClientBuilder() {
|
||||
WebClient.Builder defaultWebClientBuilder = WebClient.builder()
|
||||
private WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder defaultWebClientBuilder() {
|
||||
WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder defaultWebClientBuilder = WebClient.builder()
|
||||
.baseUri("{{basePath}}")
|
||||
.config(clientConfig());
|
||||
{{#jsonb}}
|
||||
@ -260,7 +266,7 @@ public class ApiClient {
|
||||
{{/jsonb}}
|
||||
{{#jackson}}
|
||||
defaultWebClientBuilder.addMediaSupport(objectMapper == null
|
||||
? JacksonSupport.create()
|
||||
? JacksonSupport.create({{^x-helidon-v3}}clientConfig(){{/x-helidon-v3}})
|
||||
: JacksonSupport.create(objectMapper));
|
||||
{{/jackson}}
|
||||
return defaultWebClientBuilder;
|
||||
|
@ -1,11 +1,15 @@
|
||||
{{>licenseInfo}}
|
||||
package {{invokerPackage}};
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
{{#x-helidon-v3}}import java.util.concurrent.ExecutionException;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.common.reactive.Single;
|
||||
{{#x-helidon-v3}}import io.helidon.common.reactive.Single;
|
||||
import io.helidon.webclient.WebClientResponse;
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}import io.helidon.webclient.api.HttpClientResponse;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
{{#appName}}
|
||||
/**
|
||||
@ -18,17 +22,17 @@ import io.helidon.webclient.WebClientResponse;
|
||||
{{/appName}}
|
||||
public interface ApiResponse<T> {
|
||||
|
||||
static <T> ApiResponse<T> create(GenericType<T> responseType, Single<WebClientResponse> webClientResponse) {
|
||||
static <T> ApiResponse<T> create(GenericType<T> responseType, {{#x-helidon-v3}}Single<WebClientResponse>{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientResponse{{/x-helidon-v3}} webClientResponse) {
|
||||
return new ApiResponseBase<>(responseType, webClientResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns reactive access to the {@link WebClientResponse} describing the response from the server
|
||||
* @returns reactive access to the {@link {{#x-helidon-v3}}Web{{/x-helidon-v3}}{{^x-helidon-v3}}Http{{/x-helidon-v3}}ClientResponse} describing the response from the server
|
||||
*/
|
||||
Single<WebClientResponse> webClientResponse();
|
||||
{{#x-helidon-v3}}Single<WebClientResponse>{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientResponse{{/x-helidon-v3}} webClientResponse();
|
||||
|
||||
/**
|
||||
* @return reactive access to the value returned in the response from the server
|
||||
* @return {{#x-helidon-v3}}reactive {{/x-helidon-v3}}access to the value returned in the response from the server
|
||||
*/
|
||||
Single<T> result() throws ExecutionException, InterruptedException;
|
||||
{{#x-helidon-v3}}Single<T>{{/x-helidon-v3}}{{^x-helidon-v3}}T{{/x-helidon-v3}} result(){{#x-helidon-v3}} throws ExecutionException, InterruptedException{{/x-helidon-v3}};
|
||||
}
|
||||
|
@ -1,11 +1,15 @@
|
||||
{{>licenseInfo}}
|
||||
package {{invokerPackage}};
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
{{#x-helidon-v3}}import java.util.concurrent.ExecutionException;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.common.reactive.Single;
|
||||
{{#x-helidon-v3}}import io.helidon.common.reactive.Single;
|
||||
import io.helidon.webclient.WebClientResponse;
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}import io.helidon.webclient.api.HttpClientResponse;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
{{#appName}}
|
||||
/**
|
||||
@ -16,21 +20,21 @@ import io.helidon.webclient.WebClientResponse;
|
||||
{{/appName}}
|
||||
class ApiResponseBase<T> implements ApiResponse<T> {
|
||||
|
||||
private final Single<WebClientResponse> webClientResponse;
|
||||
private final {{#x-helidon-v3}}Single<Web{{/x-helidon-v3}}{{^x-helidon-v3}}Http{{/x-helidon-v3}}ClientResponse{{#x-helidon-v3}}>{{/x-helidon-v3}} webClientResponse;
|
||||
private final GenericType<T> responseType;
|
||||
|
||||
protected ApiResponseBase(GenericType<T> responseType, Single<WebClientResponse> webClientResponse) {
|
||||
protected ApiResponseBase(GenericType<T> responseType, {{#x-helidon-v3}}Single<Web{{/x-helidon-v3}}{{^x-helidon-v3}}Http{{/x-helidon-v3}}ClientResponse{{#x-helidon-v3}}>{{/x-helidon-v3}} webClientResponse) {
|
||||
this.webClientResponse = webClientResponse;
|
||||
this.responseType = responseType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<WebClientResponse> webClientResponse() {
|
||||
public {{#x-helidon-v3}}Single<WebClientResponse>{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientResponse{{/x-helidon-v3}} webClientResponse() {
|
||||
return webClientResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<T> result() throws ExecutionException, InterruptedException {
|
||||
return webClientResponse.get().content().as(responseType);
|
||||
public {{#x-helidon-v3}}Single<{{/x-helidon-v3}}T{{#x-helidon-v3}}>{{/x-helidon-v3}} result() {{#x-helidon-v3}}throws ExecutionException, InterruptedException{{/x-helidon-v3}} {
|
||||
return webClientResponse.{{#x-helidon-v3}}get().content(){{/x-helidon-v3}}{{^x-helidon-v3}}entity(){{/x-helidon-v3}}.as(responseType);
|
||||
}
|
||||
}
|
@ -8,11 +8,11 @@
|
||||
## Overview
|
||||
This project was generated using the Helidon OpenAPI Generator.
|
||||
|
||||
The generated classes use the programming model from the Helidon WebClient implementation, primarily the `WebClient` interface and its
|
||||
`WebClient.Builder` class. Refer to the Helidon WebClient documentation for complete information about them.
|
||||
The generated classes use the programming model from the Helidon WebClient implementation, primarily the `WebClient` interface and its{{^x-helidon-v3}} associated {{/x-helidon-v3}}
|
||||
`WebClient{{^x-helidon-v3}}Client{{/x-helidon-v3}}.Builder` class. Refer to the Helidon WebClient documentation for complete information about them.
|
||||
|
||||
## Using the Generated Classes and Interfaces
|
||||
The generated `ApiClient` class wraps a `WebClient` instance. Similarly, the `ApiClient.Builder` class wraps the `WebClient.Builder` class.
|
||||
The generated `ApiClient` class wraps a `WebClient` instance. Similarly, the `ApiClient.Builder` class wraps the `WebClient{{^x-helidon-v3}}Config{{/x-helidon-v3}}.Builder` class.
|
||||
|
||||
The generated `xxxApi` interfaces and `xxxApiImpl` classes make it very simple for your code to send requests (with input parameters) to the remote service which the OpenAPI document describes and to process the response (with output values) from the remote service.
|
||||
|
||||
|
@ -12,14 +12,27 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
{{/jackson}}
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.common.http.MediaType;
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}import io.helidon.common.http.MediaType;
|
||||
import io.helidon.common.reactive.Single;
|
||||
{{/x-helidon-v3}}{{^x-helidon-v3}}{{!
|
||||
}}import io.helidon.common.media.type.MediaTypes;
|
||||
{{/x-helidon-v3}}
|
||||
import io.helidon.config.Config;
|
||||
import io.helidon.media.common.MediaSupport;
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}import io.helidon.media.common.MediaSupport;
|
||||
{{/x-helidon-v3}}{{^x-helidon-v3}}{{!
|
||||
}}import io.helidon.http.Method;
|
||||
import io.helidon.http.media.MediaSupport;
|
||||
{{/x-helidon-v3}}
|
||||
{{#jsonb}}import io.helidon.media.jsonb.JsonbSupport;{{/jsonb}}
|
||||
{{#jackson}}import io.helidon.media.jackson.JacksonSupport;{{/jackson}}
|
||||
import io.helidon.webclient.WebClientRequestBuilder;
|
||||
{{#jackson}}import io.helidon{{^x-helidon-v3}}.http{{/x-helidon-v3}}.media.jackson.JacksonSupport;{{/jackson}}
|
||||
{{#x-helidon-v3}}import io.helidon.webclient.WebClientRequestBuilder;
|
||||
import io.helidon.webclient.WebClientResponse;
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}import io.helidon.webclient.api.HttpClientRequest;
|
||||
import io.helidon.webclient.api.HttpClientResponse;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import {{invokerPackage}}.ApiClient;
|
||||
|
||||
@ -67,7 +80,7 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
{{#requiredParams}}
|
||||
Objects.requireNonNull({{paramName}}, "Required parameter '{{paramName}}' not specified");
|
||||
{{/requiredParams}}
|
||||
WebClientRequestBuilder webClientRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
|
||||
{{#x-helidon-v3}}WebClientRequestBuilder{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientRequest{{/x-helidon-v3}} webClientRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
|
||||
return {{operationId}}Submit(webClientRequestBuilder{{#allParams}}, {{paramName}}{{/allParams}});
|
||||
}
|
||||
|
||||
@ -78,11 +91,11 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
|
||||
{{/allParams}}
|
||||
* @return WebClientRequestBuilder for {{operationId}}
|
||||
* @return {{#x-helidon-v3}}WebClientRequestBuilder{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientRequest{{/x-helidon-v3}} for {{operationId}}
|
||||
*/
|
||||
protected WebClientRequestBuilder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {
|
||||
WebClientRequestBuilder webClientRequestBuilder = apiClient.webClient()
|
||||
.method("{{httpMethod}}");
|
||||
protected {{#x-helidon-v3}}WebClientRequestBuilder{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientRequest{{/x-helidon-v3}} {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {
|
||||
{{#x-helidon-v3}}WebClientRequestBuilder{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientRequest{{/x-helidon-v3}} webClientRequestBuilder = apiClient.webClient()
|
||||
.method({{#x-helidon-v3}}"{{/x-helidon-v3}}{{^x-helidon-v3}}Method.{{/x-helidon-v3}}{{httpMethod}}{{#x-helidon-v3}}"{{/x-helidon-v3}});
|
||||
|
||||
{{#hasQueryParams}}
|
||||
List<Pair> queryParams = new ArrayList<>();
|
||||
@ -119,10 +132,10 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
|
||||
{{/hasQueryParams}}
|
||||
{{#hasHeaderParams}}
|
||||
WebClientRequestHeaders headers = webClientRequestBuilder.headers();
|
||||
{{#x-helidon-v3}}Web{{/x-helidon-v3}}ClientRequestHeaders headers = webClientRequestBuilder.headers();
|
||||
{{#headerParams}}
|
||||
if ({{paramName}} != null) {
|
||||
headers.put("{{baseName}}", {{paramName}}{{^isString}}.toString(){{/isString}});
|
||||
headers.{{#x-helidon-v3}}put{{/x-helidon-v3}}{{^x-helidon-v3}}add(HeaderNames.create{{/x-helidon-v3}}("{{baseName}}"{{^x-helidon-v3}}){{/x-helidon-v3}}, {{paramName}}{{^isString}}.toString(){{/isString}});
|
||||
}
|
||||
{{/headerParams}}
|
||||
|
||||
@ -133,7 +146,7 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
.add("{{{baseName}}}=" + {{{paramName}}})
|
||||
{{/cookieParams}}
|
||||
.toString();
|
||||
webClientRequestBuilder.headers().add("Cookie", cookies);
|
||||
webClientRequestBuilder.headers().add({{^x-helidon-v3}}HeaderNames.create({{/x-helidon-v3}}"Cookie"{{^x-helidon-v3}}){{/x-helidon-v3}}, cookies);
|
||||
|
||||
{{/hasCookieParams}}
|
||||
{{#hasPathParams}}
|
||||
@ -145,12 +158,12 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
{{/hasPathParams}}
|
||||
webClientRequestBuilder.path({{#hasPathParams}}path{{/hasPathParams}}{{^hasPathParams}}"{{{path}}}"{{/hasPathParams}});
|
||||
{{#bodyParam}}
|
||||
webClientRequestBuilder.contentType(MediaType.APPLICATION_JSON);
|
||||
webClientRequestBuilder.contentType(MediaType{{^x-helidon-v3}}s{{/x-helidon-v3}}.APPLICATION_JSON);
|
||||
{{/bodyParam}}
|
||||
{{#hasFormParams}}
|
||||
webClientRequestBuilder.contentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
webClientRequestBuilder.contentType(MediaType{{^x-helidon-v3}}s{{/x-helidon-v3}}.APPLICATION_FORM_URLENCODED);
|
||||
{{/hasFormParams}}
|
||||
webClientRequestBuilder.accept(MediaType.APPLICATION_JSON);
|
||||
webClientRequestBuilder.accept(MediaType{{^x-helidon-v3}}s{{/x-helidon-v3}}.APPLICATION_JSON);
|
||||
|
||||
return webClientRequestBuilder;
|
||||
}
|
||||
@ -165,7 +178,7 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
{{/allParams}}
|
||||
* @return {@code {{>operationResponseSig}}} for the submitted request
|
||||
*/
|
||||
protected {{>operationResponseSig}} {{operationId}}Submit(WebClientRequestBuilder webClientRequestBuilder{{#allParams}}, {{{dataType}}} {{paramName}}{{/allParams}}) {
|
||||
protected {{>operationResponseSig}} {{operationId}}Submit({{#x-helidon-v3}}WebClientRequestBuilder{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientRequest{{/x-helidon-v3}} webClientRequestBuilder{{#allParams}}, {{{dataType}}} {{paramName}}{{/allParams}}) {
|
||||
{{#hasFormParams}}
|
||||
String formParams = new StringJoiner("&")
|
||||
{{#formParams}}
|
||||
@ -173,7 +186,7 @@ public class {{classname}}Impl implements {{classname}} {
|
||||
{{/formParams}}
|
||||
.toString();
|
||||
{{/hasFormParams}}
|
||||
Single<WebClientResponse> webClientResponse = webClientRequestBuilder.submit({{#bodyParam}}{{paramName}}{{/bodyParam}}{{#hasFormParams}}formParams{{/hasFormParams}});
|
||||
{{#x-helidon-v3}}Single<WebClientResponse>{{/x-helidon-v3}}{{^x-helidon-v3}}HttpClientResponse{{/x-helidon-v3}} webClientResponse = webClientRequestBuilder.{{#x-helidon-v3}}submit{{/x-helidon-v3}}{{^x-helidon-v3}}{{#bodyParam}}submit{{/bodyParam}}{{#hasFormParams}}submit{{/hasFormParams}}{{^bodyParam}}{{^hasFormParams}}request{{/hasFormParams}}{{/bodyParam}}{{/x-helidon-v3}}({{#bodyParam}}{{paramName}}{{/bodyParam}}{{#hasFormParams}}formParams{{/hasFormParams}});
|
||||
return ApiResponse.create(RESPONSE_TYPE_{{operationId}}, webClientResponse);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,183 @@
|
||||
{{>licenseInfo}}
|
||||
package {{package}};
|
||||
|
||||
import java.util.Objects;
|
||||
import {{invokerPackage}}.ApiResponse;
|
||||
|
||||
{{#jsonb}}
|
||||
import jakarta.json.bind.JsonbBuilder;
|
||||
{{/jsonb}}
|
||||
{{#jackson}}
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
{{/jackson}}
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.common.media.type.MediaType;
|
||||
import io.helidon.config.Config;
|
||||
import io.helidon.http.media.MediaSupport;
|
||||
{{#jsonb}}import io.helidon.http.media.jsonb.JsonbSupport;{{/jsonb}}
|
||||
{{#jackson}}import io.helidon.http.media.jackson.JacksonSupport;{{/jackson}}
|
||||
import io.helidon.webclient.api.HttpClientRequest;
|
||||
import io.helidon.webclient.api.HttpClientResponse;
|
||||
{{#hasHeaderParams}}
|
||||
import io.helidon.http.ClientRequestHeaders;
|
||||
import io.helidon.http.HeaderNames;
|
||||
{{/hasHeaderParams}}
|
||||
|
||||
import {{invokerPackage}}.ApiClient;
|
||||
|
||||
{{#x-helidon-implImports}}import {{import}};
|
||||
{{/x-helidon-implImports}}
|
||||
|
||||
{{#appName}}
|
||||
/**
|
||||
* {{{appName}}}
|
||||
*
|
||||
{{#appDescription}}
|
||||
* <p>{{{.}}}
|
||||
{{/appDescription}}
|
||||
*/
|
||||
{{/appName}}
|
||||
public class {{classname}}Impl implements {{classname}} {
|
||||
|
||||
private final ApiClient apiClient;
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
protected static final GenericType<{{>operationResponseTypeDecl}}> RESPONSE_TYPE_{{operationId}} = ResponseType.create({{#isArray}}List.class, {{/isArray}}{{#isMap}}Map.class, String.class, {{/isMap}}{{#returnBaseType}}{{returnBaseType}}{{/returnBaseType}}{{^returnBaseType}}Void{{/returnBaseType}}.class);
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {{classname}}Impl initialized with the specified {@link ApiClient}.
|
||||
*
|
||||
*/
|
||||
public static {{classname}}Impl create(ApiClient apiClient) {
|
||||
return new {{classname}}Impl(apiClient);
|
||||
}
|
||||
|
||||
protected {{classname}}Impl(ApiClient apiClient) {
|
||||
this.apiClient = apiClient;
|
||||
}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
{{#isDeprecated}}
|
||||
@Deprecated
|
||||
{{/isDeprecated}}
|
||||
@Override
|
||||
public {{>operationResponseSig}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {
|
||||
{{#requiredParams}}
|
||||
Objects.requireNonNull({{paramName}}, "Required parameter '{{paramName}}' not specified");
|
||||
{{/requiredParams}}
|
||||
HttpClientRequest clientRequest = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
|
||||
return {{operationId}}Submit(clientRequest{{#allParams}}, {{paramName}}{{/allParams}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@code WebClientRequestBuilder} for the {{operationId}} operation.
|
||||
* Optional customization point for subclasses.
|
||||
*
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
|
||||
{{/allParams}}
|
||||
* @return HttpClientRequest for {{operationId}}
|
||||
*/
|
||||
protected HttpClientRequest {{operationId}}HttpClientRequest({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {
|
||||
HttpClientRequest clientRequest = apiClient.webClient()
|
||||
.method("{{httpMethod}}");
|
||||
|
||||
{{#hasQueryParams}}
|
||||
List<Pair> queryParams = new ArrayList<>();
|
||||
{{#queryParams}}
|
||||
{{#collectionFormat}}
|
||||
queryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}}));
|
||||
{{/collectionFormat}}
|
||||
{{^collectionFormat}}
|
||||
{{#isDeepObject}}
|
||||
if ({{paramName}} != null) {
|
||||
{{#items.vars}}
|
||||
queryParams.addAll(ApiClient.parameterToPairs({{#isArray}}"csv", {{/isArray}}"{{baseName}}", {{paramName}}.{{getter}}()));
|
||||
{{/items.vars}}
|
||||
}
|
||||
{{/isDeepObject}}
|
||||
{{^isDeepObject}}
|
||||
{{#isExplode}}
|
||||
{{#hasVars}}
|
||||
{{#vars}}
|
||||
queryParams.addAll(ApiClent.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}()));
|
||||
{{/vars}}
|
||||
{{/hasVars}}
|
||||
{{^hasVars}}
|
||||
queryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
|
||||
{{/hasVars}}
|
||||
{{/isExplode}}
|
||||
{{^isExplode}}
|
||||
queryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}));
|
||||
{{/isExplode}}
|
||||
{{/isDeepObject}}
|
||||
{{/collectionFormat}}
|
||||
{{/queryParams}}
|
||||
queryParams.forEach(p -> clientRequest.queryParam(p.getName(), p.getValue()));
|
||||
|
||||
{{/hasQueryParams}}
|
||||
{{#hasHeaderParams}}
|
||||
ClientRequestHeaders headers = clientRequest.headers();
|
||||
{{#headerParams}}
|
||||
if ({{paramName}} != null) {
|
||||
headers.add(HeaderNames.create("{{baseName}}", {{paramName}}{{^isInteger}}{{^isString}}.toString(){{/isString}}{{/isInteger}});
|
||||
}
|
||||
{{/headerParams}}
|
||||
|
||||
{{/hasHeaderParams}}
|
||||
{{#hasCookieParams}}
|
||||
String cookies = new StringJoiner("; ")
|
||||
{{#cookieParams}}
|
||||
.add("{{{baseName}}}=" + {{{paramName}}})
|
||||
{{/cookieParams}}
|
||||
.toString();
|
||||
clientRequest.headers().add(HeaderNames.COOKIE, cookies);
|
||||
|
||||
{{/hasCookieParams}}
|
||||
clientRequest.path("{{{path}}}");
|
||||
{{#pathParams}}
|
||||
clientRequest.pathParam("{{{paramName}}}", {{paramName}});
|
||||
{{/pathParams}}
|
||||
{/hasPathParams}}
|
||||
{{#bodyParam}}
|
||||
clientRequest.contentType(MediaType.APPLICATION_JSON);
|
||||
{{/bodyParam}}
|
||||
{{#hasFormParams}}
|
||||
clientRequest.contentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
{{/hasFormParams}}
|
||||
clientRequest.accept(MediaType.APPLICATION_JSON);
|
||||
|
||||
return clientRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the request for the {{operationId}} operation.
|
||||
* Optional customization point for subclasses.
|
||||
*
|
||||
* @param clientRequest the request builder to use for submitting the request
|
||||
{{#allParams}}
|
||||
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
|
||||
{{/allParams}}
|
||||
* @return {@code {{>operationResponseSig}}} for the submitted request
|
||||
*/
|
||||
protected {{>operationResponseSig}} {{operationId}}Submit(WebClientRequestBuilder clientRequest{{#allParams}}, {{{dataType}}} {{paramName}}{{/allParams}}) {
|
||||
{{#hasFormParams}}
|
||||
String formParams = new StringJoiner("&")
|
||||
{{#formParams}}
|
||||
.add("{{{baseName}}}=" + {{paramName}})
|
||||
{{/formParams}}
|
||||
.toString();
|
||||
{{/hasFormParams}}
|
||||
HttpClientResponse clientResponse = clientRequest.submit({{#bodyParam}}{{paramName}}{{/bodyParam}}{{#hasFormParams}}formParams{{/hasFormParams}});
|
||||
// Single<WebClientResponse> webClientResponse = clientRequest.submit({{#bodyParam}}{{paramName}}{{/bodyParam}}{{#hasFormParams}}formParams{{/hasFormParams}});
|
||||
return ApiResponse.create(RESPONSE_TYPE_{{operationId}}, clientResponse);
|
||||
}
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
}
|
@ -16,8 +16,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.helidon.common.reactive.Single;
|
||||
{{#x-helidon-v3}}import io.helidon.common.reactive.Single;
|
||||
import io.helidon.webclient.WebClientResponse;
|
||||
{{/x-helidon-v3}}{{^x-helidon-v3}}{{!
|
||||
}}import io.helidon.webclient.api.HttpClientResponse;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
@ -45,8 +45,8 @@
|
||||
{{/openApiNullable}}
|
||||
{{#jackson}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.media</groupId>
|
||||
<artifactId>helidon-media-jackson</artifactId>
|
||||
<groupId>io.helidon.{{^x-helidon-v3}}http.{{/x-helidon-v3}}media</groupId>
|
||||
<artifactId>helidon-{{^x-helidon-v3}}http-{{/x-helidon-v3}}media-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
@ -63,8 +63,8 @@
|
||||
<artifactId>{{x-helidon-rootJavaEEDepPrefix}}.json.bind-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.media</groupId>
|
||||
<artifactId>helidon-media-jsonb</artifactId>
|
||||
<groupId>io.helidon.http.media</groupId>
|
||||
<artifactId>helidon-http1media-jsonb</artifactId>
|
||||
</dependency>
|
||||
{{/jsonb}}
|
||||
<dependency>
|
||||
|
@ -0,0 +1,549 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Oracle and/or its affiliates.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Commonly used status codes defined by HTTP, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10">HTTP/1.1 documentation</a>.
|
||||
* Additional status codes can be added by applications
|
||||
* by call {@link #create(int)} or {@link #create(int, String)} with unknown status code, or with text
|
||||
* that differs from the predefined status codes.
|
||||
* <p>
|
||||
* Although the constants are instances of this class, they can be compared using instance equality, as the only
|
||||
* way to obtain an instance is through methods {@link #create(int)} {@link #create(int, String)}, which ensures
|
||||
* the same instance is returned for known status codes and reason phrases.
|
||||
* <p>
|
||||
* A good reference is the IANA list of HTTP Status Codes (we may not cover all of them in this type):
|
||||
* <a href="https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml">IANA HTTP Status Codes</a>
|
||||
*/
|
||||
public class Status {
|
||||
/**
|
||||
* 100 Continue,
|
||||
* see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1.1">HTTP/1.1 documentations</a>.
|
||||
*/
|
||||
public static final Status CONTINUE_100 = new Status(100, "Continue", true);
|
||||
/**
|
||||
* 101 Switching Protocols,
|
||||
* see <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1.2">HTTP/1.1 documentations</a>.
|
||||
*/
|
||||
public static final Status SWITCHING_PROTOCOLS_101 = new Status(101, "Switching Protocols", true);
|
||||
/**
|
||||
* 200 OK, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status OK_200 = new Status(200, "OK", true);
|
||||
/**
|
||||
* 201 Created, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status CREATED_201 = new Status(201, "Created", true);
|
||||
/**
|
||||
* 202 Accepted, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3">HTTP/1.1 documentation</a>
|
||||
* .
|
||||
*/
|
||||
public static final Status ACCEPTED_202 = new Status(202, "Accepted", true);
|
||||
/**
|
||||
* 203 Non-Authoritative Information, see
|
||||
* <a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.4">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static final Status NON_AUTHORITATIVE_INFORMATION_203 = new Status(203, "Non-Authoritative Information", true);
|
||||
|
||||
/**
|
||||
* 204 No Content, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status NO_CONTENT_204 = new Status(204, "No Content", true);
|
||||
/**
|
||||
* 205 Reset Content, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.6">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status RESET_CONTENT_205 = new Status(205, "Reset Content", true);
|
||||
/**
|
||||
* 206 Reset Content, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.7">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status PARTIAL_CONTENT_206 = new Status(206, "Partial Content", true);
|
||||
/**
|
||||
* 207 Multi-Status, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc4918.html#section-13">RFC 4918 - HTTP Extensions for WebDAV</a>.
|
||||
*
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static final Status MULTI_STATUS_207 = new Status(207, "Multi-Status", true);
|
||||
/**
|
||||
* 301 Moved Permanently, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status MOVED_PERMANENTLY_301 = new Status(301, "Moved Permanently", true);
|
||||
/**
|
||||
* 302 Found, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status FOUND_302 = new Status(302, "Found", true);
|
||||
/**
|
||||
* 303 See Other, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status SEE_OTHER_303 = new Status(303, "See Other", true);
|
||||
/**
|
||||
* 304 Not Modified, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status NOT_MODIFIED_304 = new Status(304, "Not Modified", true);
|
||||
/**
|
||||
* 305 Use Proxy, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.6">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status USE_PROXY_305 = new Status(305, "Use Proxy", true);
|
||||
/**
|
||||
* 307 Temporary Redirect, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.8">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status TEMPORARY_REDIRECT_307 = new Status(307, "Temporary Redirect", true);
|
||||
/**
|
||||
* 308 Permanent Redirect, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc7538">HTTP Status Code 308 documentation</a>.
|
||||
*/
|
||||
public static final Status PERMANENT_REDIRECT_308 = new Status(308, "Permanent Redirect", true);
|
||||
/**
|
||||
* 400 Bad Request, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status BAD_REQUEST_400 = new Status(400, "Bad Request", true);
|
||||
/**
|
||||
* 401 Unauthorized, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status UNAUTHORIZED_401 = new Status(401, "Unauthorized", true);
|
||||
/**
|
||||
* 402 Payment Required, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status PAYMENT_REQUIRED_402 = new Status(402, "Payment Required", true);
|
||||
/**
|
||||
* 403 Forbidden, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status FORBIDDEN_403 = new Status(403, "Forbidden", true);
|
||||
/**
|
||||
* 404 Not Found, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status NOT_FOUND_404 = new Status(404, "Not Found", true);
|
||||
/**
|
||||
* 405 Method Not Allowed, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status METHOD_NOT_ALLOWED_405 = new Status(405, "Method Not Allowed", true);
|
||||
/**
|
||||
* 406 Not Acceptable, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.7">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status NOT_ACCEPTABLE_406 = new Status(406, "Not Acceptable", true);
|
||||
/**
|
||||
* 407 Proxy Authentication Required, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.8">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status PROXY_AUTHENTICATION_REQUIRED_407 = new Status(407, "Proxy Authentication Required", true);
|
||||
/**
|
||||
* 408 Request Timeout, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status REQUEST_TIMEOUT_408 = new Status(408, "Request Timeout", true);
|
||||
/**
|
||||
* 409 Conflict, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status CONFLICT_409 = new Status(409, "Conflict", true);
|
||||
/**
|
||||
* 410 Gone, see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status GONE_410 = new Status(410, "Gone", true);
|
||||
/**
|
||||
* 411 Length Required, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.12">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status LENGTH_REQUIRED_411 = new Status(411, "Length Required", true);
|
||||
/**
|
||||
* 412 Precondition Failed, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status PRECONDITION_FAILED_412 = new Status(412, "Precondition Failed", true);
|
||||
/**
|
||||
* 413 Request Entity Too Large, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status REQUEST_ENTITY_TOO_LARGE_413 = new Status(413, "Request Entity Too Large", true);
|
||||
/**
|
||||
* 414 Request-URI Too Long, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.15">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status REQUEST_URI_TOO_LONG_414 = new Status(414, "Request-URI Too Long", true);
|
||||
/**
|
||||
* 415 Unsupported Media Type, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.16">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status UNSUPPORTED_MEDIA_TYPE_415 = new Status(415, "Unsupported Media Type", true);
|
||||
/**
|
||||
* 416 Requested Range Not Satisfiable, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.17">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status REQUESTED_RANGE_NOT_SATISFIABLE_416 = new Status(416, "Requested Range Not Satisfiable", true);
|
||||
/**
|
||||
* 417 Expectation Failed, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.18">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status EXPECTATION_FAILED_417 = new Status(417, "Expectation Failed", true);
|
||||
/**
|
||||
* 418 I'm a teapot, see
|
||||
* <a href="https://tools.ietf.org/html/rfc2324#section-2.3.2">Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)</a>.
|
||||
*/
|
||||
public static final Status I_AM_A_TEAPOT_418 = new Status(418, "I'm a teapot", true);
|
||||
/**
|
||||
* Misdirected request, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-421-misdirected-request">RFC 9110 - Http Semantics</a>.
|
||||
*/
|
||||
public static final Status MISDIRECTED_REQUEST_421 = new Status(421, "Misdirected Request", true);
|
||||
/**
|
||||
* Unprocessable content, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-422-unprocessable-content">RFC 9110 - Http Semantics</a>.
|
||||
*/
|
||||
public static final Status UNPROCESSABLE_CONTENT_422 = new Status(422, "Unprocessable Content", true);
|
||||
/**
|
||||
* Locked, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc4918.html#page-78">RFC 4918 - HTTP Extensions for WebDAV</a>.
|
||||
*/
|
||||
public static final Status LOCKED_423 = new Status(423, "Locked", true);
|
||||
/**
|
||||
* Failed dependency, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc4918.html#section-11.4">RFC 4918 - HTTP Extensions for WebDAV</a>.
|
||||
*/
|
||||
public static final Status FAILED_DEPENDENCY_424 = new Status(424, "Failed Dependency", true);
|
||||
/**
|
||||
* Upgrade required, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc9110.html#name-426-upgrade-required">RFC 9110 - Http Semantics</a>.
|
||||
*/
|
||||
public static final Status UPGRADE_REQUIRED_426 = new Status(426, "Upgrade Required", true);
|
||||
/**
|
||||
* Precondition required, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc6585.html#page-2">RFC 6585 - Additional HTTP Status Codes</a>.
|
||||
*/
|
||||
public static final Status PRECONDITION_REQUIRED_428 = new Status(428, "Precondition Required", true);
|
||||
/**
|
||||
* Too many requests, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc6585.html#page-3">RFC 6585 - Additional HTTP Status Codes</a>.
|
||||
*/
|
||||
public static final Status TOO_MANY_REQUESTS_429 = new Status(429, "Too Many Requests", true);
|
||||
/**
|
||||
* 500 Internal Server Error, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status INTERNAL_SERVER_ERROR_500 = new Status(500, "Internal Server Error", true);
|
||||
/**
|
||||
* 501 Not Implemented, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.2">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status NOT_IMPLEMENTED_501 = new Status(501, "Not Implemented", true);
|
||||
/**
|
||||
* 502 Bad Gateway, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status BAD_GATEWAY_502 = new Status(502, "Bad Gateway", true);
|
||||
/**
|
||||
* 503 Service Unavailable, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4">HTTP/1.1 documentation</a>.
|
||||
*/
|
||||
public static final Status SERVICE_UNAVAILABLE_503 = new Status(503, "Service Unavailable", true);
|
||||
/**
|
||||
* 504 Gateway Timeout, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.5">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final Status GATEWAY_TIMEOUT_504 = new Status(504, "Gateway Timeout", true);
|
||||
/**
|
||||
* 505 HTTP Version Not Supported, see
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.6">HTTP/1.1 documentation</a>.
|
||||
*
|
||||
* @since 3.0.3
|
||||
*/
|
||||
public static final Status HTTP_VERSION_NOT_SUPPORTED_505 = new Status(505, "HTTP Version Not Supported", true);
|
||||
/**
|
||||
* 507 Insufficient Storage, see
|
||||
* <a href="http://www.ietf.org/rfc/rfc4918.txt">WebDAV documentation</a>.
|
||||
*
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static final Status INSUFFICIENT_STORAGE_507 = new Status(507, "Insufficient Storage", true);
|
||||
/**
|
||||
* 508 Loop Detected, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc5842#section-7.2">RFC 5842 - Bindings for the Constrained Application Protocol (CoAP)</a>.
|
||||
*
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static final Status LOOP_DETECTED_508 = new Status(508, "Loop Detected", true);
|
||||
|
||||
/**
|
||||
* 510 Not Extended, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc2774#section-7">RFC 2774 - An HTTP Extension Framework</a>.
|
||||
*
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static final Status NOT_EXTENDED_510 = new Status(510, "Not Extended", true);
|
||||
|
||||
/**
|
||||
* 511 Network Authentication Required, see
|
||||
* <a href="https://www.rfc-editor.org/rfc/rfc6585#section-6">RFC 6585 - Additional HTTP Status Codes</a>.
|
||||
*
|
||||
* @since 4.0.6
|
||||
*/
|
||||
public static final Status NETWORK_AUTHENTICATION_REQUIRED_511 = new Status(511, "Network Authentication Required", true);
|
||||
|
||||
|
||||
static {
|
||||
// THIS MUST BE AFTER THE LAST CONSTANT
|
||||
StatusHelper.statusesDone();
|
||||
}
|
||||
|
||||
private final int code;
|
||||
private final String reason;
|
||||
private final Family family;
|
||||
private final String codeText;
|
||||
private final String stringValue;
|
||||
|
||||
private JavaHelidonHttpStatus(int statusCode, String reasonPhrase, boolean instance) {
|
||||
this.code = statusCode;
|
||||
this.reason = reasonPhrase;
|
||||
this.family = Family.of(statusCode);
|
||||
this.codeText = String.valueOf(code);
|
||||
this.stringValue = code + " " + reason;
|
||||
|
||||
if (instance) {
|
||||
StatusHelper.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
private JavaHelidonHttpStatus(int statusCode, String reasonPhrase, Family family, String codeText) {
|
||||
// for custom codes
|
||||
this.code = statusCode;
|
||||
this.reason = reasonPhrase;
|
||||
this.family = family;
|
||||
this.codeText = codeText;
|
||||
this.stringValue = code + " " + reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numerical status code into the corresponding Status.
|
||||
* <p>
|
||||
* For an unknown code, an ad-hoc {@link Status} is created.
|
||||
*
|
||||
* @param statusCode the numerical status code
|
||||
* @return the matching Status; either a constant from this class, or an ad-hoc {@link Status}
|
||||
*/
|
||||
public static Status create(int statusCode) {
|
||||
Status found = StatusHelper.find(statusCode);
|
||||
|
||||
if (found == null) {
|
||||
return createNew(Family.of(statusCode), statusCode, "", String.valueOf(statusCode));
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numerical status code into the corresponding Status.
|
||||
* <p>
|
||||
* It either returns an existing {@link Status} constant if possible.
|
||||
* For an unknown code, or code/reason phrase combination it creates
|
||||
* an ad-hoc {@link Status}.
|
||||
*
|
||||
* @param statusCode the numerical status code
|
||||
* @param reasonPhrase the reason phrase; if {@code null} or a known reason phrase, an instance with the default
|
||||
* phrase is returned; otherwise, a new instance is returned
|
||||
* @return the matching Status
|
||||
*/
|
||||
public static Status create(int statusCode, String reasonPhrase) {
|
||||
Status found = StatusHelper.find(statusCode);
|
||||
if (found == null) {
|
||||
return createNew(Family.of(statusCode), statusCode, reasonPhrase, String.valueOf(statusCode));
|
||||
}
|
||||
if (reasonPhrase == null) {
|
||||
return found;
|
||||
}
|
||||
if (found.reasonPhrase().equalsIgnoreCase(reasonPhrase)) {
|
||||
return found;
|
||||
}
|
||||
return createNew(found.family(), statusCode, reasonPhrase, found.codeText());
|
||||
}
|
||||
|
||||
private static Status createNew(Family family, int statusCode, String reasonPhrase, String codeText) {
|
||||
return new Status(statusCode, reasonPhrase, family, codeText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated integer value representing the status code.
|
||||
*
|
||||
* @return the integer value representing the status code.
|
||||
*/
|
||||
public int code() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class of status code.
|
||||
*
|
||||
* @return the class of status code.
|
||||
*/
|
||||
public Family family() {
|
||||
return family;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reason phrase.
|
||||
*
|
||||
* @return the reason phrase.
|
||||
*/
|
||||
public String reasonPhrase() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Text of the {@link #code()}.
|
||||
*
|
||||
* @return code string (number as a string)
|
||||
*/
|
||||
public String codeText() {
|
||||
return codeText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response status as string.
|
||||
*
|
||||
* @return the response status string in the form of a partial HTTP response status line,
|
||||
* i.e. {@code "Status-Code SP Reason-Phrase"}.
|
||||
*/
|
||||
public String toString() {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Text of the status as used in HTTP/1, such as "200 OK".
|
||||
*
|
||||
* @return text of this status
|
||||
*/
|
||||
public String text() {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Status status = (Status) o;
|
||||
return code == status.code && reason.equals(status.reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(code, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration representing the class of status code. Family is used
|
||||
* here since class is overloaded in Java.
|
||||
* <p>
|
||||
* Copied from JAX-RS.
|
||||
*/
|
||||
public enum Family {
|
||||
|
||||
/**
|
||||
* {@code 1xx} HTTP status codes.
|
||||
*/
|
||||
INFORMATIONAL,
|
||||
/**
|
||||
* {@code 2xx} HTTP status codes.
|
||||
*/
|
||||
SUCCESSFUL,
|
||||
/**
|
||||
* {@code 3xx} HTTP status codes.
|
||||
*/
|
||||
REDIRECTION,
|
||||
/**
|
||||
* {@code 4xx} HTTP status codes.
|
||||
*/
|
||||
CLIENT_ERROR,
|
||||
/**
|
||||
* {@code 5xx} HTTP status codes.
|
||||
*/
|
||||
SERVER_ERROR,
|
||||
/**
|
||||
* Other, unrecognized HTTP status codes.
|
||||
*/
|
||||
OTHER;
|
||||
|
||||
/**
|
||||
* Get the family for the response status code.
|
||||
*
|
||||
* @param statusCode response status code to get the family for.
|
||||
* @return family of the response status code.
|
||||
*/
|
||||
public static Family of(int statusCode) {
|
||||
return switch (statusCode / 100) {
|
||||
case 1 -> Family.INFORMATIONAL;
|
||||
case 2 -> Family.SUCCESSFUL;
|
||||
case 3 -> Family.REDIRECTION;
|
||||
case 4 -> Family.CLIENT_ERROR;
|
||||
case 5 -> Family.SERVER_ERROR;
|
||||
default -> Family.OTHER;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -5,25 +5,39 @@ package {{package}};
|
||||
|
||||
{{#useAbstractClass}}
|
||||
import java.util.Optional;
|
||||
{{#x-helidon-v3}}
|
||||
import java.util.logging.Logger;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
{{#x-helidon-v3}}
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.common.reactive.Single;
|
||||
{{/x-helidon-v3}}
|
||||
{{/useAbstractClass}}
|
||||
import io.helidon.webserver.Routing;
|
||||
import io.helidon.webserver.ServerRequest;
|
||||
import io.helidon.webserver.ServerResponse;
|
||||
import io.helidon.webserver.Service;
|
||||
import io.helidon.webserver.{{#x-helidon-v3}}Routing{{/x-helidon-v3}}{{^x-helidon-v3}}http.HttpRules{{/x-helidon-v3}};
|
||||
import io.helidon.webserver.{{^x-helidon-v3}}http.{{/x-helidon-v3}}ServerRequest;
|
||||
import io.helidon.webserver.{{^x-helidon-v3}}http.{{/x-helidon-v3}}ServerResponse;
|
||||
import io.helidon.webserver.{{^x-helidon-v3}}http.Http{{/x-helidon-v3}}Service;
|
||||
|
||||
{{#operations}}
|
||||
{{^useAbstractClass}}public interface {{classname}} extends Service { {{/useAbstractClass}}
|
||||
{{#useAbstractClass}}public abstract class {{classname}} implements Service {
|
||||
{{^x-helidon-v3}}
|
||||
@io.helidon.common.Generated(value = "{{additionalProperties.generatorClass}}",
|
||||
trigger = "tag = '{{baseName}}'",
|
||||
version = "{{generatorVersion}}")
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^useAbstractClass}}public interface {{classname}} extends {{^x-helidon-v3}}Http{{/x-helidon-v3}}Service {{=<% %>=}}{<%#x-helidon-v3%> <%/x-helidon-v3%><%={{ }}=%>
|
||||
{{/useAbstractClass}}{{!
|
||||
}}{{#useAbstractClass}}public abstract class {{classname}} implements {{^x-helidon-v3}}Http{{/x-helidon-v3}}Service {
|
||||
|
||||
protected static final Logger LOGGER = Logger.getLogger({{classname}}.class.getName());
|
||||
{{#jackson}}
|
||||
{{#x-helidon-v3}} protected static final Logger LOGGER = Logger.getLogger({{classname}}.class.getName());
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{#jackson}}
|
||||
protected static final ObjectMapper MAPPER = JsonProvider.objectMapper();{{/jackson}}
|
||||
{{#jsonb}}
|
||||
protected static final Jsonb JSONB = JsonbBuilder.create();{{/jsonb}}
|
||||
protected static final Jsonb JSONB = JsonbBuilder.create();{{/jsonb}}{{!
|
||||
}}{{^x-helidon-v3}}
|
||||
{{#operations}}{{#operation}} protected {{#lambda.titlecase}}{{operationId}}Op{{/lambda.titlecase}} {{operationId}}Op = create{{#lambda.titlecase}}{{operationId}}Op{{/lambda.titlecase}}();
|
||||
{{/operation}}{{/operations}}{{/x-helidon-v3}}
|
||||
{{/useAbstractClass}}
|
||||
|
||||
/**
|
||||
@ -31,48 +45,87 @@ import io.helidon.webserver.Service;
|
||||
* @param rules the routing rules.
|
||||
*/
|
||||
@Override
|
||||
{{#useAbstractClass}}public{{/useAbstractClass}}{{^useAbstractClass}}default{{/useAbstractClass}} void update(Routing.Rules rules) {
|
||||
{{#useAbstractClass}}public{{/useAbstractClass}}{{^useAbstractClass}}default{{/useAbstractClass}} void {{#x-helidon-v3}}update{{/x-helidon-v3}}{{^x-helidon-v3}}routing{{/x-helidon-v3}}({{#x-helidon-v3}}Routing.{{/x-helidon-v3}}{{^x-helidon-v3}}Http{{/x-helidon-v3}}Rules rules) {
|
||||
{{#operation}}
|
||||
rules.{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}}("{{{path}}}", {{!
|
||||
}}{{#bodyParam}}{{#isModel}}Handler.create({{{dataType}}}.class, {{/isModel}}this::{{{operationId}}}){{#isModel}}){{/isModel}}{{/bodyParam}}{{!
|
||||
}}{{^bodyParam}}this::{{{operationId}}}){{/bodyParam}};
|
||||
rules.{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}}("{{#x-helidon-v3}}{{{path}}}{{/x-helidon-v3}}{{^x-helidon-v3}}{{{vendorExtensions.x-helidon-pathSuffix}}}{{/x-helidon-v3}}", {{!
|
||||
|
||||
See comment below about the signatures of the generated handler methods for v3 vs. v4.
|
||||
|
||||
}}{{#x-helidon-v3}}{{#bodyParam}}{{#isModel}}Handler.create({{{dataType}}}.class, {{/isModel}}this::{{{operationId}}}){{#isModel}}){{/isModel}}{{/bodyParam}}{{!
|
||||
}}{{^bodyParam}}this::{{{operationId}}}){{/bodyParam}}{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}this::{{{operationId}}}){{/x-helidon-v3}};
|
||||
{{/operation}}
|
||||
}
|
||||
{{#useAbstractClass}}{{#isFormParamsFunctions}}
|
||||
{{#x-helidon-v3}}{{#useAbstractClass}}{{#isFormParamsFunctions}}
|
||||
|
||||
{{!}}{{>formParamsFunctions}}
|
||||
{{/isFormParamsFunctions}}{{/useAbstractClass}}
|
||||
{{/isFormParamsFunctions}}{{/useAbstractClass}}{{/x-helidon-v3}}
|
||||
{{#operation}}
|
||||
|
||||
/**
|
||||
* {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}}.
|
||||
{{^x-helidon-v3}} *
|
||||
{{/x-helidon-v3}}
|
||||
* @param request the server request
|
||||
* @param response the server response{{#allParams}}{{#isBodyParam}}{{#isModel}}
|
||||
* @param {{paramName}} {{{description}}}{{^description}}{{paramName}}{{/description}} {{/isModel}}{{/isBodyParam}}{{/allParams}}
|
||||
* @param response the server response{{!
|
||||
}}{{!
|
||||
For v3 the interface or abstract class handler methods declare a method parameter for the body parameter--if one is
|
||||
specified in the OpenAPI operation declaration--in addition to the request and response. The routing code extracts the
|
||||
body parameter from the request content and passes it to the handler method.
|
||||
|
||||
For v4 the generated handler methods do not declare the body parameter as a method parameter. Instead body parameters are
|
||||
dealt with, as all other request parameters, by the user-provided code (when an interface is generated) or by the
|
||||
generated code (when an abstract class is generated).
|
||||
|
||||
}}{{#x-helidon-v3}}{{#allParams}}{{#isBodyParam}}{{#isModel}}
|
||||
* @param {{paramName}} {{{description}}}{{^description}}{{paramName}}{{/description}} {{/isModel}}{{/isBodyParam}}{{/allParams}}{{/x-helidon-v3}}
|
||||
*/
|
||||
void {{{operationId}}}(ServerRequest request, ServerResponse response{{#allParams}}{{#isBodyParam}}{{#isModel}}, {{{dataType}}} {{paramName}}{{/isModel}}{{/isBodyParam}}{{/allParams}}){{^useAbstractClass}};{{/useAbstractClass}}{{#useAbstractClass}} { {{#formParams}}{{#-first}}
|
||||
{{>formParamsInitial}}{{/-first}}{{/formParams}}
|
||||
Single.create({{^hasParams}}Single.empty(){{/hasParams}}{{#hasParams}}{{^bodyParam}}{{#formParams}}{{#-first}}formSingle{{/-first}}{{/formParams}}{{^formParams}}Single.empty(){{/formParams}}{{/bodyParam}}{{#bodyParam}}{{^isModel}}request.content().as(new GenericType<{{{dataType}}}>() { }){{/isModel}}{{#isModel}}Single.empty(){{/isModel}}{{/bodyParam}}{{/hasParams}})
|
||||
{{^x-helidon-v3}}{{#useAbstractClass}}protected {{/useAbstractClass}}{{/x-helidon-v3}}void {{{operationId}}}(ServerRequest request, ServerResponse response{{#x-helidon-v3}}{{#allParams}}{{#isBodyParam}}{{#isModel}}, {{{dataType}}} {{paramName}}{{/isModel}}{{/isBodyParam}}{{/allParams}}{{/x-helidon-v3}}){{^useAbstractClass}};{{/useAbstractClass}}{{#useAbstractClass}} { {{> paramsInitial }}{{!
|
||||
}}{{#x-helidon-v3}}
|
||||
Single.create({{^hasParams}}Single.empty(){{/hasParams}}{{#hasParams}}{{^bodyParam}}{{#formParams}}{{#-first}}formSingle{{/-first}}{{/formParams}}{{^formParams}}Single.empty(){{/formParams}}{{/bodyParam}}{{#bodyParam}}{{^isModel}}request.content().as(new GenericType<{{#isFile}}InputStream{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}}>() { }){{/isModel}}{{#isModel}}Single.empty(){{/isModel}}{{/bodyParam}}{{/hasParams}})
|
||||
.thenAccept({{#bodyParam}}{{^isModel}}{{paramName}}{{/isModel}}{{#isModel}}val{{/isModel}}{{/bodyParam}}{{^bodyParam}}val{{/bodyParam}} -> {
|
||||
{{#allParams}}
|
||||
{{> queryParams }}{{> pathParams }}{{> headerParams}}{{> bodyParams}}{{> formParams}}{{> cookieParams}}
|
||||
{{/x-helidon-v3}}
|
||||
{{#allParams}}{{^x-helidon-v3}}
|
||||
// Parameter: {{baseName}}
|
||||
{{/x-helidon-v3}}
|
||||
{{#x-helidon-v3}} {{/x-helidon-v3}} {{> queryParams }}{{> pathParams }}{{> headerParams}}{{> bodyParams}}{{> formParams}}{{> cookieParams}}
|
||||
{{/allParams}}
|
||||
handle{{#lambda.titlecase}}{{{operationId}}}{{/lambda.titlecase}}(request, response{{#allParams}}, {{paramName}}{{/allParams}});
|
||||
})
|
||||
{{#x-helidon-v3}} {{/x-helidon-v3}} {{> paramsFinal }}{{!
|
||||
}}{{#x-helidon-v3}} {{/x-helidon-v3}} handle{{#lambda.titlecase}}{{{operationId}}}{{/lambda.titlecase}}(request, response{{#allParams}}, {{^x-helidon-v3}}
|
||||
{{/x-helidon-v3}}{{paramName}}{{/allParams}});
|
||||
{{#x-helidon-v3}} })
|
||||
.exceptionally(throwable -> handleError(request, response, throwable));
|
||||
{{/x-helidon-v3}}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}}.
|
||||
* Handle {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}}.{{^x-helidon-v3}}
|
||||
*{{/x-helidon-v3}}
|
||||
* @param request the server request
|
||||
* @param response the server response{{#allParams}}
|
||||
* @param {{paramName}} {{{description}}}{{^description}}{{paramName}}{{/description}} {{/allParams}}
|
||||
*/
|
||||
abstract void handle{{#lambda.titlecase}}{{{operationId}}}{{/lambda.titlecase}}(ServerRequest request, ServerResponse response{{#allParams}}, {{>dataType}} {{paramName}}{{/allParams}});
|
||||
{{^x-helidon-v3}}{{#useAbstractClass}}protected {{/useAbstractClass}}{{/x-helidon-v3}}abstract {{> handleMethodSignature }};
|
||||
{{/useAbstractClass}}
|
||||
{{#x-helidon-v3}}
|
||||
|
||||
{{/x-helidon-v3}}
|
||||
{{/operation}}
|
||||
{{#useAbstractClass}} abstract Void handleError(ServerRequest request, ServerResponse response, Throwable throwable);{{!
|
||||
}}{{/useAbstractClass}}
|
||||
}
|
||||
{{#useAbstractClass}}{{#x-helidon-v3}} abstract Void handleError(ServerRequest request, ServerResponse response, Throwable throwable);{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}
|
||||
{{#operation}}
|
||||
{{> opHelpers }}
|
||||
{{/operation}}
|
||||
{{/x-helidon-v3}}{{/useAbstractClass}}
|
||||
{{#useAbstractClass}}
|
||||
{{^x-helidon-v3}}
|
||||
@Override
|
||||
public void afterStop() {
|
||||
System.out.println("Service {{classname}} is down. Goodbye!");
|
||||
}
|
||||
|
||||
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{/useAbstractClass}}{{!
|
||||
}}}
|
||||
{{/operations}}
|
||||
|
@ -3,17 +3,22 @@ package {{package}};
|
||||
{{#imports}}import {{import}};
|
||||
{{/imports}}
|
||||
{{^useAbstractClass}}
|
||||
import java.util.logging.Logger;{{/useAbstractClass}}
|
||||
{{#x-helidon-v3}}import java.util.logging.Logger;
|
||||
|
||||
import io.helidon.webserver.ServerRequest;
|
||||
import io.helidon.webserver.ServerResponse;
|
||||
{{/x-helidon-v3}}
|
||||
{{/useAbstractClass}}
|
||||
import io.helidon.webserver.{{^x-helidon-v3}}http.{{/x-helidon-v3}}ServerRequest;
|
||||
import io.helidon.webserver.{{^x-helidon-v3}}http.{{/x-helidon-v3}}ServerResponse;
|
||||
|
||||
{{#operations}}
|
||||
public class {{classname}}Impl {{^useAbstractClass}}implements{{/useAbstractClass}}{{#useAbstractClass}}extends{{/useAbstractClass}} {{classname}} {
|
||||
{{#x-helidon-v3}}
|
||||
|
||||
private static final int HTTP_CODE_NOT_IMPLEMENTED = 501;
|
||||
{{/x-helidon-v3}}
|
||||
{{^useAbstractClass}}
|
||||
private static final Logger LOGGER = Logger.getLogger({{classname}}.class.getName());
|
||||
{{#x-helidon-v3}} private static final Logger LOGGER = Logger.getLogger({{classname}}.class.getName());
|
||||
{{/x-helidon-v3}}
|
||||
{{#jackson}}
|
||||
private static final ObjectMapper MAPPER = JsonProvider.objectMapper();{{/jackson}}
|
||||
{{#jsonb}}
|
||||
@ -22,19 +27,47 @@ public class {{classname}}Impl {{^useAbstractClass}}implements{{/useAbstractClas
|
||||
{{#operation}}
|
||||
|
||||
{{#useAbstractClass}}
|
||||
public void handle{{#lambda.titlecase}}{{{operationId}}}{{/lambda.titlecase}}(ServerRequest request, ServerResponse response{{#allParams}}, {{>dataType}} {{paramName}}{{/allParams}}) {
|
||||
{{^x-helidon-v3}}@Override
|
||||
protected{{/x-helidon-v3}}{{#x-helidon-v3}}public{{/x-helidon-v3}} {{> handleMethodSignature }} {
|
||||
{{/useAbstractClass}}
|
||||
{{^useAbstractClass}}
|
||||
{{#x-helidon-v3}}
|
||||
public void {{{operationId}}}(ServerRequest request, ServerResponse response{{#allParams}}{{#isBodyParam}}{{#isModel}}, {{{dataType}}} {{paramName}}{{/isModel}}{{/isBodyParam}}{{/allParams}}) {
|
||||
{{/useAbstractClass}}
|
||||
response.status(HTTP_CODE_NOT_IMPLEMENTED).send();
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}}
|
||||
@Override
|
||||
public void {{{operationId}}}(ServerRequest request, ServerResponse response) {
|
||||
{{!
|
||||
If the user generated an interface instead of an abstract class, add a few conveniences here in the implementation class
|
||||
to suggest how the developer might implement the code.
|
||||
|
||||
}}{{^isMultipart}}{{#hasFormParams}} Parameters formParams = request.content().as(Parameters.class);
|
||||
{{/hasFormParams}}{{/isMultipart}}{{!
|
||||
}}{{#isMultipart}}{{#useAbstractClass}} Map<String, ReadablePart> parts = PartsUtils.partsMap(request);
|
||||
{{/useAbstractClass}}{{!
|
||||
}}{{^useAbstractClass}}{{!
|
||||
}} MultiPart multiPart = request.content().as(MultiPart.class);
|
||||
{{/useAbstractClass}}{{/isMultipart}}{{!
|
||||
}}{{#useBeanValidation}} ValidatorUtils.Validator validator = ValidatorUtils.validator();
|
||||
{{/useBeanValidation}}{{!
|
||||
}}{{/x-helidon-v3}}{{!
|
||||
}}{{/useAbstractClass}}{{^x-helidon-v3}}
|
||||
{{/x-helidon-v3}}{{!
|
||||
}} response.status({{#x-helidon-v3}}HTTP_CODE_NOT_IMPLEMENTED{{/x-helidon-v3}}{{^x-helidon-v3}}Status.NOT_IMPLEMENTED_501{{/x-helidon-v3}}).send();
|
||||
}
|
||||
{{/operation}}
|
||||
|
||||
{{#useAbstractClass}}
|
||||
{{#useAbstractClass}}{{#x-helidon-v3}}
|
||||
public Void handleError(ServerRequest request, ServerResponse response, Throwable throwable) {
|
||||
return response.send(throwable);
|
||||
}
|
||||
{{/useAbstractClass}}
|
||||
}
|
||||
{{/x-helidon-v3}}{{/useAbstractClass}}{{!
|
||||
}}{{^useAbstractClass}}{{^x-helidon-v3}}
|
||||
@Override
|
||||
public void afterStop() {
|
||||
System.out.println("Service {{classname}} is down. Goodbye!");
|
||||
}
|
||||
|
||||
{{/x-helidon-v3}}{{/useAbstractClass}}{{!
|
||||
}}}
|
||||
{{/operations}}
|
@ -1,4 +1,4 @@
|
||||
{{#pattern}}{{#isString}}
|
||||
{{#x-helidon-v3}}{{#pattern}}{{#isString}}
|
||||
ValidatorUtils.validatePattern({{paramName}}, "{{{pattern}}}");{{/isString}}{{/pattern}}{{#minLength}}{{#maxLength}}
|
||||
ValidatorUtils.validateSize({{paramName}}, {{minLength}}, {{maxLength}});{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}}
|
||||
ValidatorUtils.validateSize({{paramName}}, {{minLength}}, null);{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}}
|
||||
@ -12,5 +12,29 @@
|
||||
ValidatorUtils.validateMax({{paramName}}, {{.}});{{/maximum}}{{/isInteger}}{{#isLong}}{{#minimum}}
|
||||
ValidatorUtils.validateMin({{paramName}}.intValue(), {{.}});{{/minimum}}{{#maximum}}
|
||||
ValidatorUtils.validateMax({{paramName}}.intValue(), {{.}});{{/maximum}}{{/isLong}}{{^isInteger}}{{^isLong}}{{#minimum}}
|
||||
ValidatorUtils.validateMin({{paramName}}, "{{minimum}}", {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
ValidatorUtils.validateMax({{paramName}}, "{{maximum}}", {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isLong}}{{/isInteger}}
|
||||
ValidatorUtils.validateMin({{^isNumber}}new java.math.BigDecimal({{/isNumber}}{{paramName}}{{^isNumber}}){{/isNumber}}, "{{minimum}}", {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
ValidatorUtils.validateMax({{^isNumber}}new java.math.BigDecimal({{/isNumber}}{{paramName}}{{^isNumber}}){{/isNumber}}, "{{maximum}}", {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isLong}}{{/isInteger}}{{!
|
||||
}}{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}{{!
|
||||
}}{{#pattern}}{{#isString}}{{!
|
||||
}} validator.validatePattern("{{paramName}}", {{paramName}}, "{{{pattern}}}");{{/isString}}{{/pattern}}{{#minLength}}{{#maxLength}}
|
||||
validator.validateSize("{{paramName}}", {{paramName}}, {{minLength}}, {{maxLength}});{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}}
|
||||
validator.validateSize("{{paramName}}", {{paramName}}, {{minLength}}, null);{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}}
|
||||
validator.validateSize("{{paramName}}", {{paramName}}, null, {{.}});{{/maxLength}}{{/minLength}}{{#minItems}}{{#maxItems}}
|
||||
validator.validateSize("{{paramName}}", {{paramName}}, {{minItems}}, {{maxItems}});{{/maxItems}}{{/minItems}}{{#minItems}}{{^maxItems}}
|
||||
validator.validateSize("{{paramName}}", {{paramName}}, {{minItems}}, null);{{/maxItems}}{{/minItems}}{{^minItems}}{{#maxItems}}
|
||||
validator.validateSize("{{paramName}}", {{paramName}}, null, {{.}});{{/maxItems}}{{/minItems}}{{#useBeanValidation}}{{#isEmail}}
|
||||
//RFC 5322 for Email Validation
|
||||
validator.validatePattern("{{paramName}}", {{paramName}}, "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^.-]+@[a-zA-Z0-9.-]+$");{{/isEmail}}{{/useBeanValidation}}{{#isInteger}}{{#minimum}}
|
||||
validator.validateMin("{{paramName}}", {{paramName}}, {{.}}, {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
validator.validateMax("{{paramName}}", {{paramName}}, {{.}}, {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isInteger}}{{#isLong}}{{#minimum}}
|
||||
validator.validateMin("{{paramName}}", {{paramName}}.intValue(), {{.}}, {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
validator.validateMax("{{paramName}}", {{paramName}}.intValue(), {{.}}, {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isLong}}{{#isDouble}}{{#minimum}}
|
||||
validator.validateMin("{{paramName}}", {{paramName}}, {{.}}d, {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
validator.validateMax("{{paramName}}", {{paramName}}, {{.}}d, {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isDouble}}{{#isFloat}}{{#minimum}}
|
||||
validator.validateMin("{{paramName}}", {{paramName}}, {{.}}f, {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
validator.validateMax("{{paramName}}", {{paramName}}, {{.}}f, {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isFloat}}{{^isInteger}}{{^isLong}}{{^isDouble}}{{^isFloat}}{{#minimum}}
|
||||
validator.validateMin("{{paramName}}", {{paramName}}, "{{minimum}}", {{#exclusiveMinimum}}false{{/exclusiveMinimum}}{{^exclusiveMinimum}}true{{/exclusiveMinimum}});{{/minimum}}{{#maximum}}
|
||||
validator.validateMax("{{paramName}}", {{paramName}}, "{{maximum}}", {{#exclusiveMaximum}}false{{/exclusiveMaximum}}{{^exclusiveMaximum}}true{{/exclusiveMaximum}});{{/maximum}}{{/isFloat}}{{/isDouble}}{{/isLong}}{{/isInteger}}{{!
|
||||
}}{{!
|
||||
}}{{/x-helidon-v3}}
|
@ -1,2 +1,2 @@
|
||||
{{#required}}{{!}}
|
||||
{{!}}ValidatorUtils.checkNonNull({{paramName}});{{/required}}
|
||||
{{#x-helidon-v3}} {{!}}ValidatorUtils.checkNonNull({{/x-helidon-v3}}{{^x-helidon-v3}}validator.require("{{paramName}}", {{/x-helidon-v3}}{{paramName}});{{/required}}
|
@ -1,2 +1,2 @@
|
||||
{{! PathParam is always required, no @NotNull necessary }}
|
||||
ValidatorUtils.checkNonNull({{paramName}});{{#isPrimitiveType}}{{>beanValidationCore}}{{/isPrimitiveType}}
|
||||
{{#x-helidon-v3}}ValidatorUtils.checkNonNull({{/x-helidon-v3}}{{^x-helidon-v3}}validator.require("{{paramName}}", {{/x-helidon-v3}}{{paramName}});{{#isPrimitiveType}}{{>beanValidationCore}}{{/isPrimitiveType}}
|
@ -1,2 +1,2 @@
|
||||
{{#required}}{{!}}
|
||||
{{!}}ValidatorUtils.checkNonNull({{paramName}});{{/required}}{{#isPrimitiveType}}{{>beanValidationCore}}{{/isPrimitiveType}}
|
||||
{{#x-helidon-v3}} {{!}}ValidatorUtils.checkNonNull({{/x-helidon-v3}}{{^x-helidon-v3}}validator.require("{{paramName}}", {{/x-helidon-v3}}{{paramName}});{{/required}}{{#isPrimitiveType}}{{>beanValidationCore}}{{/isPrimitiveType}}
|
@ -0,0 +1,5 @@
|
||||
{{!
|
||||
Assumed Mustache context is one EntrySet element from the media-type-name-to-CodegenMediaType map
|
||||
at operation->requestBody->content.
|
||||
}}{{!
|
||||
}}{{>paramDeclType}} {{paramName}}{{#lambda.helidonMediaTypeSuffix}}{{key}}{{/lambda.helidonMediaTypeSuffix}}
|
@ -0,0 +1,3 @@
|
||||
request.content().hasEntity()
|
||||
? {{^required}}Optional.of({{/required}}request.content().{{#isFile}}inputStream(){{/isFile}}{{^isFile}}as({{> paramValueAs }}){{/isFile}}{{> paramValueAsSuffix }}{{^required}}){{/required}}
|
||||
: {{^isContainer}}{{^required}}Optional.empty(){{/required}}{{#required}}null{{/required}}{{/isContainer}}{{#isContainer}}{{containerTypeMapped}}.of(){{/isContainer}}
|
@ -1 +1,4 @@
|
||||
{{#isBodyParam}}ValidatorUtils.checkNonNull({{paramName}});{{/isBodyParam}}
|
||||
{{#isBodyParam}}{{^x-helidon-v3}}{{> paramDecl }} = {{> paramMethodInvocation }};{{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}}
|
||||
{{/x-helidon-v3}}
|
||||
{{#x-helidon-v3}}ValidatorUtils.checkNonNull({{paramName}});
|
||||
{{/x-helidon-v3}}{{/isBodyParam}}
|
@ -1,4 +1,6 @@
|
||||
{{#isPrimitiveType}}{{^isFile}}{{{dataType}}}{{/isFile}}{{#isFile}}InputStream{{/isFile}}{{/isPrimitiveType}}{{!
|
||||
{{!
|
||||
Used for v3 only.
|
||||
}}{{#isPrimitiveType}}{{^isFile}}{{{dataType}}}{{/isFile}}{{#isFile}}InputStream{{/isFile}}{{/isPrimitiveType}}{{!
|
||||
}}{{^isPrimitiveType}}{{!
|
||||
}}{{#isArray}}{{!
|
||||
}}{{#isBodyParam}}{{{dataType}}}{{/isBodyParam}}{{!
|
||||
|
@ -0,0 +1 @@
|
||||
{{#isFile}}{{#isArray}}List<{{/isArray}}{{^isBodyParam}}byte[]{{/isBodyParam}}{{#isBodyParam}}InputStream{{/isBodyParam}}{{#isArray}}>{{/isArray}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}}
|
@ -1 +1,6 @@
|
||||
{{#isFormParam}}{{^isFile}}{{>dataType}} {{paramName}} = {{>paramValue}}{{/isFile}}{{#isFile}}{{#isArray}}List<{{/isArray}}InputStream{{#isArray}}>{{/isArray}} {{paramName}} = {{>paramValue}}{{/isFile}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{/isFormParam}}
|
||||
{{!
|
||||
|
||||
Starting with v4 we process each part in multipart content as a form param because that's how the generator presents parts.
|
||||
|
||||
}}{{#isFormParam}}{{> paramDecl}} = {{>paramValue}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{!
|
||||
}}{{/isFormParam}}
|
@ -1,11 +1,17 @@
|
||||
private void processNonFileFormField(String name, Map<String, List<String>> nonFileFormContent, ReadableBodyPart part) {
|
||||
private void processNonFileFormField(String name, Map<String, List<String>> nonFileFormContent, Readable{{#x-helidon-v3}}Body{{/x-helidon-v3}}Part part) {
|
||||
List<String> content = nonFileFormContent.computeIfAbsent(name, key -> new ArrayList<>());
|
||||
part.content().as(String.class).thenAccept(content::add);
|
||||
{{#x-helidon-v3}} part.content().as(String.class).thenAccept(content::add);
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}} content.add(part.as(String.class));
|
||||
{{/x-helidon-v3}}
|
||||
}
|
||||
|
||||
private void processFileFormField(String name, Map<String, List<InputStream>> fileFormContent, ReadableBodyPart part) {
|
||||
List<InputStream> content = fileFormContent.computeIfAbsent(name, key -> new ArrayList<>());
|
||||
part.content().map(DataChunk::bytes)
|
||||
{{!
|
||||
Helidon 4 changed ReadableBodyPart to ReadablePart and, for Helidon 4, we save the entire part (which can now include
|
||||
the optional filename and part headers) as well as the InputStream instead of just the InputStream as in Helidon 3.
|
||||
}}
|
||||
private void processFileFormField(String name, Map<String, List<{{#x-helidon-v3}}InputStream{{/x-helidon-v3}}{{^x-helidon-v3}}ReadablePart{{/x-helidon-v3}}>> fileFormContent, Readable{{#x-helidon-v3}}Body{{/x-helidon-v3}}Part part) {
|
||||
{{^x-helidon-v3}} {{/x-helidon-v3}}List<{{#x-helidon-v3}}InputStream{{/x-helidon-v3}}{{^x-helidon-v3}}ReadablePart{{/x-helidon-v3}}> content = fileFormContent.computeIfAbsent(name, key -> new ArrayList<>());
|
||||
{{#x-helidon-v3}} part.content().map(DataChunk::bytes)
|
||||
.collect(ByteArrayOutputStream::new, (stream, bytes) -> {
|
||||
try {
|
||||
stream.write(bytes);
|
||||
@ -14,4 +20,7 @@ private void processNonFileFormField(String name, Map<String, List<String>> nonF
|
||||
}
|
||||
})
|
||||
.thenAccept(byteStream -> content.add(new ByteArrayInputStream(byteStream.toByteArray())));
|
||||
}
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}} content.add(part);
|
||||
{{/x-helidon-v3}}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
Map<String, List<String>> nonFileFormContent = new HashMap<>();
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}Map<String, List<String>> nonFileFormContent = new HashMap<>();
|
||||
Map<String, List<InputStream>> fileFormContent = new HashMap<>();
|
||||
Single<Void> formSingle = request.content().asStream(ReadableBodyPart.class)
|
||||
.forEach(part -> {
|
||||
@ -8,4 +9,12 @@ Map<String, List<String>> nonFileFormContent = new HashMap<>();
|
||||
}}{{#isFile}}processFileFormField(name, fileFormContent, part);{{/isFile}}
|
||||
}{{/formParams}}
|
||||
part.drain();
|
||||
});
|
||||
});
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}
|
||||
{{^isMultipart}}{{#hasFormParams}}{{!
|
||||
}} Parameters formParams = request.content().as(Parameters.class);
|
||||
{{/hasFormParams}}{{/isMultipart}}{{!
|
||||
}}{{#isMultipart}}{{!
|
||||
}} Map<String, ReadablePart> parts = PartsUtils.partsMap(request);
|
||||
{{/isMultipart}}{{/x-helidon-v3}}
|
@ -0,0 +1,12 @@
|
||||
package {{modelPackage}};
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
|
||||
public interface GenericTypes {
|
||||
{{#x-helidon-genericTypeDeclarations}}
|
||||
GenericType<{{collectionType}}<{{#isMap}}String, {{/isMap}}{{baseType}}>> TYPE__{{collectionType}}_{{baseType}} = new GenericType<>() {};
|
||||
{{/x-helidon-genericTypeDeclarations}}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
void handle{{#lambda.titlecase}}{{{operationId}}}{{/lambda.titlecase}}(ServerRequest request, ServerResponse response{{#allParams}}, {{^x-helidon-v3}}
|
||||
{{/x-helidon-v3}}{{>paramDecl}}{{/allParams}})
|
@ -0,0 +1,70 @@
|
||||
package {{apiPackage}};
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import io.helidon.webserver.http.ServerRequest;
|
||||
import io.helidon.webserver.http.ServerResponse;
|
||||
|
||||
/**
|
||||
* Utility methods related to handlers for Helidon 4+ support.
|
||||
*/
|
||||
class HandlerUtils {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(HandlerUtils.class.getName());
|
||||
|
||||
private HandlerUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler which accepts a request, response, and a body parameter type and, if the body part is declared as required,
|
||||
* enforces that.
|
||||
*
|
||||
* @param <T> type of the body parameter
|
||||
*/
|
||||
static class Handler<T> implements io.helidon.webserver.http.Handler {
|
||||
|
||||
private final Class<T> type;
|
||||
private final boolean isRequired;
|
||||
private final Op<T> op;
|
||||
|
||||
Handler(Class<T> type, boolean isRequired, Op<T> op) {
|
||||
this.type = type;
|
||||
this.isRequired = isRequired;
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a handler which extracts a body parameter from the content and, if the parameter is required, enforces that.
|
||||
*
|
||||
* @param type type of the body parameter
|
||||
* @param isRequired whether the body parameter is declared as required
|
||||
* @param op operation the handler is to invoke with the request, response, and body parameter
|
||||
* @param <T> type of the body parameter
|
||||
* @return the new handler
|
||||
*/
|
||||
static <T> Handler<T> create(Class<T> type, boolean isRequired, Handler.Op<T> op) {
|
||||
return new Handler<>(type, isRequired, op);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse)
|
||||
throws Exception {
|
||||
ValidatorUtils.Validator validator = isRequired ? ValidatorUtils.validator() : null;
|
||||
T body = serverRequest.content().as(type);
|
||||
if (isRequired) {
|
||||
validator.require("body", body);
|
||||
validator.execute();
|
||||
}
|
||||
op.apply(serverRequest, serverResponse, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* An operation to which the handler delegates upon receipt of a request and extraction of the body parameter.
|
||||
*
|
||||
* @param <T> type of the body parameter
|
||||
*/
|
||||
interface Op<T> {
|
||||
void apply(ServerRequest request, ServerResponse response, T body);
|
||||
}
|
||||
}
|
||||
}
|
217
modules/openapi-generator/src/main/resources/java-helidon/server/libraries/se/hcollectors.mustache
vendored
Normal file
217
modules/openapi-generator/src/main/resources/java-helidon/server/libraries/se/hcollectors.mustache
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
package {{apiPackage}};
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collector;
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.http.Headers;
|
||||
import io.helidon.http.WritableHeaders;
|
||||
import io.helidon.http.media.EntityReader;
|
||||
import io.helidon.http.media.FormParamsSupport;
|
||||
import io.helidon.http.media.MediaSupport;
|
||||
|
||||
/**
|
||||
* Collectors with particular features useful from the generated code.
|
||||
*/
|
||||
@io.helidon.common.Generated(value = "{{additionalProperties.generatorClass}}",
|
||||
trigger = "utility",
|
||||
version = "{{generatorVersion}}")
|
||||
public final class HCollectors {
|
||||
|
||||
private static final MediaSupport FORM_PARAMS_SUPPORT = FormParamsSupport.create();
|
||||
private static final Headers EMPTY_HEADERS = WritableHeaders.create();
|
||||
|
||||
/**
|
||||
* Returns a new {@link java.util.stream.Collector} that applies a default value in the absence of provided values and returns
|
||||
* the resulting {@link java.util.List}.
|
||||
*
|
||||
* @param baseDefault default value expressed in the base type of the parameter
|
||||
* @param converter transforms the default value from the base type to the result type
|
||||
* @param <BT> base type
|
||||
* @param <T> result type
|
||||
* @return new collector
|
||||
*/
|
||||
static <BT, T> Collector<T, ?, List<T>> toDefaultedList(BT baseDefault, Function<BT, T> converter) {
|
||||
return new DefaultableListCollector<>(baseDefault, converter);
|
||||
}
|
||||
|
||||
static <T> Collector<String, ?, Map<String, T>> noOpMap() {
|
||||
|
||||
return new NoOpMapCollector<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes URL encoded string as binary data.
|
||||
* <p>
|
||||
* Inspired hugely by java.net.URLDecoder.
|
||||
* </p>
|
||||
*
|
||||
* @param s URL encoded string
|
||||
* @return binary data encoded by the string
|
||||
*/
|
||||
static byte[] decodeBinaryFormParam(String s) {
|
||||
boolean needToChange = false;
|
||||
int numChars = s.length();
|
||||
int i = 0;
|
||||
|
||||
char c;
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
byte[] bytes = null;
|
||||
while (i < numChars) {
|
||||
c = s.charAt(i);
|
||||
switch (c) {
|
||||
case '+':
|
||||
output.write(' ');
|
||||
i++;
|
||||
needToChange = true;
|
||||
break;
|
||||
case '%':
|
||||
/*
|
||||
* Starting with this instance of %, process all
|
||||
* consecutive substrings of the form %xy. Each
|
||||
* substring %xy will yield a byte. Convert all
|
||||
* consecutive bytes obtained this way to whatever
|
||||
* character(s) they represent in the provided
|
||||
* encoding.
|
||||
*/
|
||||
|
||||
try {
|
||||
|
||||
// (numChars-i)/3 is an upper bound for the number
|
||||
// of remaining bytes
|
||||
if (bytes == null)
|
||||
bytes = new byte[(numChars-i)/3];
|
||||
int pos = 0;
|
||||
|
||||
while ( ((i+2) < numChars) &&
|
||||
(c=='%')) {
|
||||
int v = Integer.parseInt(s, i + 1, i + 3, 16);
|
||||
if (v < 0)
|
||||
throw new IllegalArgumentException(
|
||||
"URLDecoder: Illegal hex characters in escape "
|
||||
+ "(%) pattern - negative value");
|
||||
bytes[pos++] = (byte) v;
|
||||
i+= 3;
|
||||
if (i < numChars)
|
||||
c = s.charAt(i);
|
||||
}
|
||||
|
||||
// A trailing, incomplete byte encoding such as
|
||||
// "%x" will cause an exception to be thrown
|
||||
|
||||
if ((i < numChars) && (c=='%'))
|
||||
throw new IllegalArgumentException(
|
||||
"URLDecoder: Incomplete trailing escape (%) pattern");
|
||||
|
||||
output.write(bytes, 0, pos);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"URLDecoder: Illegal hex characters in escape (%) pattern - "
|
||||
+ e.getMessage());
|
||||
}
|
||||
needToChange = true;
|
||||
break;
|
||||
default:
|
||||
output.write(c);
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output.toByteArray();
|
||||
}
|
||||
|
||||
private static class NoOpMapCollector<T> implements Collector<String, Map<String, T>, Map<String, T>> {
|
||||
|
||||
@Override
|
||||
public Supplier<Map<String, T>> supplier() {
|
||||
return LinkedHashMap::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiConsumer<Map<String, T>, String> accumulator() {
|
||||
return (map, expr) -> {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryOperator<Map<String, T>> combiner() {
|
||||
return (a, b) -> a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Map<String, T>, Map<String, T>> finisher() {
|
||||
return Function.identity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
return Set.of();
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class AbstractListCollector<T> implements Collector<T, List<T>, List<T>> {
|
||||
|
||||
@Override
|
||||
public Supplier<List<T>> supplier() {
|
||||
return ArrayList::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiConsumer<List<T>, T> accumulator() {
|
||||
return List::add;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BinaryOperator<List<T>> combiner() {
|
||||
return (l1, l2) -> {
|
||||
l2.addAll(l1);
|
||||
return l2;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
return Set.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link java.util.stream.Collector} for streams of the base type (values from the request, often strings}
|
||||
* applying a converter to the desired result type and supplying a default value if there are no base values.
|
||||
*
|
||||
* @param <BT> base type (often string)
|
||||
* @param <T> result type
|
||||
*/
|
||||
private static class DefaultableListCollector<BT, T> extends AbstractListCollector<T> {
|
||||
|
||||
private final BT baseDefault;
|
||||
private final Function<BT, T> converter;
|
||||
|
||||
DefaultableListCollector(BT baseDefault, Function<BT, T> converter) {
|
||||
this.baseDefault = baseDefault;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<List<T>, List<T>> finisher() {
|
||||
return l -> {
|
||||
if (l.isEmpty()) {
|
||||
l.add(converter.apply(baseDefault));
|
||||
}
|
||||
return l;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
{{#isHeaderParam}}{{>dataType}} {{paramName}} = {{>paramValue}}{{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}}{{/isHeaderParam}}
|
||||
{{#isHeaderParam}}{{>paramDecl}} = {{>paramValue}}{{#useBeanValidation}}{{>beanValidationHeaderParams}}{{/useBeanValidation}}{{/isHeaderParam}}
|
@ -2,22 +2,35 @@ package {{invokerPackage}};
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}
|
||||
import {{package}}.{{classname}}Impl;{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
|
||||
import io.helidon.common.LogConfig;
|
||||
import io.helidon{{^x-helidon-v3}}.logging{{/x-helidon-v3}}.common.LogConfig;
|
||||
{{#x-helidon-v3}}
|
||||
import io.helidon.common.reactive.Single;
|
||||
{{/x-helidon-v3}}
|
||||
import io.helidon.config.Config;
|
||||
{{#x-helidon-v3}}
|
||||
import io.helidon.health.HealthSupport;
|
||||
import io.helidon.health.checks.HealthChecks;
|
||||
import io.helidon.media.jsonp.JsonpSupport;
|
||||
{{/x-helidon-v3}}
|
||||
{{#jsonb}}
|
||||
{{#x-helidon-v3}}
|
||||
import io.helidon.media.jsonb.JsonbSupport;
|
||||
{{/x-helidon-v3}}
|
||||
{{/jsonb}}
|
||||
{{#jackson}}
|
||||
{{#x-helidon-v3}}
|
||||
import io.helidon.media.jackson.JacksonSupport;
|
||||
import {{apiPackage}}.JsonProvider;
|
||||
{{/x-helidon-v3}}
|
||||
{{/jackson}}
|
||||
{{#x-helidon-v3}}
|
||||
import io.helidon.metrics.MetricsSupport;
|
||||
import io.helidon.openapi.OpenAPISupport;
|
||||
import io.helidon.webserver.Routing;
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}}
|
||||
import io.helidon.webserver.http.HttpRouting;
|
||||
{{/x-helidon-v3}}
|
||||
import io.helidon.webserver.WebServer;
|
||||
|
||||
/**
|
||||
@ -43,14 +56,18 @@ public final class Main {
|
||||
* Start the server.
|
||||
* @return the created {@link WebServer} instance
|
||||
*/
|
||||
static Single<WebServer> startServer() {
|
||||
static {{#x-helidon-v3}}Single<{{/x-helidon-v3}}WebServer{{#x-helidon-v3}}>{{/x-helidon-v3}} startServer() {
|
||||
|
||||
// load logging configuration
|
||||
LogConfig.configureRuntime();
|
||||
|
||||
// By default this will pick up application.yaml from the classpath
|
||||
Config config = Config.create();
|
||||
{{^x-helidon-v3}}
|
||||
Config.global(config);
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
{{#x-helidon-v3}}
|
||||
WebServer server = WebServer.builder(createRouting(config))
|
||||
.config(config.get("server"))
|
||||
.addMediaSupport(JsonpSupport.create())
|
||||
@ -74,10 +91,21 @@ public final class Main {
|
||||
System.err.println("Startup failed: " + t.getMessage());
|
||||
t.printStackTrace(System.err);
|
||||
});
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}}
|
||||
WebServer webserver = WebServer.builder()
|
||||
.config(config.get("server"))
|
||||
.routing(Main::routing)
|
||||
.build()
|
||||
.start();
|
||||
|
||||
System.out.println("WEB server is up! {{{basePath}}}");
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
return webserver;
|
||||
}
|
||||
|
||||
{{#x-helidon-v3}}
|
||||
/**
|
||||
* Creates new {@link Routing}.
|
||||
*
|
||||
@ -98,4 +126,14 @@ public final class Main {
|
||||
.register("/", new {{classname}}Impl()){{/operations}}{{/apis}}{{/apiInfo}}
|
||||
.build();
|
||||
}
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}}
|
||||
/**
|
||||
* Updates HTTP routing and implicitly registers observe providers.
|
||||
*/
|
||||
static void routing(HttpRouting.Builder routing) {
|
||||
routing{{#apiInfo}}{{#apis}}{{#operations}}
|
||||
.register("{{#x-helidon-v3}}/{{/x-helidon-v3}}{{{pathPrefix}}}", new {{classname}}Impl()){{^x-helidon-v3}}{{#x-helidon-fixupPath}}/* {{.}} */{{/x-helidon-fixupPath}}{{/x-helidon-v3}}{{/operations}}{{/apis}}{{/apiInfo}};
|
||||
}
|
||||
{{/x-helidon-v3}}
|
||||
}
|
||||
|
@ -1,28 +1,47 @@
|
||||
package {{invokerPackage}};
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}import java.util.concurrent.TimeUnit;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import {{rootJavaEEPackage}}.json.Json;
|
||||
import {{rootJavaEEPackage}}.json.JsonBuilderFactory;
|
||||
|
||||
import io.helidon.media.jsonp.JsonpSupport;
|
||||
import io.helidon.webclient.WebClient;
|
||||
{{#x-helidon-v3}}import io.helidon.media.jsonp.JsonpSupport;
|
||||
{{/x-helidon-v3}}
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}import io.helidon.webclient.WebClient;
|
||||
import io.helidon.webserver.WebServer;
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}}{{!
|
||||
}}import io.helidon.webclient.http1.Http1Client;
|
||||
import io.helidon.webserver.http.HttpRouting;
|
||||
import io.helidon.webserver.testing.junit5.ServerTest;
|
||||
import io.helidon.webserver.testing.junit5.SetUpRoute;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
{{/x-helidon-v3}}
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@Disabled
|
||||
{{#x-helidon-v3}}@Disabled
|
||||
{{/x-helidon-v3}}
|
||||
{{^x-helidon-v3}}@ServerTest
|
||||
{{/x-helidon-v3}}
|
||||
public class MainTest {
|
||||
|
||||
private static WebServer webServer;
|
||||
{{#x-helidon-v3}}{{!
|
||||
}} private static WebServer webServer;
|
||||
private static WebClient webClient;
|
||||
{{/x-helidon-v3}}
|
||||
private static final JsonBuilderFactory JSON_BUILDER = Json.createBuilderFactory(Collections.emptyMap());
|
||||
|
||||
@BeforeAll
|
||||
{{#x-helidon-v3}}{{!
|
||||
}} @BeforeAll
|
||||
public static void startTheServer() throws Exception {
|
||||
webServer = Main.startServer().await();
|
||||
|
||||
@ -40,6 +59,23 @@ public class MainTest {
|
||||
.get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}
|
||||
|
||||
private Http1Client client;
|
||||
|
||||
MainTest(Http1Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@SetUpRoute
|
||||
static void routing(HttpRouting.Builder builder) {
|
||||
Main.routing(builder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
|
@ -0,0 +1,3 @@
|
||||
{{!
|
||||
Declares a field for an operation's header result.
|
||||
}}
|
187
modules/openapi-generator/src/main/resources/java-helidon/server/libraries/se/opHelpers.mustache
vendored
Normal file
187
modules/openapi-generator/src/main/resources/java-helidon/server/libraries/se/opHelpers.mustache
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Returns a new instance of the class which handles parameters to and responses from the {{operationId}} operation.
|
||||
* <p>
|
||||
* Developers can override this method if they extend the {{classname}} class.
|
||||
* </p>
|
||||
*
|
||||
* @return new {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}
|
||||
*/
|
||||
protected {{#lambda.titlecase}}{{operationId}}Op{{/lambda.titlecase}} create{{#lambda.titlecase}}{{operationId}}Op{{/lambda.titlecase}}() {
|
||||
return new {{#lambda.titlecase}}{{operationId}}Op{{/lambda.titlecase}}();
|
||||
}
|
||||
|
||||
{{!
|
||||
Declares an inner class for each operation which collects:
|
||||
* overridable methods for preparing each parameter from the request
|
||||
* an interface which defines the possible return groups (body or header results and status).
|
||||
}}
|
||||
/**
|
||||
* Helper elements for the {{=<% %>=}}{@code <%operationId%>}<%={{ }}=%> operation.
|
||||
* <p>
|
||||
* Also below are records for each response declared in the OpenAPI document, organized by response status.
|
||||
* <p>
|
||||
* Once your code determines which (if any) declared response to send it can use the static {@code builder} method for
|
||||
* that specific result, passing the required elements of the response as parameters, and then assign any optional
|
||||
* response elements using the other builder methods.
|
||||
* <p>
|
||||
* Finally, your code should invoke the {@code apply} method, passing the original {@link ServerResponse}. The
|
||||
* generated method sets any headers you have assigned, sets the correct status in the response, and sends
|
||||
* the response including any appropriate entity.
|
||||
* </p>
|
||||
*/
|
||||
public static class {{#lambda.titlecase}}{{operationId}}Op{{/lambda.titlecase}} {
|
||||
{{#allParams}}
|
||||
|
||||
/**
|
||||
* Prepares the {{paramName}} parameter.
|
||||
*
|
||||
* @param request {@link io.helidon.webserver.http.ServerRequest} containing the parameter
|
||||
{{#isFormParameter}}{{^isMultipart}}{{!
|
||||
}} * @param formParams {@link io.helidon.common.parameters.Parameters} containing all form parameters
|
||||
{{/isMultipart}}{{/isFormParameter}}{{#vendorExtensions.x-helidon-isMultipartFormParam}}{{!
|
||||
}} * @param parts {@code Map} of part names to {@link io.helidon.http.media.multipart.ReadablePart} for each part
|
||||
{{/vendorExtensions.x-helidon-isMultipartFormParam}}{{!
|
||||
}} * @param validator {@link {{apiPackage}}.ValidatorUtils.Validator} for validating all parameters to the operation
|
||||
* @return {{paramName}} parameter value
|
||||
*/
|
||||
protected {{> paramDeclType }} {{> paramMethodName }}(ServerRequest request, {{#isFormParam}}{{^isMultipart}}Parameters formParams, {{/isMultipart}}{{#isMultipart}}Map<String, ReadablePart> parts, {{/isMultipart}}{{/isFormParam}}ValidatorUtils.Validator validator) {
|
||||
return {{^isBodyParam}}{{> paramValueExpr}}{{/isBodyParam}}{{#isBodyParam}}{{> bodyParamValue }};{{/isBodyParam}}
|
||||
}
|
||||
{{/allParams}}
|
||||
{{#responses}}
|
||||
|
||||
/**
|
||||
* {{#isDefault}}Default result{{/isDefault}}{{^isDefault}}Response for HTTP status code {{=<% %>=}}{@code <%code%>}<%={{ }}=%>{{/isDefault}}.{{!
|
||||
}}{{#isDefault}}
|
||||
*
|
||||
* @param status (required) Status value to be sent with this default result{{/isDefault}}{{!
|
||||
}}{{#vendorExtensions.x-helidon-hasResponseProps}}{{!
|
||||
}}{{^isDefault}}
|
||||
*{{/isDefault}}{{!
|
||||
}}{{#vendorExtensions.x-helidon-allResponseProps}}
|
||||
* @param {{name}} {{#required}}(required) {{/required}}{{description}}{{/vendorExtensions.x-helidon-allResponseProps}}{{/vendorExtensions.x-helidon-hasResponseProps}}
|
||||
*/
|
||||
record {{> resultRecordTypeName }}({{#isDefault}}Status status{{#vendorExtensions.x-helidon-hasResponseProps}}, {{/vendorExtensions.x-helidon-hasResponseProps}}{{!
|
||||
}}{{/isDefault}}{{#vendorExtensions.x-helidon-allResponseProps}}{{^-first}},
|
||||
{{/-first}}{{> opResultParamDecl}}{{/vendorExtensions.x-helidon-allResponseProps}}{{!
|
||||
}}) {
|
||||
|
||||
/**
|
||||
* Creates a response builder for the {{#isDefault}}default{{/isDefault}}{{^isDefault}}status {{=<% %>=}}{@code <%code%>}<%={{ }}=%>{{/isDefault}} response
|
||||
* for the {{operationId}} operation{{#x-helidon-hasRequiredResponseProps}}, accepting all the required response values{{/x-helidon-hasRequiredResponseProps}}{{^x-helidon-hasRequiredResponseProps}}; there are no required result values{{/x-helidon-hasRequiredResponseProps}} for this response.
|
||||
*{{!
|
||||
}}{{#vendorExtensions.x-helidon-requiredResponseProps}}
|
||||
* @param {{name}} returned {{#isHeader}}header{{/isHeader}}{{^isHeader}}entity{{/isHeader}}{{/vendorExtensions.x-helidon-requiredResponseProps}}
|
||||
* @return new builder for status {{code}}
|
||||
*/
|
||||
static Builder builder({{#isDefault}}Status status{{#vendorExtensions.x-helidon-hasRequiredResponseProps}},
|
||||
{{/vendorExtensions.x-helidon-hasRequiredResponseProps}}{{/isDefault}}{{#vendorExtensions.x-helidon-requiredResponseProps}}{{^-first}},
|
||||
{{/-first}}{{> opResultParamDecl }}{{/vendorExtensions.x-helidon-requiredResponseProps}}) {
|
||||
return new Builder({{#isDefault}}status{{#vendorExtensions.x-helidon-hasRequiredResponseProps}},
|
||||
{{/vendorExtensions.x-helidon-hasRequiredResponseProps}}{{/isDefault}}{{#vendorExtensions.x-helidon-requiredResponseProps}}{{^-first}},
|
||||
{{/-first}}{{name}}{{/vendorExtensions.x-helidon-requiredResponseProps}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for the {{> resultRecordTypeName}} result.
|
||||
*/
|
||||
static class Builder implements io.helidon.common.Builder<Builder, {{> resultRecordTypeName }}> {
|
||||
{{#vendorExtensions.x-helidon-allResponseProps}}{{#-first}}
|
||||
{{/-first}}{{!
|
||||
}} private {{#required}}final {{/required}}{{> opResultParamDecl }};{{/vendorExtensions.x-helidon-allResponseProps}}
|
||||
{{#vendorExtensions.x-helidon-resultBuilderNeedsCtor}}{{!
|
||||
}}{{#isDefault}}{{!
|
||||
}} private final Status status;
|
||||
{{/isDefault}}
|
||||
Builder({{#isDefault}}Status status{{#vendorExtensions.x-helidon-hasRequiredResponseProps}},
|
||||
{{/vendorExtensions.x-helidon-hasRequiredResponseProps}}{{/isDefault}}{{#vendorExtensions.x-helidon-requiredResponseProps}}{{^-first}},
|
||||
{{/-first}}{{> opResultParamDecl }}{{/vendorExtensions.x-helidon-requiredResponseProps}}) {
|
||||
{{#isDefault}}{{!
|
||||
}} this.status = status;{{/isDefault}}
|
||||
{{#vendorExtensions.x-helidon-requiredResponseProps}}{{!
|
||||
}} this.{{name}} = {{name}};{{/vendorExtensions.x-helidon-requiredResponseProps}}
|
||||
}
|
||||
{{/vendorExtensions.x-helidon-resultBuilderNeedsCtor}}
|
||||
@Override
|
||||
public {{> resultRecordTypeName}} build() {
|
||||
return new {{> resultRecordTypeName}}({{#isDefault}}status{{#vendorExtensions.x-helidon-hasResponseProps}},
|
||||
{{/vendorExtensions.x-helidon-hasResponseProps}}{{/isDefault}}{{#vendorExtensions.x-helidon-allResponseProps}}{{^-first}},
|
||||
{{/-first}}{{name}}{{/vendorExtensions.x-helidon-allResponseProps}});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the response data in this builder to the specified {@link io.helidon.webserver.http.ServerResponse},
|
||||
* assigning the HTTP status, any response headers, and any response entity.
|
||||
* <p>
|
||||
* Equivalent to {@snippet :
|
||||
* build().send(_serverResponse);
|
||||
* }
|
||||
* </p>
|
||||
*
|
||||
* @param _serverResponse the {@code ServerResponse} to which to apply the status, headers, and entity
|
||||
*/
|
||||
void send(ServerResponse _serverResponse) {
|
||||
build().send(_serverResponse);
|
||||
}{{#vendorExtensions.x-helidon-optionalResponseProps}}
|
||||
|
||||
/**
|
||||
* Sets the value for the optional return property {{=<% %>=}}{@code <%name%>}<%={{ }}=%>.
|
||||
* @param {{name}} {{description}}
|
||||
* @return updated result builder
|
||||
*/
|
||||
Builder {{name}}({{> opResultParamDecl }}) {
|
||||
this.{{name}} = {{name}};
|
||||
return this;
|
||||
}{{/vendorExtensions.x-helidon-optionalResponseProps}}
|
||||
}
|
||||
{{!
|
||||
Suppress the generated constructor if it would duplicate the implied canonical constructor.
|
||||
}}{{!
|
||||
}}{{#vendorExtensions.x-helidon-hasRequiredResponseProps}}
|
||||
{{> opResultRecordCtor }}{{!
|
||||
}}{{/vendorExtensions.x-helidon-hasRequiredResponseProps}}{{!
|
||||
}}{{^vendorExtensions.x-helidon-hasRequiredResponseProps}}{{#isDefault}}
|
||||
{{> opResultRecordCtor }}{{!
|
||||
}}{{/isDefault}}{{/vendorExtensions.x-helidon-hasRequiredResponseProps}}
|
||||
/**
|
||||
* Applies this response data to the specified {@link io.helidon.webserver.http.ServerResponse}, assigning the
|
||||
* HTTP status, any response headers, and any response entity.
|
||||
*
|
||||
* @param _serverResponse the server response to which to apply these result values
|
||||
*/
|
||||
void send(ServerResponse _serverResponse) {
|
||||
_serverResponse.status({{^isDefault}}{{vendorExtensions.x-helidon-resultStatusDecl}}{{/isDefault}}{{#isDefault}}status{{/isDefault}});{{!
|
||||
}}{{#headers}}{{!
|
||||
}} if ({{name}} != null) {
|
||||
_serverResponse.header("{{baseName}}", {{name}}{{^isString}}.toString(){{/isString}});
|
||||
}{{/headers}}{{!
|
||||
}}{{#returnProperty}}{{!
|
||||
}}{{^required}}
|
||||
if ({{name}} != null) { {{!
|
||||
}}{{/required}}{{!
|
||||
}}{{^isFile}}
|
||||
{{^required}} {{/required}}{{!
|
||||
}} _serverResponse.send({{name}});{{!
|
||||
}}{{^required}}
|
||||
} else {
|
||||
_serverResponse.send();
|
||||
}{{!
|
||||
}}{{/required}}{{!
|
||||
}}{{/isFile}}{{!
|
||||
}}{{#isFile}}
|
||||
{{^required}} {{/required}}{{!
|
||||
}} _serverResponse.contentLength({{name}}.transferTo(_serverResponse.outputStream()));{{!
|
||||
}}{{^required}}
|
||||
}{{!
|
||||
}}{{/required}}{{!
|
||||
}} _serverResponse.send();{{!
|
||||
}}{{/isFile}}{{!
|
||||
}}{{/returnProperty}}{{!
|
||||
}}{{^dataType}}
|
||||
_serverResponse.send();{{!
|
||||
}}{{/dataType}}{{!
|
||||
}}
|
||||
}
|
||||
}
|
||||
{{/responses}}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{{!
|
||||
Declaration (type and name) of a result property.
|
||||
}}{{^isFile}}{{{dataType}}}{{/isFile}}{{#isFile}}InputStream{{/isFile}} {{name}}
|
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Constructor for a result for the {{#isDefault}}default{{/isDefault}}{{^isDefault}}status {{code}}{{/isDefault}} result
|
||||
* for the {{operationId}} operation, verifying non-null values for required return data.
|
||||
*{{!
|
||||
}}{{#vendorExtensions.x-helidon-allResponseProps}}
|
||||
* @param {{name}} returned {{#isHeader}}header{{/isHeader}}{{^isHeader}}entity{{/isHeader}}{{/vendorExtensions.x-helidon-allResponseProps}}
|
||||
*/
|
||||
public {{> resultRecordTypeName }}({{#isDefault}}Status status{{#vendorExtensions.x-helidon-hasResponseProps}}, {{/vendorExtensions.x-helidon-hasResponseProps}}{{!
|
||||
}}{{/isDefault}}{{#vendorExtensions.x-helidon-allResponseProps}}{{^-first}},
|
||||
{{/-first}}{{> opResultParamDecl }}{{/vendorExtensions.x-helidon-allResponseProps}}) {
|
||||
ValidatorUtils.Validator validator = ValidatorUtils.validator();
|
||||
{{#isDefault}}
|
||||
validator.require("status for default response", status);
|
||||
{{/isDefault}}
|
||||
{{#vendorExtensions.x-helidon-requiredResponseProps}}
|
||||
validator.require("required result {{#isHeader}}header{{/isHeader}}{{^isHeader}}entity{{/isHeader}} {{name}}", {{name}});{{/vendorExtensions.x-helidon-requiredResponseProps}}{{!
|
||||
}} validator.execute();
|
||||
{{#isDefault}}
|
||||
this.status = status;
|
||||
{{/isDefault}}
|
||||
{{#vendorExtensions.x-helidon-allResponseProps}}{{!
|
||||
}} this.{{name}} = {{name}};
|
||||
{{/vendorExtensions.x-helidon-allResponseProps}}
|
||||
}
|
10
modules/openapi-generator/src/main/resources/java-helidon/server/libraries/se/paramDecl.mustache
vendored
Normal file
10
modules/openapi-generator/src/main/resources/java-helidon/server/libraries/se/paramDecl.mustache
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{{!
|
||||
Declares a parameter, including the correct datatype and parameter name. Suitable for declaring a variable or
|
||||
method parameter.
|
||||
}}{{#x-helidon-v3}}{{>dataType}} {{paramName}}{{/x-helidon-v3}}{{!
|
||||
|
||||
}}{{^x-helidon-v3}}{{^isBodyParam}}{{!
|
||||
}}{{> paramDeclType }} {{paramName}}{{!
|
||||
}}{{/isBodyParam}}{{#isBodyParam}}{{!
|
||||
}}{{> bodyParamDecl }}{{/isBodyParam}}{{!
|
||||
}}{{/x-helidon-v3}}
|
@ -0,0 +1,14 @@
|
||||
{{!
|
||||
Type declaration of a parameter for v4 and later.
|
||||
|
||||
Non-container parameters declared in the OpenAPI document as not required become Optional<dataType>; all other declarations
|
||||
are just the dataType.
|
||||
|
||||
}}{{^x-helidon-v3}}{{!
|
||||
}}{{^required}}{{^isContainer}}{{#x-helidon-use-optional}}Optional<{{/x-helidon-use-optional}}{{/isContainer}}{{/required}}{{!
|
||||
}}{{#vendorExtensions.x-helidon-isMultipartFormParam}}ReadablePart{{/vendorExtensions.x-helidon-isMultipartFormParam}}{{!
|
||||
}}{{^vendorExtensions.x-helidon-isMultipartFormParam}}{{#isFormParam}}{{> formOrBodyParamDeclType }}{{/isFormParam}}{{!
|
||||
}}{{^isFormParam}}{{#isBodyParam}}{{> formOrBodyParamDeclType }}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}}{{/isBodyParam}}{{/isFormParam}}{{!
|
||||
}}{{/vendorExtensions.x-helidon-isMultipartFormParam}}{{!
|
||||
}}{{^required}}{{^isContainer}}{{#x-helidon-use-optional}}>{{/x-helidon-use-optional}}{{/isContainer}}{{/required}}{{!
|
||||
}}{{/x-helidon-v3}}
|
@ -0,0 +1 @@
|
||||
{{operationId}}Op.{{> paramMethodName}}(request, {{^isMultipart}}{{#isFormParam}}formParams, {{/isFormParam}}{{/isMultipart}}{{#vendorExtensions.x-helidon-isMultipartFormParam}}parts, {{/vendorExtensions.x-helidon-isMultipartFormParam}}validator)
|
@ -0,0 +1 @@
|
||||
{{paramName}}
|
@ -1,4 +1,5 @@
|
||||
{{#isPathParam}}Optional.ofNullable(request.path().param("{{baseName}}")){{/isPathParam}}{{!
|
||||
{{#x-helidon-v3}}{{!
|
||||
}}{{#isPathParam}}Optional.ofNullable(request.path().param("{{baseName}}")){{/isPathParam}}{{!
|
||||
}}{{#isQueryParam}}{{#isPrimitiveType}}request.queryParams().toMap().getOrDefault("{{baseName}}", List.of()).stream().findFirst(){{/isPrimitiveType}}{{/isQueryParam}}{{!
|
||||
}}{{#isQueryParam}}{{^isPrimitiveType}}Optional.ofNullable(request.queryParams().toMap().get("{{baseName}}")){{/isPrimitiveType}}{{/isQueryParam}}{{!
|
||||
}}{{#isCookieParam}}{{#isPrimitiveType}}request.headers().cookies().toMap().getOrDefault("{{baseName}}", List.of()).stream().findFirst(){{/isPrimitiveType}}{{/isCookieParam}}{{!
|
||||
@ -11,4 +12,7 @@
|
||||
}}{{#isDate}}LocalDate::parse{{/isDate}}{{#isDateTime}}OffsetDateTime::parse{{/isDateTime}}{{!
|
||||
}}{{^isDecimal}}{{^isNumber}}{{^isDate}}{{^isDateTime}}{{{dataType}}}::valueOf{{/isDateTime}}{{/isDate}}{{/isNumber}}{{/isDecimal}}){{!
|
||||
}}{{/isString}}{{/isFile}}{{/isPrimitiveType}}{{!
|
||||
}}.orElse(null);
|
||||
}}.orElse(null);
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{^x-helidon-v3}}{{> paramMethodInvocation }};
|
||||
{{/x-helidon-v3}}
|
@ -0,0 +1,5 @@
|
||||
{{#isContainer}}GenericTypes.TYPE__{{containerTypeMapped}}_{{baseType}}{{/isContainer}}{{!
|
||||
}}{{^isContainer}}{{!
|
||||
}}{{#isFormParam}}{{^isMultipart}}Parameters.class{{/isMultipart}}{{#isMultipart}}{{{dataType}}}.class{{/isMultipart}}{{/isFormParam}}{{!
|
||||
}}{{^isFormParam}}{{{dataType}}}.class{{/isFormParam}}{{!
|
||||
}}{{/isContainer}}
|
@ -0,0 +1 @@
|
||||
{{#isFormParam}}{{/isFormParam}}
|
@ -0,0 +1,14 @@
|
||||
{{^vendorExtensions.x-helidon-hasEnumClass}}{{!
|
||||
}}{{^isString}}{{#isDecimal}}BigDecimal::new{{/isDecimal}}{{!
|
||||
}}{{#isNumber}}BigDecimal::new{{/isNumber}}{{!
|
||||
}}{{#isDate}}LocalDate::parse{{/isDate}}{{#isDateTime}}OffsetDateTime::parse{{/isDateTime}}{{!
|
||||
}}{{#isByteArray}}HexFormat.of()::parseHex{{/isByteArray}}{{!
|
||||
}}{{^isDecimal}}{{^isNumber}}{{^isDate}}{{^isDateTime}}{{^isByteArray}}{{#isContainer}}{{baseType}}{{/isContainer}}{{^isContainer}}{{{dataType}}}{{/isContainer}}::valueOf{{/isByteArray}}{{/isDateTime}}{{/isDate}}{{/isNumber}}{{/isDecimal}}{{/isString}}{{!
|
||||
}}{{#isString}}String::valueOf{{/isString}}{{!
|
||||
}}{{/vendorExtensions.x-helidon-hasEnumClass}}{{!
|
||||
}}{{!
|
||||
|
||||
Some enums are specified using a $ref to a type; to those the code adds the x-helidon-hasEnumClass boolean set to true.
|
||||
Others are described in-line in the OpenAPI document and those do not have x-helidon-hasEnumClass.
|
||||
|
||||
}}{{#vendorExtensions.x-helidon-hasEnumClass}}{{baseType}}::fromValue{{/vendorExtensions.x-helidon-hasEnumClass}}
|
@ -0,0 +1,69 @@
|
||||
{{^x-helidon-v3}}{{!
|
||||
|
||||
Most non-body parameter values are handled largely the same regardless of their origin (path, query, cookie, header).
|
||||
Wrap a single-valued parameter in an Optional only if it is NOT declared as required; otherwise insist that it be present.
|
||||
|
||||
The Helidon 4 API exposes path, query, and cookie values as Value objects but header values as Strings, so deal with
|
||||
them slightly differently.
|
||||
}}{{#vendorExtensions.x-helidon-isMultipartFormParam}}{{^required}}{{^isContainer}}Optional.ofNullable({{/isContainer}}{{/required}}parts.get("{{baseName}}"){{^required}}{{^isContainer}}){{/isContainer}}{{/required}}{{!
|
||||
}}{{/vendorExtensions.x-helidon-isMultipartFormParam}}{{!
|
||||
}}{{^vendorExtensions.x-helidon-isMultipartFormParam}}{{^isFormParam}}request{{/isFormParam}}{{!
|
||||
}}{{#isFormParam}}formParams{{/isFormParam}}{{!
|
||||
}}{{#isPathParam}}.path()
|
||||
.pathParameters(){{!
|
||||
}}{{/isPathParam}}{{!
|
||||
}}{{#isQueryParam}}.query(){{!
|
||||
}}{{/isQueryParam}}{{!
|
||||
}}{{#isCookieParam}}.headers()
|
||||
.cookies(){{!
|
||||
}}{{/isCookieParam}}{{!
|
||||
}}{{#isHeaderParam}}.headers(){{!
|
||||
}}{{/isHeaderParam}}{{!
|
||||
We have generated code to access the object from which we'll get either the first value or all the values given a name.
|
||||
Headers use "values" which accepts a HeaderName while the other objects use "all" which accepts a String to gather all of
|
||||
potentially multiple values. All types use "first" to retrieve only the first value with the name.
|
||||
}}{{#isContainer}}{{!
|
||||
}}{{#isHeaderParam}}
|
||||
.values(HeaderNames.create("{{baseName}}")){{!
|
||||
}}{{/isHeaderParam}}{{!
|
||||
}}{{^isHeaderParam}}
|
||||
.all("{{baseName}}"){{!
|
||||
}}{{/isHeaderParam}}
|
||||
.stream(){{!
|
||||
}}{{/isContainer}}{{!
|
||||
}}{{^isContainer}}
|
||||
.first({{#isHeaderParam}}HeaderNames.create({{/isHeaderParam}}"{{baseName}}"{{#isHeaderParam}}){{/isHeaderParam}}){{!
|
||||
}}{{^isHeaderParam}}
|
||||
.asOptional(){{/isHeaderParam}}{{!
|
||||
}}{{#defaultValue}}
|
||||
.or(() -> Optional.of("{{defaultValue}}")){{/defaultValue}}{{!
|
||||
}}{{/isContainer}}{{!
|
||||
}}{{^isFile}}{{^isString}}
|
||||
.map({{>paramValueConverter}}){{!
|
||||
}}{{/isString}}{{/isFile}}{{!
|
||||
}}{{#isFormParam}}{{#isFile}}
|
||||
.map(HCollectors::decodeBinaryFormParam){{/isFile}}{{/isFormParam}}{{!
|
||||
}}{{^vendorExtensions.x-helidon-hasEnumClass}}{{#isEnum}}
|
||||
.map(v -> validator.check("{{baseName}}",
|
||||
v,
|
||||
List.of({{#allowableValues}}{{#enumVars}}{{^-first}},
|
||||
{{/-first}}{{{value}}}{{/enumVars}}{{/allowableValues}}))){{!
|
||||
}}{{/isEnum}}{{/vendorExtensions.x-helidon-hasEnumClass}}{{!
|
||||
}}{{#required}}{{^isContainer}}{{!
|
||||
We use orElse(null) here even if there is a default value that was applied (in string form) above. This allows us to plug
|
||||
in the default value earlier, as a string, before any conversion to the desired datatype, so we do not have to also convert
|
||||
the default value if we wanted to use it in the orElse.
|
||||
}}
|
||||
.orElse(null){{/isContainer}}{{/required}}{{!
|
||||
}}{{#isContainer}}{{!
|
||||
}}{{#defaultValue}}
|
||||
.collect(HCollectors.toDefaultedList("{{defaultValue}}",
|
||||
{{>paramValueConverter}})){{!
|
||||
}}{{/defaultValue}}{{^defaultValue}}{{^isMap}}
|
||||
.collect(Collectors.to{{containerTypeMapped}}()){{/isMap}}{{!
|
||||
}}{{#isMap}}
|
||||
// TODO - Developer must override this method and provide the correct mapping.
|
||||
.collect(HCollectors.noOpMap()){{/isMap}}{{!
|
||||
}}{{/defaultValue}}{{!
|
||||
}}{{/isContainer}}{{/vendorExtensions.x-helidon-isMultipartFormParam}};{{!
|
||||
}}{{/x-helidon-v3}}
|
@ -0,0 +1,3 @@
|
||||
{{^x-helidon-v3}}{{#hasParams}}validator.execute();
|
||||
|
||||
{{/hasParams}}{{/x-helidon-v3}}
|
@ -0,0 +1,9 @@
|
||||
{{^x-helidon-v3}}{{#hasParams}}
|
||||
|
||||
ValidatorUtils.Validator validator = ValidatorUtils.validator();
|
||||
{{/hasParams}}{{^hasParams}}
|
||||
|
||||
{{/hasParams}}{{/x-helidon-v3}}{{!
|
||||
}}{{#hasFormParams}}
|
||||
{{> formParamsInitial }}{{/hasFormParams}}{{!
|
||||
}}
|
@ -0,0 +1,92 @@
|
||||
{{!
|
||||
For v4 and later.
|
||||
}}
|
||||
package {{apiPackage}};
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import io.helidon.common.GenericType;
|
||||
import io.helidon.http.media.multipart.MultiPart;
|
||||
import io.helidon.http.media.multipart.ReadablePart;
|
||||
import io.helidon.webserver.http.ServerRequest;
|
||||
|
||||
@io.helidon.common.Generated(value = "{{additionalProperties.generatorClass}}",
|
||||
trigger = "utility",
|
||||
version = "{{generatorVersion}}")
|
||||
class PartsUtils {
|
||||
|
||||
private final Map<String, ReadablePart> parts = new LinkedHashMap<>();
|
||||
|
||||
static Map<String, ReadablePart> partsMap(ServerRequest request) {
|
||||
Map<String, ReadablePart> parts = new LinkedHashMap<>();
|
||||
request.content().as(MultiPart.class).forEachRemaining(part -> parts.put(part.name(), part));
|
||||
return parts;
|
||||
}
|
||||
|
||||
static PartsUtils create(ServerRequest request) {
|
||||
return new PartsUtils(request);
|
||||
}
|
||||
|
||||
private PartsUtils(ServerRequest request) {
|
||||
request.content().as(MultiPart.class).forEachRemaining(part -> parts.put(part.name(), part));
|
||||
}
|
||||
|
||||
<T> T part(String partName, Class<T> type, T defaultValue) {
|
||||
ReadablePart part = parts.get(partName);
|
||||
if (part == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return part.as(type);
|
||||
}
|
||||
|
||||
<T> Optional<T> partOpt(String partName, Class<T> type, T defaultValue) {
|
||||
return Optional.ofNullable(part(partName, type, defaultValue));
|
||||
}
|
||||
|
||||
<T> T part(String partName, GenericType<T> type, T defaultValue) {
|
||||
ReadablePart part = parts.get(partName);
|
||||
if (part == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return part.as(type);
|
||||
}
|
||||
|
||||
<T> Optional<T> partOpt(String partName, GenericType<T> type, T defaultValue) {
|
||||
return Optional.ofNullable(part(partName, type, defaultValue));
|
||||
}
|
||||
|
||||
InputStream inputStreamPart(String partName) {
|
||||
ReadablePart part = parts.get(partName);
|
||||
if (part == null) {
|
||||
return null;
|
||||
}
|
||||
return part.inputStream();
|
||||
}
|
||||
|
||||
Optional<InputStream> inputStreamPartOpt(String partName) {
|
||||
return Optional.ofNullable(inputStreamPart(partName));
|
||||
}
|
||||
|
||||
File filePart(String partName, Path directory) {
|
||||
ReadablePart part = parts.get(partName);
|
||||
if (part == null) {
|
||||
return null;
|
||||
}
|
||||
try (InputStream inputStream = part.inputStream()) {
|
||||
Path path = directory.resolve(part.fileName().orElse(partName));
|
||||
inputStream.transferTo(Files.newOutputStream(path, StandardOpenOption.CREATE_NEW));
|
||||
return path.toFile();
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
{{#isPathParam}}{{> dataType }} {{paramName}} = {{> paramValue }}{{#useBeanValidation}}
|
||||
{{>beanValidationPathParams}}{{/useBeanValidation}}{{/isPathParam}}
|
||||
{{#isPathParam}}{{> paramDecl }} = {{> paramValue }}{{#useBeanValidation}}
|
||||
{{#x-helidon-v3}} {{/x-helidon-v3}}{{>beanValidationPathParams}}{{/useBeanValidation}}{{/isPathParam}}
|
@ -43,7 +43,7 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens
|
||||
// JSON-B / Jackson
|
||||
}
|
||||
|
||||
/**
|
||||
{{#hasVars}} /**
|
||||
* Create {{classname}}.
|
||||
*
|
||||
{{#vars}}
|
||||
@ -58,7 +58,7 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens
|
||||
{{#vars}}
|
||||
this.{{name}} = {{name}};
|
||||
{{/vars}}
|
||||
}
|
||||
}{{/hasVars}}
|
||||
|
||||
{{#vars}}{{#vendorExtensions.x-has-readonly-properties}}{{#jsonb}}
|
||||
@JsonbCreator
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.helidon.applications</groupId>
|
||||
@ -34,17 +34,31 @@
|
||||
<artifactId>helidon-webserver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.media</groupId>
|
||||
<artifactId>helidon-media-jsonp</artifactId>
|
||||
<groupId>io.helidon.{{^x-helidon-v3}}http.{{/x-helidon-v3}}media</groupId>
|
||||
<artifactId>helidon-{{^x-helidon-v3}}http-{{/x-helidon-v3}}media-jsonp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
{{^x-helidon-v3}}{{!
|
||||
}} <dependency>
|
||||
<groupId>io.helidon.http.media</groupId>
|
||||
<artifactId>helidon-http-media-multipart</artifactId>
|
||||
</dependency>
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}{{#x-helidon-v3}}{{!
|
||||
}} <dependency>
|
||||
<groupId>io.helidon.media</groupId>
|
||||
<artifactId>helidon-media-multipart</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
{{/x-helidon-v3}}{{!
|
||||
}} <dependency>
|
||||
<groupId>io.helidon.config</groupId>
|
||||
<artifactId>helidon-config-yaml</artifactId>
|
||||
</dependency>
|
||||
{{^x-helidon-v3}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.webserver.observe</groupId>
|
||||
<artifactId>helidon-webserver-observe-health</artifactId>
|
||||
</dependency>
|
||||
{{/x-helidon-v3}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.health</groupId>
|
||||
<artifactId>helidon-health</artifactId>
|
||||
@ -53,10 +67,28 @@
|
||||
<groupId>io.helidon.health</groupId>
|
||||
<artifactId>helidon-health-checks</artifactId>
|
||||
</dependency>
|
||||
{{^x-helidon-v3}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.webserver.observe</groupId>
|
||||
<artifactId>helidon-webserver-observe-metrics</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.metrics</groupId>
|
||||
<artifactId>helidon-metrics-system-meters</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.helidon.logging</groupId>
|
||||
<artifactId>helidon-logging-jul</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
{{/x-helidon-v3}}
|
||||
{{#x-helidon-v3}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.metrics</groupId>
|
||||
<artifactId>helidon-metrics</artifactId>
|
||||
</dependency>
|
||||
{{/x-helidon-v3}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.openapi</groupId>
|
||||
<artifactId>helidon-openapi</artifactId>
|
||||
@ -70,15 +102,14 @@
|
||||
{{/openApiNullable}}
|
||||
{{#jackson}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.media</groupId>
|
||||
<artifactId>helidon-media-jackson</artifactId>
|
||||
<groupId>io.helidon.{{^x-helidon-v3}}http.{{/x-helidon-v3}}media</groupId>
|
||||
<artifactId>helidon-{{^x-helidon-v3}}http-{{/x-helidon-v3}}media-jackson</artifactId>
|
||||
</dependency>
|
||||
{{/jackson}}
|
||||
{{#jsonb}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.media</groupId>
|
||||
<artifactId>helidon-media-jsonb</artifactId>
|
||||
<version>${helidon.version}</version>
|
||||
<groupId>io.helidon.{{#x-helidon-v3}}http.{{/x-helidon-v3}}media</groupId>
|
||||
<artifactId>helidon-{{#x-helidon-v3}}http-{{/x-helidon-v3}}media-jsonb</artifactId>
|
||||
</dependency>
|
||||
{{/jsonb}}
|
||||
<dependency>
|
||||
@ -91,6 +122,13 @@
|
||||
<artifactId>helidon-webclient</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
{{^x-helidon-v3}}
|
||||
<dependency>
|
||||
<groupId>io.helidon.webserver.testing.junit5</groupId>
|
||||
<artifactId>helidon-webserver-testing-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
{{/x-helidon-v3}}
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -1 +1 @@
|
||||
{{#isQueryParam}}{{>dataType}} {{paramName}} = {{>paramValue}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{/isQueryParam}}
|
||||
{{#isQueryParam}}{{>paramDecl}} = {{>paramValue}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{/isQueryParam}}
|
@ -0,0 +1,3 @@
|
||||
{{!
|
||||
Compute the record type for a result.
|
||||
}}{{^isDefault}}Response{{code}}{{/isDefault}}{{#isDefault}}Default{{/isDefault}}
|
@ -3,8 +3,19 @@ package {{apiPackage}};
|
||||
import java.lang.reflect.Array;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
{{^x-helidon-v3}}
|
||||
import java.util.List;
|
||||
{{/x-helidon-v3}}
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
{{^x-helidon-v3}}
|
||||
import java.util.Optional;
|
||||
|
||||
import io.helidon.common.Errors;
|
||||
import io.helidon.common.mapper.OptionalValue;
|
||||
import io.helidon.webserver.http.ServerRequest;
|
||||
import io.helidon.webserver.http.ServerResponse;
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
import {{rootJavaEEPackage}}.validation.ValidationException;
|
||||
|
||||
@ -109,4 +120,301 @@ public final class ValidatorUtils {
|
||||
throw new ValidationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
{{^x-helidon-v3}}{{!
|
||||
}}
|
||||
public static <T> T nonEmpty(T arg) {
|
||||
try {
|
||||
return Objects.requireNonNull(arg, "Required value is missing");
|
||||
} catch (NullPointerException npe) {
|
||||
throw new ValidationException(npe);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T nonEmpty(Optional<T> opt) {
|
||||
if (opt.isEmpty()) {
|
||||
throw new ValidationException("Required value is missing");
|
||||
}
|
||||
return opt.get();
|
||||
}
|
||||
|
||||
public static <T> T nonEmpty(OptionalValue<T> ov) {
|
||||
if (ov.isEmpty()) {
|
||||
throw new ValidationException("Required value is missing");
|
||||
}
|
||||
return ov.get();
|
||||
}
|
||||
|
||||
public static <M extends Map<?, ?>> M nonEmpty(M map) {
|
||||
if (map.isEmpty()) {
|
||||
throw new ValidationException("Required value is missing");
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static <C extends Collection<?>> C nonEmpty(C coll) {
|
||||
if (coll.isEmpty()) {
|
||||
throw new ValidationException("Required value is missing");
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
|
||||
static Validator validator() {
|
||||
return new Validator();
|
||||
}
|
||||
|
||||
public static class Validator {
|
||||
|
||||
private final Errors.Collector errorsCollector = Errors.collector();
|
||||
|
||||
<T> T check(String paramName, T paramValue, List<T> validValues) {
|
||||
if (!validValues.contains(paramValue)) {
|
||||
errorsCollector.fatal(String.format("Invalid value %s = '%s' not among %s",
|
||||
paramName,
|
||||
paramValue,
|
||||
validValues));
|
||||
}
|
||||
return paramValue;
|
||||
}
|
||||
|
||||
<T> T require(String paramName, T paramValue) {
|
||||
if (paramValue == null || ((paramValue instanceof Optional opt) && opt.isEmpty())) {
|
||||
errorsCollector.fatal(String.format("Missing required param: %s", paramName));
|
||||
}
|
||||
return paramValue;
|
||||
}
|
||||
|
||||
<T> List<T> require(String paramName, List<T> paramValues) {
|
||||
if (paramValues.isEmpty()) {
|
||||
errorsCollector.fatal(String.format("Empty required parameter: %s", paramName));
|
||||
}
|
||||
return paramValues;
|
||||
}
|
||||
|
||||
<T> T require(String paramName, Optional<T> optionalValue) {
|
||||
if (optionalValue.isEmpty()) {
|
||||
errorsCollector.fatal(String.format("Empty required parameter: %s", paramName));
|
||||
}
|
||||
return optionalValue.orElse(null);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Long value, Long min, boolean isExclusive) {
|
||||
boolean result = value == null || value > min || !isExclusive && value.equals(min);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s %d violates %sminimum %d",
|
||||
paramName,
|
||||
value,
|
||||
isExclusive ? "exclusive " : "",
|
||||
min));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<Long> value, Long min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Integer value, Integer min, boolean isExclusive) {
|
||||
return validateMin(paramName, Long.valueOf(value), Long.valueOf(min), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<Integer> value, Integer min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Short value, Short min, boolean isExclusive) {
|
||||
return validateMin(paramName, value.intValue(), min.intValue(), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<Short> value, Short min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Byte value, Byte min, boolean isExclusive) {
|
||||
return validateMin(paramName, value.intValue(), min.intValue(), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<Byte> value, Byte min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Double value, Double min, boolean isExclusive) {
|
||||
return validateMin(paramName, new BigDecimal(value), new BigDecimal(min), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<Double> value, Double min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Float value, Float min, boolean isExclusive) {
|
||||
boolean result = value == null || value.compareTo(min) > 0 || isExclusive && value.equals(min);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s %f violates %sminimum %f",
|
||||
paramName,
|
||||
value,
|
||||
isExclusive ? "exclusive " : "",
|
||||
min));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<Float> value, Float min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, BigDecimal value, String min, boolean isExclusive) {
|
||||
return validateMin(paramName, value, new BigDecimal(min), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, BigDecimal value, BigDecimal min, boolean isExclusive) {
|
||||
boolean result = value == null || value.compareTo(min) > 0 || !isExclusive && value.equals(min);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s %f violates %sminimum %f",
|
||||
paramName,
|
||||
value,
|
||||
isExclusive ? "exclusive " : "",
|
||||
min));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validateMin(String paramName, Optional<BigDecimal> value, String min, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), min, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Long value, Long max, boolean isExclusive) {
|
||||
boolean result = value == null || value < max || !isExclusive && value.equals(max);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s %d violates %smaximum %d",
|
||||
paramName,
|
||||
value,
|
||||
isExclusive ? "exclusive " : "",
|
||||
max));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<Long> value, Long max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMax(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Integer value, Integer max, boolean isExclusive) {
|
||||
return validateMax(paramName, Long.valueOf(value), Long.valueOf(max), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<Integer> value, Integer max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMax(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Short value, Short max, boolean isExclusive) {
|
||||
return validateMax(paramName, value.intValue(), max.intValue(), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<Short> value, Short max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMax(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Byte value, Byte max, boolean isExclusive) {
|
||||
return validateMax(paramName, value.intValue(), max.intValue(), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<Byte> value, Byte max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMax(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Double value, Double max, boolean isExclusive) {
|
||||
return validateMax(paramName, new BigDecimal(value), new BigDecimal(max), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<Double> value, Double max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMin(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Float value, Float max, boolean isExclusive) {
|
||||
boolean result = value == null || value.compareTo(max) < 0 || isExclusive && value.equals(max);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s %f violates %smaximum %f",
|
||||
paramName,
|
||||
value,
|
||||
isExclusive ? "exclusive " : "",
|
||||
max));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<Float> value, Float max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMax(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, BigDecimal value, String max, boolean isExclusive) {
|
||||
return validateMax(paramName, value, new BigDecimal(max), isExclusive);
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, BigDecimal value, BigDecimal max, boolean isExclusive) {
|
||||
boolean result = value == null || value.compareTo(max) < 0 || !isExclusive && value.equals(max);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s %f violates %smaximum %f",
|
||||
paramName,
|
||||
value,
|
||||
isExclusive ? "exclusive " : "",
|
||||
max));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validateMax(String paramName, Optional<BigDecimal> value, String max, boolean isExclusive) {
|
||||
return value.isEmpty() || validateMax(paramName, value.get(), max, isExclusive);
|
||||
}
|
||||
|
||||
boolean validatePattern(String paramName, String value, String pattern) {
|
||||
boolean result = value == null || value.matches(pattern);
|
||||
if (!result) {
|
||||
errorsCollector.fatal(String.format("Parameter %s '%s' does not match pattern '%s'",
|
||||
paramName,
|
||||
value,
|
||||
pattern));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean validatePattern(String paramName, Optional<String> value, String pattern) {
|
||||
return value.isEmpty() || validatePattern(pattern, value.get(), pattern);
|
||||
}
|
||||
|
||||
boolean validateSize(String paramName, Object value, Integer min, Integer max) {
|
||||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
int size = switch (value) {
|
||||
case Map<?, ?> map -> map.size();
|
||||
case CharSequence cs -> cs.length();
|
||||
case Collection<?> coll -> coll.size();
|
||||
default -> value.getClass().isArray() ? Array.getLength(value) : -1;
|
||||
};
|
||||
if (size == -1) {
|
||||
errorsCollector.fatal(String.format("Parameter %s with type %s unrecognized for validating size",
|
||||
paramName,
|
||||
value.getClass().getName()));
|
||||
return false;
|
||||
}
|
||||
if (min != null) {
|
||||
validateMin(paramName, size, min, false);
|
||||
}
|
||||
if (max != null) {
|
||||
validateMax(paramName, size, max, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean validateSize(String paramName, Optional<Object> value, Integer min, Integer max) {
|
||||
return value.isEmpty() || validateSize(paramName, value.get(), min, max);
|
||||
}
|
||||
|
||||
void execute() {
|
||||
Errors errors = errorsCollector.collect();
|
||||
if (errors.hasFatal()) {
|
||||
throw new ValidationException("Validation errors: " + errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{{/x-helidon-v3}}{{#x-helidon-v3}}}{{/x-helidon-v3}}
|
@ -3,10 +3,13 @@
|
||||
# For more information see $JAVA_HOME/jre/lib/logging.properties
|
||||
|
||||
# Send messages to the console
|
||||
handlers=io.helidon.common.HelidonConsoleHandler
|
||||
{{#x-helidon-v3}}handlers=io.helidon.common.HelidonConsoleHandler
|
||||
{{/x-helidon-v3}}{{^x-helidon-v3}}handlers=java.util.logging.ConsoleHandler
|
||||
{{/x-helidon-v3}}
|
||||
|
||||
# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
|
||||
java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
|
||||
{{#x-helidon-v3}}# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread
|
||||
{{/x-helidon-v3}}{{!
|
||||
}}java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n
|
||||
|
||||
# Global logging level. Can be overridden by specific loggers
|
||||
.level=INFO
|
||||
|
@ -38,4 +38,14 @@ public class HelidonCommonCodegenTest {
|
||||
assertThat(test.chooseVersion("1.2.2", List.of("3.2.1", "3.2.0", "2.0.4", "1.2.3", "1.2.2", "1.1.0")))
|
||||
.isEqualTo("1.2.2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVersionNotInDefaultListWithNoNetwork() {
|
||||
// Simulate a network failure so the full list of valid versions is inaccessible and the user selects a version
|
||||
// that is not in the cached values or the hard-coded list.
|
||||
assertThat(test.chooseVersion("4.0.8", List.of("1.2.3", "2.5.6", "3.2.7", "4.0.9")))
|
||||
.isEqualTo("4.0.8");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -26,6 +24,8 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -33,7 +31,9 @@ import org.openapitools.client.model.FakeBigDecimalMap200Response;
|
||||
import java.io.File;
|
||||
import org.openapitools.client.model.FileSchemaTestClass;
|
||||
import org.openapitools.client.model.HealthCheckResult;
|
||||
import java.util.List;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import org.openapitools.client.model.OuterComposite;
|
||||
import org.openapitools.client.model.OuterObjectWithEnumProperty;
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -26,6 +24,8 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -26,6 +24,8 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.ModelApiResponse;
|
||||
import org.openapitools.client.model.Pet;
|
||||
import java.util.Set;
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -25,6 +23,8 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.Order;
|
||||
|
||||
/**
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -25,6 +23,8 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import org.openapitools.client.model.User;
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -21,7 +21,9 @@ import org.openapitools.client.model.FakeBigDecimalMap200Response;
|
||||
import java.io.File;
|
||||
import org.openapitools.client.model.FileSchemaTestClass;
|
||||
import org.openapitools.client.model.HealthCheckResult;
|
||||
import java.util.List;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import org.openapitools.client.model.OuterComposite;
|
||||
import org.openapitools.client.model.OuterObjectWithEnumProperty;
|
||||
|
@ -14,6 +14,8 @@
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -14,6 +14,8 @@
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.ModelApiResponse;
|
||||
import org.openapitools.client.model.Pet;
|
||||
import java.util.Set;
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.Order;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import org.openapitools.client.model.User;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>io.helidon.applications</groupId>
|
||||
<artifactId>helidon-mp</artifactId>
|
||||
<version>4.0.8</version>
|
||||
<version>4.0.11</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>petstore-helidon-client-mp</artifactId>
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -26,6 +24,8 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -33,8 +31,11 @@ import org.openapitools.client.model.FakeBigDecimalMap200Response;
|
||||
import java.io.File;
|
||||
import org.openapitools.client.model.FileSchemaTestClass;
|
||||
import org.openapitools.client.model.HealthCheckResult;
|
||||
import java.util.List;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Optional;
|
||||
import org.openapitools.client.model.OuterComposite;
|
||||
import org.openapitools.client.model.OuterObjectWithEnumProperty;
|
||||
import org.openapitools.client.model.Pet;
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -26,6 +24,8 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -26,7 +24,10 @@ import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.ModelApiResponse;
|
||||
import java.util.Optional;
|
||||
import org.openapitools.client.model.Pet;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -25,6 +23,8 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.Order;
|
||||
|
||||
/**
|
||||
|
@ -14,8 +14,6 @@ package org.openapitools.client.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.ws.rs.*;
|
||||
@ -25,7 +23,10 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Optional;
|
||||
import org.openapitools.client.model.User;
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,8 @@
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -21,8 +21,11 @@ import org.openapitools.client.model.FakeBigDecimalMap200Response;
|
||||
import java.io.File;
|
||||
import org.openapitools.client.model.FileSchemaTestClass;
|
||||
import org.openapitools.client.model.HealthCheckResult;
|
||||
import java.util.List;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Optional;
|
||||
import org.openapitools.client.model.OuterComposite;
|
||||
import org.openapitools.client.model.OuterObjectWithEnumProperty;
|
||||
import org.openapitools.client.model.Pet;
|
||||
|
@ -14,6 +14,8 @@
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import org.openapitools.client.model.Client;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -14,7 +14,10 @@
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.ModelApiResponse;
|
||||
import java.util.Optional;
|
||||
import org.openapitools.client.model.Pet;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.openapitools.client.model.Order;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
@ -13,7 +13,10 @@
|
||||
|
||||
package org.openapitools.client.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Optional;
|
||||
import org.openapitools.client.model.User;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
@ -0,0 +1,23 @@
|
||||
# OpenAPI Generator Ignore
|
||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
@ -0,0 +1,129 @@
|
||||
README.md
|
||||
docs/AdditionalPropertiesClass.md
|
||||
docs/AllOfWithSingleRef.md
|
||||
docs/Animal.md
|
||||
docs/AnotherFakeApi.md
|
||||
docs/ArrayOfArrayOfNumberOnly.md
|
||||
docs/ArrayOfNumberOnly.md
|
||||
docs/ArrayTest.md
|
||||
docs/Capitalization.md
|
||||
docs/Cat.md
|
||||
docs/Category.md
|
||||
docs/ChildWithNullable.md
|
||||
docs/ClassModel.md
|
||||
docs/Client.md
|
||||
docs/DefaultApi.md
|
||||
docs/DeprecatedObject.md
|
||||
docs/Dog.md
|
||||
docs/EnumArrays.md
|
||||
docs/EnumClass.md
|
||||
docs/EnumTest.md
|
||||
docs/FakeApi.md
|
||||
docs/FakeBigDecimalMap200Response.md
|
||||
docs/FakeClassnameTags123Api.md
|
||||
docs/FileSchemaTestClass.md
|
||||
docs/Foo.md
|
||||
docs/FooGetDefaultResponse.md
|
||||
docs/FormatTest.md
|
||||
docs/HasOnlyReadOnly.md
|
||||
docs/HealthCheckResult.md
|
||||
docs/MapTest.md
|
||||
docs/MixedPropertiesAndAdditionalPropertiesClass.md
|
||||
docs/Model200Response.md
|
||||
docs/ModelApiResponse.md
|
||||
docs/ModelFile.md
|
||||
docs/ModelList.md
|
||||
docs/ModelReturn.md
|
||||
docs/Name.md
|
||||
docs/NullableClass.md
|
||||
docs/NumberOnly.md
|
||||
docs/ObjectWithDeprecatedFields.md
|
||||
docs/Order.md
|
||||
docs/OuterComposite.md
|
||||
docs/OuterEnum.md
|
||||
docs/OuterEnumDefaultValue.md
|
||||
docs/OuterEnumInteger.md
|
||||
docs/OuterEnumIntegerDefaultValue.md
|
||||
docs/OuterObjectWithEnumProperty.md
|
||||
docs/ParentWithNullable.md
|
||||
docs/Pet.md
|
||||
docs/PetApi.md
|
||||
docs/ReadOnlyFirst.md
|
||||
docs/SingleRefType.md
|
||||
docs/SpecialModelName.md
|
||||
docs/StoreApi.md
|
||||
docs/Tag.md
|
||||
docs/TestInlineFreeformAdditionalPropertiesRequest.md
|
||||
docs/User.md
|
||||
docs/UserApi.md
|
||||
pom.xml
|
||||
src/main/java/org/openapitools/client/ApiClient.java
|
||||
src/main/java/org/openapitools/client/ApiResponse.java
|
||||
src/main/java/org/openapitools/client/ApiResponseBase.java
|
||||
src/main/java/org/openapitools/client/Pair.java
|
||||
src/main/java/org/openapitools/client/RFC3339DateFormat.java
|
||||
src/main/java/org/openapitools/client/api/AnotherFakeApi.java
|
||||
src/main/java/org/openapitools/client/api/AnotherFakeApiImpl.java
|
||||
src/main/java/org/openapitools/client/api/DefaultApi.java
|
||||
src/main/java/org/openapitools/client/api/DefaultApiImpl.java
|
||||
src/main/java/org/openapitools/client/api/FakeApi.java
|
||||
src/main/java/org/openapitools/client/api/FakeApiImpl.java
|
||||
src/main/java/org/openapitools/client/api/FakeClassnameTags123Api.java
|
||||
src/main/java/org/openapitools/client/api/FakeClassnameTags123ApiImpl.java
|
||||
src/main/java/org/openapitools/client/api/PetApi.java
|
||||
src/main/java/org/openapitools/client/api/PetApiImpl.java
|
||||
src/main/java/org/openapitools/client/api/ResponseType.java
|
||||
src/main/java/org/openapitools/client/api/StoreApi.java
|
||||
src/main/java/org/openapitools/client/api/StoreApiImpl.java
|
||||
src/main/java/org/openapitools/client/api/UserApi.java
|
||||
src/main/java/org/openapitools/client/api/UserApiImpl.java
|
||||
src/main/java/org/openapitools/client/model/AdditionalPropertiesClass.java
|
||||
src/main/java/org/openapitools/client/model/AllOfWithSingleRef.java
|
||||
src/main/java/org/openapitools/client/model/Animal.java
|
||||
src/main/java/org/openapitools/client/model/ArrayOfArrayOfNumberOnly.java
|
||||
src/main/java/org/openapitools/client/model/ArrayOfNumberOnly.java
|
||||
src/main/java/org/openapitools/client/model/ArrayTest.java
|
||||
src/main/java/org/openapitools/client/model/Capitalization.java
|
||||
src/main/java/org/openapitools/client/model/Cat.java
|
||||
src/main/java/org/openapitools/client/model/Category.java
|
||||
src/main/java/org/openapitools/client/model/ChildWithNullable.java
|
||||
src/main/java/org/openapitools/client/model/ClassModel.java
|
||||
src/main/java/org/openapitools/client/model/Client.java
|
||||
src/main/java/org/openapitools/client/model/DeprecatedObject.java
|
||||
src/main/java/org/openapitools/client/model/Dog.java
|
||||
src/main/java/org/openapitools/client/model/EnumArrays.java
|
||||
src/main/java/org/openapitools/client/model/EnumClass.java
|
||||
src/main/java/org/openapitools/client/model/EnumTest.java
|
||||
src/main/java/org/openapitools/client/model/FakeBigDecimalMap200Response.java
|
||||
src/main/java/org/openapitools/client/model/FileSchemaTestClass.java
|
||||
src/main/java/org/openapitools/client/model/Foo.java
|
||||
src/main/java/org/openapitools/client/model/FooGetDefaultResponse.java
|
||||
src/main/java/org/openapitools/client/model/FormatTest.java
|
||||
src/main/java/org/openapitools/client/model/HasOnlyReadOnly.java
|
||||
src/main/java/org/openapitools/client/model/HealthCheckResult.java
|
||||
src/main/java/org/openapitools/client/model/MapTest.java
|
||||
src/main/java/org/openapitools/client/model/MixedPropertiesAndAdditionalPropertiesClass.java
|
||||
src/main/java/org/openapitools/client/model/Model200Response.java
|
||||
src/main/java/org/openapitools/client/model/ModelApiResponse.java
|
||||
src/main/java/org/openapitools/client/model/ModelFile.java
|
||||
src/main/java/org/openapitools/client/model/ModelList.java
|
||||
src/main/java/org/openapitools/client/model/ModelReturn.java
|
||||
src/main/java/org/openapitools/client/model/Name.java
|
||||
src/main/java/org/openapitools/client/model/NullableClass.java
|
||||
src/main/java/org/openapitools/client/model/NumberOnly.java
|
||||
src/main/java/org/openapitools/client/model/ObjectWithDeprecatedFields.java
|
||||
src/main/java/org/openapitools/client/model/Order.java
|
||||
src/main/java/org/openapitools/client/model/OuterComposite.java
|
||||
src/main/java/org/openapitools/client/model/OuterEnum.java
|
||||
src/main/java/org/openapitools/client/model/OuterEnumDefaultValue.java
|
||||
src/main/java/org/openapitools/client/model/OuterEnumInteger.java
|
||||
src/main/java/org/openapitools/client/model/OuterEnumIntegerDefaultValue.java
|
||||
src/main/java/org/openapitools/client/model/OuterObjectWithEnumProperty.java
|
||||
src/main/java/org/openapitools/client/model/ParentWithNullable.java
|
||||
src/main/java/org/openapitools/client/model/Pet.java
|
||||
src/main/java/org/openapitools/client/model/ReadOnlyFirst.java
|
||||
src/main/java/org/openapitools/client/model/SingleRefType.java
|
||||
src/main/java/org/openapitools/client/model/SpecialModelName.java
|
||||
src/main/java/org/openapitools/client/model/Tag.java
|
||||
src/main/java/org/openapitools/client/model/TestInlineFreeformAdditionalPropertiesRequest.java
|
||||
src/main/java/org/openapitools/client/model/User.java
|
@ -0,0 +1 @@
|
||||
7.8.0-SNAPSHOT
|
24
samples/client/petstore/java-helidon-client/v4/se/README.md
Normal file
24
samples/client/petstore/java-helidon-client/v4/se/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# OpenAPI Petstore
|
||||
|
||||
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\
|
||||
|
||||
|
||||
## Overview
|
||||
This project was generated using the Helidon OpenAPI Generator.
|
||||
|
||||
The generated classes use the programming model from the Helidon WebClient implementation, primarily the `WebClient` interface and its associated
|
||||
`WebClientClient.Builder` class. Refer to the Helidon WebClient documentation for complete information about them.
|
||||
|
||||
## Using the Generated Classes and Interfaces
|
||||
The generated `ApiClient` class wraps a `WebClient` instance. Similarly, the `ApiClient.Builder` class wraps the `WebClientConfig.Builder` class.
|
||||
|
||||
The generated `xxxApi` interfaces and `xxxApiImpl` classes make it very simple for your code to send requests (with input parameters) to the remote service which the OpenAPI document describes and to process the response (with output values) from the remote service.
|
||||
|
||||
To use the generated API, your code performs the following steps.
|
||||
|
||||
1. Create an instance of the `ApiClient` using its `Builder`.
|
||||
2. Create an instance of a `xxxApi` it wants to access, typically by invoking `xxxApiImpl.create(ApiClient)` and passing the `ApiClient` instance just created.
|
||||
3. Invoke any of the `public` methods on the `xxxApi` instance, passing the input parameters and saving the returned `Single<WebClientResponse>` object.
|
||||
4. Invoke methods on the returned `Single<WebClientResponse>` to process the response and any output from it.
|
||||
|
||||
Browse the methods and JavaDoc on the generated classes for more information.
|
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
# AdditionalPropertiesClass
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Name | Type | Description | Notes |
|
||||
|------------ | ------------- | ------------- | -------------|
|
||||
|**mapProperty** | **Map<String, String>** | | [optional] |
|
||||
|**mapOfMapProperty** | **Map<String, Map<String, String>>** | | [optional] |
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user