Add support for Helidon 4 MP client and server generation (#18627)

* Add support for Helidon 4 MP client and server generation

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>

* Rerun samples generation trying to fix spring jobs

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>

* Update copyright

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>

* Correct the copyright notice

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>

---------

Signed-off-by: Tim Quinn <tim.quinn@oracle.com>
This commit is contained in:
Tim Quinn 2024-05-12 03:49:28 -05:00 committed by GitHub
parent 4b56fd281a
commit 0e05cf26d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
953 changed files with 27164 additions and 287 deletions

View File

@ -1,14 +1,14 @@
name: Samples Java Helidon
name: Samples Java Helidon v3
on:
push:
paths:
- samples/client/petstore/java-helidon-client/**
- samples/server/petstore/java-helidon-server/**
- samples/client/petstore/java-helidon-client/v3/**
- samples/server/petstore/java-helidon-server/v3/**
pull_request:
paths:
- samples/client/petstore/java-helidon-client/**
- samples/server/petstore/java-helidon-server/**
- samples/client/petstore/java-helidon-client/v3/**
- samples/server/petstore/java-helidon-server/v3/**
jobs:
build:
name: Build Java Helidon
@ -17,10 +17,10 @@ jobs:
fail-fast: false
matrix:
sample:
- samples/client/petstore/java-helidon-client/mp
- samples/client/petstore/java-helidon-client/se
- samples/server/petstore/java-helidon-server/mp
- samples/server/petstore/java-helidon-server/se
- samples/client/petstore/java-helidon-client/v3/mp
- samples/client/petstore/java-helidon-client/v3/se
- samples/server/petstore/java-helidon-server/v3/mp
- samples/server/petstore/java-helidon-server/v3/se
version: [17]
steps:
- uses: actions/checkout@v4

View File

@ -0,0 +1,39 @@
name: Samples Java Helidon v4
on:
push:
paths:
- samples/client/petstore/java-helidon-client/v4/**
- samples/server/petstore/java-helidon-server/v4/**
pull_request:
paths:
- samples/client/petstore/java-helidon-client/v4/**
- samples/server/petstore/java-helidon-server/v4/**
jobs:
build:
name: Build Java Helidon
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
- samples/client/petstore/java-helidon-client/v4/mp
- samples/server/petstore/java-helidon-server/v4/mp
version: [21]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: ${{ matrix.version }}
- name: Cache maven dependencies
uses: actions/cache@v4
env:
cache-name: maven-repository
with:
path: |
~/.m2
key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
- name: Build
working-directory: ${{ matrix.sample }}
run: mvn clean package

View File

@ -4,28 +4,28 @@ on:
paths:
# clients
- samples/openapi3/client/petstore/spring-cloud-3/**
- samples/client/petstore/java-helidon-client/mp/**
- samples/client/petstore/java-helidon-client/se/**
- samples/client/petstore/java-helidon-client/v3/mp/**
- samples/client/petstore/java-helidon-client/v3/se/**
- samples/client/petstore/spring-http-interface-reactive/**
- samples/client/petstore/spring-http-interface/**
- samples/client/petstore/java/webclient-jakarta/**
# servers
- samples/openapi3/server/petstore/springboot-3/**
- samples/server/petstore/java-helidon-server/mp/**
- samples/server/petstore/java-helidon-server/se/**
- samples/server/petstore/java-helidon-server/v3/mp/**
- samples/server/petstore/java-helidon-server/v3/se/**
pull_request:
paths:
# clients
- samples/openapi3/client/petstore/spring-cloud-3/**
- samples/client/petstore/java-helidon-client/mp/**
- samples/client/petstore/java-helidon-client/se/**
- samples/client/petstore/java-helidon-client/v3/mp/**
- samples/client/petstore/java-helidon-client/v3/se/**
- samples/client/petstore/spring-http-interface-reactive/**
- samples/client/petstore/spring-http-interface/**
- samples/client/petstore/java/webclient-jakarta/**
# servers
- samples/openapi3/server/petstore/springboot-3/**
- samples/server/petstore/java-helidon-server/mp/**
- samples/server/petstore/java-helidon-server/se/**
- samples/server/petstore/java-helidon-server/v3/mp/**
- samples/server/petstore/java-helidon-server/v3/se/**
jobs:
build:
name: Build with JDK17
@ -36,15 +36,15 @@ jobs:
sample:
# clients
- samples/openapi3/client/petstore/spring-cloud-3
- samples/client/petstore/java-helidon-client/mp
- samples/client/petstore/java-helidon-client/se
- samples/client/petstore/java-helidon-client/v3/mp/
- samples/client/petstore/java-helidon-client/v3/se
- samples/client/petstore/spring-http-interface-reactive
- samples/client/petstore/spring-http-interface
- samples/client/petstore/java/webclient-jakarta
# servers
- samples/openapi3/server/petstore/springboot-3
- samples/server/petstore/java-helidon-server/mp
- samples/server/petstore/java-helidon-server/se
- samples/server/petstore/java-helidon-server/v3/mp/
- samples/server/petstore/java-helidon-server/v3/se
- samples/client/petstore/spring-http-interface-reactive
- samples/client/petstore/spring-http-interface
steps:

43
.github/workflows/samples-jdk21.yaml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Samples JDK21
on:
push:
paths:
# clients
- samples/client/petstore/java-helidon-client/v4/mp/**
# servers
- samples/server/petstore/java-helidon-server/v4/mp/**
pull_request:
paths:
# clients
- samples/client/petstore/java-helidon-client/v4/mp/**
# servers
- samples/server/petstore/java-helidon-server/v4/mp/**
jobs:
build:
name: Build with JDK21
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# clients
- samples/client/petstore/java-helidon-client/v4/mp/
# servers
- samples/server/petstore/java-helidon-server/v4/mp/
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 21
- name: Cache maven dependencies
uses: actions/cache@v4
env:
cache-name: maven-repository
with:
path: |
~/.m2
key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
- name: Build
working-directory: ${{ matrix.sample }}
run: mvn clean package

View File

@ -1,8 +1,9 @@
generatorName: java-helidon-client
library: mp
outputDir: samples/client/petstore/java-helidon-client/mp
outputDir: samples/client/petstore/java-helidon-client/v3/mp
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
additionalProperties:
helidonVersion: 3.2.7
artifactId: petstore-helidon-client-mp
hideGenerationTimestamp: "true"
configureAuth: "false"

View File

@ -0,0 +1,14 @@
generatorName: java-helidon-client
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
artifactId: petstore-helidon-client-mp
hideGenerationTimestamp: "true"
configureAuth: "false"
build: "all"
test: "spock"
requiredPropertiesInConstructor: "false"
visitable: "true"
fullProject: "true"

View File

@ -1,8 +1,9 @@
generatorName: java-helidon-client
library: se
outputDir: samples/client/petstore/java-helidon-client/se
outputDir: samples/client/petstore/java-helidon-client/v3/se
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
additionalProperties:
helidonVersion: 3.2.7
artifactId: petstore-helidon-client-se
hideGenerationTimestamp: "true"
configureAuth: "false"

View File

@ -1,9 +1,10 @@
generatorName: java-helidon-server
library: mp
outputDir: samples/server/petstore/java-helidon-server/mp
outputDir: samples/server/petstore/java-helidon-server/v3/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: 3.2.7
artifactId: petstore-helidon-server-mp
hideGenerationTimestamp: "true"
build: "all"

View File

@ -0,0 +1,13 @@
generatorName: java-helidon-server
library: mp
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
artifactId: petstore-helidon-server-mp
hideGenerationTimestamp: "true"
build: "all"
test: "spock"
useAuth: "false"
fullProject: "true"

View File

@ -1,9 +1,10 @@
generatorName: java-helidon-server
library: se
outputDir: samples/server/petstore/java-helidon-server/se
outputDir: samples/server/petstore/java-helidon-server/v3/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: 3.2.7
artifactId: petstore-helidon-server-se
hideGenerationTimestamp: "true"
fullProject: "true"

View File

@ -40,7 +40,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|fullProject|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.| ||
|generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false|
|groupId|groupId in generated pom.xml| |org.openapitools|
|helidonVersion|Helidon version for generated code| |3.0.1|
|helidonVersion|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.| |Highest released version.|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |false|
|ignoreAnyOfInEnum|Ignore anyOf keyword in enum| |false|
|implicitHeaders|Skip header parameters in the generated API methods using @ApiImplicitParams annotation.| |false|

View File

@ -40,14 +40,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false|
|gradleProject|Whether to generate gradle project instead of maven.| |false|
|groupId|groupId in generated pom.xml| |org.openapitools|
|helidonVersion|Helidon version for generated code| |3.0.1|
|helidonVersion|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.| |Highest released version.|
|hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |false|
|ignoreAnyOfInEnum|Ignore anyOf keyword in enum| |false|
|implicitHeaders|Skip header parameters in the generated API methods using @ApiImplicitParams annotation.| |false|
|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
|invokerPackage|root package for generated code| |org.openapitools.server|
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|library|library template (sub-template) to use|<dl><dt>**mp**</dt><dd>Helidon MP Server</dd><dt>**se**</dt><dd>Helidon SE Server</dd><dt>**nima**</dt><dd>Helidon NIMA Server</dd><dt>**nima-annotations**</dt><dd>Helidon NIMA Annotations Server</dd></dl>|se|
|library|library template (sub-template) to use|<dl><dt>**mp**</dt><dd>Helidon MP Server</dd><dt>**se**</dt><dd>Helidon SE Server</dd></dl>|se|
|licenseName|The name of the license| |Unlicense|
|licenseUrl|The URL of the license| |http://unlicense.org|
|modelPackage|package for generated models| |org.openapitools.server.model|

View File

@ -299,6 +299,11 @@
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-util</artifactId>
<version>${resolver-util-version}</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>

View File

@ -1,6 +1,6 @@
/*
* Copyright 2022 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022 Oracle and/or its affiliates
* Copyright 2022, 2024 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022, 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.
@ -17,17 +17,37 @@
package org.openapitools.codegen.languages;
import java.io.File;
import java.io.IOException;
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.file.Files;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.servers.Server;
import org.eclipse.aether.util.version.GenericVersionScheme;
import org.eclipse.aether.version.InvalidVersionSpecificationException;
import org.eclipse.aether.version.Version;
import org.eclipse.aether.version.VersionConstraint;
import org.eclipse.aether.version.VersionScheme;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenOperation;
@ -52,11 +72,10 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
static final String HELIDON_MP = "mp";
static final String HELIDON_SE = "se";
static final String HELIDON_NIMA = "nima";
static final String HELIDON_NIMA_ANNOTATIONS = "nima-annotations";
static final String MICROPROFILE_ROOT_PACKAGE = "rootJavaEEPackage";
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_RETURN_TYPE = "x-helidon-hasReturnType";
static final String X_RETURN_TYPE_EXAMPLE_VALUE = "x-helidon-exampleReturnTypeValue";
static final String MICROPROFILE_ROOT_PACKAGE_DESC = "Root package name for Java EE";
@ -66,7 +85,6 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
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>();
// for generated doc
static final String MICROPROFILE_ROOT_PACKAGE_DEFAULT =
"Helidon 2.x and earlier: " + MICROPROFILE_ROOT_PACKAGE_JAVAX
@ -75,9 +93,11 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
static final String SERIALIZATION_LIBRARY_JACKSON = "jackson";
static final String SERIALIZATION_LIBRARY_JSONB = "jsonb";
public static final String HELIDON_VERSION = "helidonVersion";
public static final String DEFAULT_HELIDON_VERSION = "3.0.1";
static final String HELIDON_VERSION_DESC = "Helidon version for generated code";
public static final String HELIDON_VERSION = "helidonVersion";
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 FULL_PROJECT = "fullProject";
static final String FULL_PROJECT_DESC = "If set to true, it will generate all files; if set to false, " +
@ -86,8 +106,22 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
"are never overwritten.";
private String helidonVersion;
private int helidonMajorVersion;
private String rootJavaEEPackage;
private String rootJavaEEDepPrefix;
private String mpTestsGroup;
private String mpTestsArtifact;
private String jandexGroup;
private String jandexArtifact;
public static String defaultHelidonVersion() {
return VersionUtil.instance().defaultVersion();
}
public static String chooseVersion(String requestedVersionPrefix) {
return VersionUtil.instance().chooseVersion(requestedVersionPrefix);
}
public JavaHelidonCommonCodegen() {
super();
@ -97,7 +131,7 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
EXAMPLE_RETURN_VALUES.put("map", "Map");
cliOptions.add(new CliOption(HELIDON_VERSION, HELIDON_VERSION_DESC)
.defaultValue(DEFAULT_HELIDON_VERSION));
.defaultValue("Highest released version."));
cliOptions.add(new CliOption(MICROPROFILE_ROOT_PACKAGE, MICROPROFILE_ROOT_PACKAGE_DESC)
.defaultValue(MICROPROFILE_ROOT_PACKAGE_DEFAULT));
cliOptions.add(new CliOption(FULL_PROJECT, FULL_PROJECT_DESC)
@ -128,14 +162,18 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
HELIDON_VERSION));
}
setHelidonVersion(userHelidonVersion);
} else if (!userParentVersion.isEmpty()) {
setHelidonVersion(userParentVersion);
} else {
setHelidonVersion(DEFAULT_HELIDON_VERSION);
setHelidonVersion(VersionUtil.instance().defaultVersion());
}
additionalProperties.put(HELIDON_VERSION, helidonVersion);
setEEPackageAndDependencies(helidonVersion);
setMpTestDependency(helidonVersion);
setJandexPluginDependency(helidonVersion);
}
@Override
@ -199,8 +237,9 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
}
private void setHelidonVersion(String version) {
helidonVersion = version;
setParentVersion(version);
helidonVersion = VersionUtil.instance().chooseVersion(version);
setParentVersion(helidonVersion);
helidonMajorVersion = VersionUtil.majorVersion(helidonVersion);
}
private void setEEPackageAndDependencies(String version) {
@ -217,6 +256,19 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
: VALIDATION_ARTIFACT_PREFIX_JAKARTA);
}
private void setMpTestDependency(String version) {
// The Helidon MP test dependency changed from io.helidon.microprofile.tests:helidon-microprofile-tests-junit5 in 3.x
// to io.helidon.microprofile.testing:helidon-microprofile-testing-junit5 in 4.x.
additionalProperties.put(X_USE_MP_TESTING, helidonMajorVersion >= 4);
}
private void setJandexPluginDependency(String version) {
// The Jandex plug-in GAV changed from org.jboss.jandex:jandex-maven-plugin in 3.x to
// io.smallrye:jandex-maven-plugin in 4.x.
additionalProperties.put(X_USE_SMALLRYE_JANDEX_PLUGIN, helidonMajorVersion >= 4);
}
private String checkAndSelectRootEEPackage(String version) {
String packagePrefixImpliedByVersion = usesJakartaPackages(version)
? MICROPROFILE_ROOT_PACKAGE_JAKARTA
@ -321,4 +373,206 @@ public abstract class JavaHelidonCommonCodegen extends AbstractJavaCodegen
return "null";
}
}
/**
* 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.
*/
static class VersionUtil {
private static final String PREFERENCES_KEY = "/io/helidon/openapigenerators";
private static final String VERSIONS_KEY = "versions";
private static final String HELIDON_VERSIONS_URL = "https://helidon.io/cli-data/versions.xml";
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 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" +
" </archetypes>\n" +
"</data>";
private static VersionUtil INSTANCE = null;
private static ReentrantLock lock = new ReentrantLock();
static VersionUtil instance() {
lock.lock();
try {
if (INSTANCE == null) {
INSTANCE = new VersionUtil();
}
} catch (IOException | BackingStoreException ex) {
throw new RuntimeException(ex);
} finally {
lock.unlock();
}
return INSTANCE;
}
private final List<String> versions;
private VersionUtil() throws BackingStoreException, IOException {
versions = versions();
}
String defaultVersion() {
return DEFAULT_HELIDON_VERSION;
}
static int majorVersion(String fullVersion) {
return Integer.parseUnsignedInt(fullVersion.substring(0, fullVersion.indexOf('.')));
}
/**
* Returns the version that is the "closest" match to the requested version expression from among the known releases,
* where the expression is one of the following:
* <ul>
* <li>a single major version number (e.g., {@code 4})</li>
* <li>the full exact version to use</li>
* <li>a Maven version range</li>
* </ul>
*
* @param requestedVersion version to search for
* @return matching version
*/
String chooseVersion(String requestedVersion) {
return chooseVersion(requestedVersion, versions);
}
/**
* Returns the version that is the "closest" match to the requested version expression from among the provided
* releases, where the expression expression is one of the following:
* <ul>
* <li>a single major version number (e.g., {@code 4})</li>
* <li>the full exact version to use</li>
* <li>a Maven version range</li>
* </ul>
*
* @param requestedVersion version to search for
* @param candidateVersions releases to consider
* @return matching version
*/
String chooseVersion(String requestedVersion, List<String> candidateVersions) {
VersionScheme versionScheme = new GenericVersionScheme();
// If the requested version is a single number then treat it as "highest dot release of this major version".
// Otherwise, just create a constraint from the value. That also handles the case where the requested version is
// the complete version.
VersionConstraint requestedConstraint = constraint(versionScheme, requestedVersion);
Version bestMatch = null;
for (String candidate : candidateVersions) {
Version candidateVersion;
try {
candidateVersion = versionScheme.parseVersion(candidate);
} catch (InvalidVersionSpecificationException ex) {
LOGGER.log(System.Logger.Level.WARNING, "Error parsing candidate version '" + candidate + "'", ex);
continue;
}
if (requestedConstraint.containsVersion(candidateVersion)) {
if (bestMatch == null || bestMatch.compareTo(candidateVersion) <= 0) {
bestMatch = candidateVersion;
}
}
}
return bestMatch != null ? bestMatch.toString() : null;
}
private VersionConstraint constraint(VersionScheme versionScheme, String requestedVersion) {
try {
int asSingleNumber = Integer.parseUnsignedInt(requestedVersion);
try {
return versionScheme.parseVersionConstraint(String.format(Locale.getDefault(),
"[%s,%d-alpha)",
requestedVersion,
asSingleNumber + 1));
} catch (InvalidVersionSpecificationException ex) {
throw new RuntimeException("Error preparing constraint for version expression '"
+ requestedVersion
+ "' treated as major version " + asSingleNumber,
ex);
}
} catch (NumberFormatException nfe) {
try {
return versionScheme.parseVersionConstraint(requestedVersion);
} catch (InvalidVersionSpecificationException ex) {
throw new RuntimeException("Error parsing version expression '"
+ requestedVersion
+ "' as a version constraint",
ex);
}
}
}
/**
* Retrieves the list of supported versions from the web site or, failing that, local preferences or, failing that,
* hard-coded versions.
*
* @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 {
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(CONNECTION_TIMEOUT)
.build();
try {
HttpRequest req = HttpRequest.newBuilder(URI.create(HELIDON_VERSIONS_URL))
.GET()
.timeout(REQUEST_TIMEOUT)
.build();
HttpResponse<String> response = httpClient.send(req, HttpResponse.BodyHandlers.ofString());
Preferences versionPrefs = Preferences.userRoot().node(PREFERENCES_KEY);
String versions;
if (response.statusCode() == 200) {
versions = response.body();
// Save just-retrieved versions for later off-line use.
versionPrefs.put(VERSIONS_KEY, versions);
versionPrefs.flush();
LOGGER.log(System.Logger.Level.DEBUG, "Saved retrieved versions in preferences");
} else {
LOGGER.log(System.Logger.Level.INFO,
"Unable to retrieve versions remotely; using local preferences or hard-wired defaults");
// Try to get versions from preferences.
versions = versionPrefs.get(VERSIONS_KEY, DEFAULT_VERSIONS);
}
return extractVersions(versions);
} catch (IOException | InterruptedException e) {
// Fallback to use the local versions.xml contents.
return localDefaultVersions();
}
}
private static List<String> localDefaultVersions() throws IOException {
URL versionsURL = VersionUtil.class.getResource("versions.xml");
if (versionsURL == null) {
return extractVersions(DEFAULT_VERSIONS);
}
File versionsFile = new File(versionsURL.getFile());
return Files.readAllLines(versionsFile.toPath());
}
private static List<String> extractVersions(String xmlContent) {
Pattern versionPattern = Pattern.compile("<version[^>]*>([^>]+)</version>");
Matcher matcher = versionPattern.matcher(xmlContent);
List<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(matcher.group(1));
}
return result;
}
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2022 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022 Oracle and/or its affiliates
* Copyright 2022, 2024 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022, 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.
@ -104,8 +104,6 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
supportedLibraries.put(HELIDON_MP, "Helidon MP Server");
supportedLibraries.put(HELIDON_SE, "Helidon SE Server");
supportedLibraries.put(HELIDON_NIMA, "Helidon NIMA Server");
supportedLibraries.put(HELIDON_NIMA_ANNOTATIONS, "Helidon NIMA Annotations Server");
CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use");
libraryOption.setEnum(supportedLibraries);
@ -224,10 +222,6 @@ public class JavaHelidonServerCodegen extends JavaHelidonCommonCodegen {
}
importMapping.put("Handler", "io.helidon.webserver.Handler");
processSupportingFiles(modifiable, unmodifiable);
} else if (isLibrary(HELIDON_NIMA)) {
throw new UnsupportedOperationException("Not implemented");
} else if (isLibrary(HELIDON_NIMA_ANNOTATIONS)) {
throw new UnsupportedOperationException("Not implemented");
} else {
LOGGER.error("Unknown library option (-l/--library): {}", getLibrary());
throw new IllegalArgumentException(

View File

@ -85,8 +85,14 @@
</executions>
</plugin>
<plugin>
{{^x-helidon-useSmallRyeJandexPlugin}}
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
{{/x-helidon-useSmallRyeJandexPlugin}}
{{#x-helidon-useSmallRyeJandexPlugin}}
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
{{/x-helidon-useSmallRyeJandexPlugin}}
<executions>
<execution>
<id>make-index</id>

View File

@ -68,11 +68,20 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
{{^x-helidon-useMpTesting}}
<dependency>
<groupId>io.helidon.microprofile.tests</groupId>
<artifactId>helidon-microprofile-tests-junit5</artifactId>
<scope>test</scope>
</dependency>
{{/x-helidon-useMpTesting}}
{{#x-helidon-useMpTesting}}
<dependency>
<groupId>io.helidon.microprofile.testing</groupId>
<artifactId>helidon-microprofile-testing-junit5</artifactId>
<scope>test</scope>
</dependency>
{{/x-helidon-useMpTesting}}
</dependencies>
<build>
@ -87,8 +96,14 @@
</executions>
</plugin>
<plugin>
{{^x-helidon-useSmallRyeJandexPlugin}}
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
{{/x-helidon-useSmallRyeJandexPlugin}}
{{#x-helidon-useSmallRyeJandexPlugin}}
<groupId>io.smallrye</groupId>
<artifactId>jandex-maven-plugin</artifactId>
{{/x-helidon-useSmallRyeJandexPlugin}}
<executions>
<execution>
<id>make-index</id>

View File

@ -1,6 +1,6 @@
/*
* Copyright 2022 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright 2022, 2024 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022, 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.
@ -26,7 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.Assert;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils;
@ -44,12 +44,12 @@ public class JavaHelidonCommonCodegenPackagePrefixTest {
private static final String EXCEPTION_MESSAGE_FRAGMENT = "namespace but options specified";
// The generated SE client does not depend on the jakarta/javax imports, so no need to test it.
private static final List<List<String>> GENERATOR_LIBRARY_PAIRS = new ArrayList<List<String>>() {
{
add(listOf("java-helidon-client", "mp"));
add(listOf("java-helidon-server", "se"));
add(listOf("java-helidon-server", "mp"));
}
private static final List<List<String>> GENERATOR_LIBRARY_PAIRS = new ArrayList<>() {
{
add(listOf("java-helidon-client", "mp"));
add(listOf("java-helidon-server", "se"));
add(listOf("java-helidon-server", "mp"));
}
};
private String outputDir;
@ -76,10 +76,25 @@ public class JavaHelidonCommonCodegenPackagePrefixTest {
String explicitPrefix,
String generatorName,
String libraryName) {
IllegalArgumentException e = Assertions.assertThrows(IllegalArgumentException.class,
IllegalArgumentException e = Assert.assertThrows("Run invalid combo: " + assertMsg(explicitHelidonVersion,
explicitPrefix,
generatorName,
libraryName),
IllegalArgumentException.class,
() -> runTest(explicitHelidonVersion, explicitPrefix, generatorName, libraryName));
Assertions.assertTrue(e.getMessage().contains(EXCEPTION_MESSAGE_FRAGMENT),
"Exception message '" + e.getMessage() + "' contains '" + EXCEPTION_MESSAGE_FRAGMENT + "'");
Assert.assertTrue("Exception message for " + assertMsg(explicitHelidonVersion,
explicitPrefix,
generatorName,
libraryName)
+ "'" + e.getMessage() + "' containing '" + EXCEPTION_MESSAGE_FRAGMENT + "'",
e.getMessage().contains(EXCEPTION_MESSAGE_FRAGMENT));
}
private static String assertMsg(String explicitHelidonVersion, String explicitPrefix, String generatorName, String libraryName) {
return "Explicit version: " + (explicitHelidonVersion == null ? "null" : explicitHelidonVersion)
+ ", explicit prefix: " + (explicitPrefix == null ? "null" : explicitPrefix)
+ ", generatorName: " + generatorName
+ ", libraryName: " + libraryName;
}
@DataProvider(name = "valid")

View File

@ -1,6 +1,6 @@
/*
* Copyright 2022 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022 Oracle and/or its affiliates
* Copyright 2022, 2024 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright (c) 2022, 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.
@ -26,81 +26,118 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.Assert;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.TestUtils;
import org.openapitools.codegen.config.CodegenConfigurator;
import org.openapitools.codegen.languages.JavaHelidonCommonCodegen;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class JavaHelidonCommonCodegenTest {
private DefaultGenerator generator;
private CodegenConfigurator configurator;
private String outputDir;
private DefaultGenerator mpServerGenerator;
private DefaultGenerator mpClientGenerator;
private CodegenConfigurator mpServerConfigurator;
private CodegenConfigurator mpClientConfigurator;
private String mpServerOutputDir;
private String mpClientOutputDir;
@BeforeMethod
public void setup() throws IOException {
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();
outputDir = output.getAbsolutePath().replace('\\', '/');
File mpServerOutput = Files.createTempDirectory("testMpServer").toFile();
mpServerOutput.deleteOnExit();
mpServerOutputDir = mpServerOutput.getAbsolutePath().replace('\\', '/');
configurator = new CodegenConfigurator()
File mpClientOutput = Files.createTempDirectory("testMpClient").toFile();
mpClientOutputDir = mpClientOutput.getAbsolutePath().replace('\\', '/');
mpServerConfigurator = new CodegenConfigurator()
.setGeneratorName("java-helidon-server")
.setLibrary("mp")
.setInputSpec("src/test/resources/3_0/helidon/petstore-for-testing.yaml")
.setOutputDir(outputDir);
.setOutputDir(mpServerOutputDir);
generator = new DefaultGenerator();
mpClientConfigurator = new CodegenConfigurator()
.setGeneratorName("java-helidon-client")
.setLibrary("mp")
.setInputSpec("src/test/resources/3_0/helidon/petstore-for-testing.yaml")
.setOutputDir(mpClientOutputDir);
mpServerGenerator = new DefaultGenerator();
mpClientGenerator = new DefaultGenerator();
}
@Test
public void defaultVersionTest() {
runVersionTest(null, null);
runServerVersionTest(null, null);
}
@Test
public void customHelidonVersionOnlyTest() {
runVersionTest("3.0.0", null);
runServerVersionTest("3.0.0", null);
}
@Test
void customHelidonMajorVersionOnlyTest() {
runServerVersionTest("3", null);
}
@Test
public void customParentVersionOnlyTest() {
runVersionTest(null, "3.0.0");
runServerVersionTest(null, "3.0.0");
}
@Test
public void bothEqualsVersionTest() {
runVersionTest("3.0.0", "3.0.0");
runServerVersionTest("3.0.0", "3.0.0");
}
@Test
public void bothNotEqualsVersionTest() {
IllegalArgumentException e = Assertions.assertThrows(IllegalArgumentException.class,() -> runVersionTest("1.0.0", "2.0.0"));
Assertions.assertEquals(
IllegalArgumentException e = Assert.assertThrows(IllegalArgumentException.class,() -> runServerVersionTest("1.0.0", "2.0.0"));
Assert.assertEquals(
"Both parentVersion and helidonVersion properties were set with different value.",
e.getMessage());
}
private void runVersionTest(String helidonVersion, String parentVersion) {
@Test
void customHelidonVersionOnlyClientTest() {
runClientVersionTest("4", null);
}
private void runServerVersionTest(String helidonVersion, String parentVersion) {
runVersionTest(helidonVersion, parentVersion, mpServerGenerator, mpServerConfigurator, mpServerOutputDir);
}
private void runClientVersionTest(String helidonVersion, String parentVersion) {
runVersionTest(helidonVersion, parentVersion, mpClientGenerator, mpClientConfigurator, mpClientOutputDir);
}
private void runVersionTest(String helidonVersion,
String parentVersion,
DefaultGenerator generator,
CodegenConfigurator configurator,
String outputDir) {
Map<String, Object> additionalProperties = new HashMap<>();
String expected = "3.0.1";
String expected = JavaHelidonCommonCodegen.defaultHelidonVersion();
if (parentVersion != null) {
additionalProperties.put(CodegenConstants.PARENT_VERSION, parentVersion);
expected = parentVersion;
expected = JavaHelidonCommonCodegen.chooseVersion(parentVersion);
}
if (helidonVersion != null) {
additionalProperties.put("helidonVersion", helidonVersion);
expected = helidonVersion;
expected = JavaHelidonCommonCodegen.chooseVersion(helidonVersion);
}
generator.opts(configurator.setAdditionalProperties(additionalProperties)
.toClientOptInput());
.toClientOptInput());
List<File> files = generator.generate();
TestUtils.ensureContainsFile(files, Paths.get(outputDir).toFile(), "pom.xml");
TestUtils.assertFileContains(Paths.get(outputDir + "/pom.xml"),
String.format(Locale.ROOT, "<version>%s</version>", expected));
String.format(Locale.ROOT, "<version>%s</version>", expected));
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright 2024 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* 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.List;
import org.junit.Assert;
import org.testng.annotations.Test;
// This test class is in this package, not org.openapitools.codegen.java.helidon, so it can refer to elements of
// JavaHelidonCommonCodegen without making them public; package-private is sufficient and we don't want to expose those methods
// more broadly.
class HelidonCommonCodegenTest {
@Test
void checkMajorVersionMatch() {
Assert.assertEquals("1.2.3",
JavaHelidonCommonCodegen.VersionUtil.instance().chooseVersion("1",
List.of("3.2.1",
"3.2.0",
"2.0.4",
"1.2.3",
"1.2.2",
"1.1.0")));
}
@Test
void checkExactMatch() {
Assert.assertEquals("1.2.2",
JavaHelidonCommonCodegen.VersionUtil.instance().chooseVersion("1.2.2",
List.of("3.2.1",
"3.2.0",
"2.0.4",
"1.2.3",
"1.2.2",
"1.1.0")));
}
}

View File

@ -279,7 +279,7 @@ paths:
- petstore_auth:
- 'write:pets'
- 'read:pets'
'/pet/{petId}/uploadImage':
'/pet/{petId}/{petDate}/uploadImage':
post:
tags:
- pet

View File

@ -1250,6 +1250,7 @@
<openrewrite.version>8.8.3</openrewrite.version>
<pmd-plugin.version>3.12.0</pmd-plugin.version>
<reflections.version>0.10.2</reflections.version>
<resolver-util-version>1.9.18</resolver-util-version>
<rxgen.version>1.4</rxgen.version>
<scala-maven-plugin.version>4.6.1</scala-maven-plugin.version>
<slf4j.version>1.7.36</slf4j.version>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.helidon.applications</groupId>
<artifactId>helidon-mp</artifactId>
<version>3.0.1</version>
<version>3.2.7</version>
<relativePath/>
</parent>
<artifactId>petstore-helidon-client-mp</artifactId>

Some files were not shown because too many files have changed in this diff Show More