Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JAVA] [Jersey3] Make Jakarta Annotation API optional #20576

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bin/configs/java-jersey3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ additionalProperties:
gradleProperties: "\n# JVM arguments\norg.gradle.jvmargs=-Xmx2024m -XX:MaxPermSize=512m\n# set timeout\norg.gradle.daemon.idletimeout=3600000\n# show all warnings\norg.gradle.warning.mode=all"
failOnUnknownProperties: true
useReflectionEqualsHashCode: true
useJakartaAnnotation: true
1 change: 1 addition & 0 deletions docs/generators/java-microprofile.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useBeanValidation|Use BeanValidation API annotations| |false|
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useGzipFeature|Send gzip-encoded requests| |false|
|useJakartaAnnotation|Use Jakarta Annotation API| |false|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if useJakartaEe is set to false (by default), shall it skip the Jakarta annotation by default?

(in other words, do we need another option or we can "reuse" useJakartaEe in this use case to skip the annotation?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point however, this might be confusing. useJakartaEe is a flag to decide whether to use Jakarta EE namespace instead of javax, while the goal of this PR is to allow skipping the jakarta-annotation-api without using instead the corresponding javax option.

|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson support this option.| |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|
Expand Down
1 change: 1 addition & 0 deletions docs/generators/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useBeanValidation|Use BeanValidation API annotations| |false|
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
|useGzipFeature|Send gzip-encoded requests| |false|
|useJakartaAnnotation|Use Jakarta Annotation API| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped. Only jersey2, jersey3, native, okhttp-gson support this option.| |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|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.openapitools.codegen.*;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
import org.openapitools.codegen.languages.features.GzipFeatures;
import org.openapitools.codegen.languages.features.JakartaAnnotationFeatures;
import org.openapitools.codegen.languages.features.PerformBeanValidationFeatures;
import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature;
Expand All @@ -52,7 +53,7 @@
import static org.openapitools.codegen.utils.StringUtils.camelize;

public class JavaClientCodegen extends AbstractJavaCodegen
implements BeanValidationFeatures, PerformBeanValidationFeatures, GzipFeatures {
implements BeanValidationFeatures, PerformBeanValidationFeatures, GzipFeatures, JakartaAnnotationFeatures {

static final String MEDIA_TYPE = "mediaType";

Expand Down Expand Up @@ -149,6 +150,12 @@ public class JavaClientCodegen extends AbstractJavaCodegen
@Setter protected boolean generateClientAsBean = false;
@Setter protected boolean useEnumCaseInsensitive = false;

/**
* useJakartaAnnotation to include Jakarta Annotation API
*/
@Getter @Setter
protected boolean useJakartaAnnotation = true;

@Setter protected int maxAttemptsForRetry = 1;
@Setter protected long waitTimeMillis = 10l;

Expand Down Expand Up @@ -219,6 +226,7 @@ public JavaClientCodegen() {
cliOptions.add(CliOption.newBoolean(PARCELABLE_MODEL, "Whether to generate models for Android that implement Parcelable with the okhttp-gson library."));
cliOptions.add(CliOption.newBoolean(USE_PLAY_WS, "Use Play! Async HTTP client (Play WS API)"));
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations"));
cliOptions.add(CliOption.newBoolean(USE_JAKARTAANNOTATION, "Use Jakarta Annotation API"));
cliOptions.add(CliOption.newBoolean(PERFORM_BEANVALIDATION, "Perform BeanValidation"));
cliOptions.add(CliOption.newBoolean(USE_GZIP_FEATURE, "Send gzip-encoded requests"));
cliOptions.add(CliOption.newBoolean(USE_RUNTIME_EXCEPTION, "Use RuntimeException instead of Exception. Only jersey2, jersey3, okhttp-gson, vertx, microprofile support this option."));
Expand Down Expand Up @@ -410,6 +418,9 @@ public void processOpts() {
convertPropertyToTypeAndWriteBack(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY, Integer::parseInt, this::setMaxAttemptsForRetry);
convertPropertyToTypeAndWriteBack(CodegenConstants.WAIT_TIME_OF_THREAD, Long::parseLong, this::setWaitTimeMillis);

if (JERSEY3.equals(getLibrary())) {
convertPropertyToBooleanAndWriteBack(JakartaAnnotationFeatures.USE_JAKARTAANNOTATION, this::setUseJakartaAnnotation);
}
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
final String apiFolder = (sourceFolder + '/' + apiPackage).replace(".", "/");
final String modelsFolder = (sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar)).replace('/', File.separatorChar);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
* Copyright 2018 SmartBear Software
*
* 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
*
* https://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.features;

public interface JakartaAnnotationFeatures {

// Language supports generating Jakarta-Annotation API
String USE_JAKARTAANNOTATION = "useJakartaAnnotation";

void setUseJakartaAnnotation(boolean useJakartaAnnotation);

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

{{>generatedAnnotation}}
{{#useJakartaAnnotation}}
{{>generatedAnnotation}}{{/useJakartaAnnotation}}
{{#operations}}
public class {{classname}} {
private ApiClient apiClient;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@JsonTypeName("{{name}}")
{{/isClassnameSanitized}}
{{/jackson}}
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
{{>additionalModelTypeAnnotations}}{{#useJakartaAnnotation}}{{>generatedAnnotation}}{{/useJakartaAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}
{{#vendorExtensions.x-class-extra-annotation}}
{{{vendorExtensions.x-class-extra-annotation}}}
{{/vendorExtensions.x-class-extra-annotation}}
Expand Down Expand Up @@ -81,7 +81,7 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{#deprecated}}
@Deprecated
{{/deprecated}}
{{>nullable_var_annotations}}
{{#useJakartaAnnotation}}{{>nullable_var_annotations}}{{/useJakartaAnnotation}}
private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/vendorExtensions.x-is-jackson-optional-nullable}}

Expand Down Expand Up @@ -114,7 +114,7 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{#deprecated}}
@Deprecated
{{/deprecated}}
public {{classname}} {{name}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
public {{classname}} {{name}}({{#useJakartaAnnotation}}{{>nullable_var_annotations}}{{/useJakartaAnnotation}} {{{datatypeWithEnum}}} {{name}}) {
{{#vendorExtensions.x-enum-as-string}}
if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) {
throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES));
Expand Down Expand Up @@ -198,7 +198,8 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
{{#deprecated}}
@Deprecated
{{/deprecated}}
{{>nullable_var_annotations}}
{{#useJakartaAnnotation}}
{{>nullable_var_annotations}}{{/useJakartaAnnotation}}
{{#useBeanValidation}}
{{>beanValidation}}
{{/useBeanValidation}}
Expand Down Expand Up @@ -248,7 +249,7 @@ public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtens
@Deprecated
{{/deprecated}}
{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{>nullable_var_annotations}} {{{datatypeWithEnum}}} {{name}}) {
{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{#useJakartaAnnotation}}{{>nullable_var_annotations}}{{/useJakartaAnnotation}} {{{datatypeWithEnum}}} {{name}}) {
{{#vendorExtensions.x-enum-as-string}}
if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) {
throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,15 @@
<scope>provided</scope>
</dependency>
{{/useBeanValidation}}
{{#useJakartaAnnotation}}
<!-- Jakarta Annotation API support -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${jakarta-annotation-version}</version>
<scope>provided</scope>
</dependency>
{{/useJakartaAnnotation}}
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
Expand Down Expand Up @@ -408,7 +411,8 @@
<jackson-version>2.17.1</jackson-version>
<jackson-databind-version>2.17.1</jackson-databind-version>
<jackson-databind-nullable-version>0.2.6</jackson-databind-nullable-version>
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
{{#useJakartaAnnotation}}
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>{{/useJakartaAnnotation}}
<beanvalidation-version>3.0.2</beanvalidation-version>
<junit-version>5.10.0</junit-version>
{{#hasHttpSignatureMethods}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3365,4 +3365,62 @@ public void callNativeServiceWithEmptyResponseAsync() throws IOException {
"responseBody.isBlank()? null: memberVarObjectMapper.readValue(responseBody, new TypeReference<LocationData>() {})"
);
}

@Test
public void testJerseyContainsJakartaAnnotation() {
final Path output = newTempFolder();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("java")
.setLibrary(JERSEY3)
.addAdditionalProperty(JavaClientCodegen.USE_JAKARTAANNOTATION, true)
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setOutputDir(output.toString().replace("\\", "/"));

List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

validateJavaSourceFiles(files);
// check POM includes jakarta-annotation
assertThat(files).contains(output.resolve("pom.xml").toFile());
assertThat(output.resolve("pom.xml")).content()
.contains("<jakarta-annotation-version>");
assertThat(output.resolve("pom.xml")).content()
.contains("jakarta.annotation-api");
// check API
assertThat(output.resolve("src/main/java/org/openapitools/client/api/PetApi.java")).content()
.contains("@jakarta.annotation.Generated");
// check model
assertThat(output.resolve("src/main/java/org/openapitools/client/model/Category.java")).content()
.contains("@jakarta.annotation.Generated");
assertThat(output.resolve("src/main/java/org/openapitools/client/model/Category.java")).content()
.contains("@jakarta.annotation.Nullable");
}

@Test
public void testJerseyWithoutJakartaAnnotation() {
final Path output = newTempFolder();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("java")
.setLibrary(JERSEY3)
.addAdditionalProperty(JavaClientCodegen.USE_JAKARTAANNOTATION, false)
.setInputSpec("src/test/resources/3_0/petstore.yaml")
.setOutputDir(output.toString().replace("\\", "/"));

List<File> files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

validateJavaSourceFiles(files);
// check POM includes jakarta-annotation
assertThat(files).contains(output.resolve("pom.xml").toFile());
assertThat(output.resolve("pom.xml")).content()
.doesNotContain("<jakarta-annotation-version>");
assertThat(output.resolve("pom.xml")).content()
.doesNotContain("jakarta.annotation-api");
// check API
assertThat(output.resolve("src/main/java/org/openapitools/client/api/PetApi.java")).content()
.doesNotContain("@jakarta.annotation.Generated");
// check model
assertThat(output.resolve("src/main/java/org/openapitools/client/model/Category.java")).content()
.doesNotContain("@jakarta.annotation.Generated");
assertThat(output.resolve("src/main/java/org/openapitools/client/model/Category.java")).content()
.doesNotContain("@jakarta.annotation.Nullable");
}
}
1 change: 1 addition & 0 deletions samples/client/petstore/java/jersey3-oneOf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-version}</version>
</dependency>
<!-- Jakarta Annotation API support -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
Expand Down
1 change: 1 addition & 0 deletions samples/client/petstore/java/jersey3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
<version>${beanvalidation-version}</version>
<scope>provided</scope>
</dependency>
<!-- Jakarta Annotation API support -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
Expand Down
Loading