Is your feature request related to a problem? Please describe.
The jaxrs-spec generator has no JSpecify support. useJspecify is available on the java client generator and on spring, but not here, so a JAX-RS server contract cannot express its optional properties as @Nullable even though the same information is already in the OpenAPI document.
Unlike the microprofile client library in #24883 — which advertised the option and then threw — jaxrs-spec never exposes it at all:
$ openapi-generator-cli config-help -g jaxrs-spec | grep -c useJspecify
0
Passing it anyway is silently ignored rather than rejected, which is arguably worse: generation succeeds, exits 0, and produces no annotations and no package-info.java, so it is easy to believe the option took effect.
$ openapi-generator-cli generate -g jaxrs-spec --library quarkus \
-i jspecify.yaml -o /tmp/out -p useJspecify=true,useJakartaEe=true
# no error; no @Nullable anywhere, no @NullMarked package-info
The generator emits no nullability annotations of any kind today, for any library, even though the base pom.mustache already ships com.google.code.findbugs:jsr305 under a <!-- @Nullable annotation --> comment.
Describe the solution you'd like
Support useJspecify for jaxrs-spec, consistent with the java and spring generators:
@NullMarked package-info.java for the api and model packages
@Nullable on optional properties and operation parameters, with type-use placement on qualified types (java.math.@Nullable BigDecimal)
- the
org.jspecify:jspecify dependency in the generated pom, replacing jsr305 when the flag is on (as native, resttemplate and the other java client libraries already do)
This is worth doing at the generator level rather than per library: pojo.mustache and the parameter partials are shared by all six libraries (default, quarkus, thorntail, openliberty, helidon, kumuluzee), and only quarkus overrides formParams. One set of template changes covers all of them.
The quarkus library in particular benefits, since generated servers are commonly consumed from Quarkus and Kotlin, both of which act on JSpecify metadata, and NullAway can then enforce the contract's optionality at compile time.
Describe alternatives you've considered
Leaving it unsupported. That keeps the generator as-is but means the required information in the contract is discarded at the Java boundary, and every caller has to re-derive it from the spec.
Scoping it to library=quarkus only was also considered, but the shared pojo.mustache has to be edited either way — only the gating would differ — so restricting it would add a rejection path without reducing the change.
Additional context
Two things that are specific to this generator and not obvious from how the java client does it:
-
applyJspecify() has to run after the supportingFiles.clear() in JavaJAXRSSpecServerCodegen#processOpts, which otherwise drops the @NullMarked package-info files it registers.
-
The nullable* and packageInfo templates have to be added under JavaJaxRS/spec. The java client libraries all resolve against one shared Java template directory, but jaxrs-spec sets its own embeddedTemplateDir with no fallback, so they cannot simply be inherited.
Also worth noting for whoever picks this up: jaxrs-cxf-cdi extends JavaJAXRSSpecServerCodegen but sets its own cxf-cdi template directory, so it inherits any new cliOption while producing none of the output — it needs removeOption(USE_JSPECIFY), alongside the existing removeOption(GENERATE_JSON_CREATOR).
I have an implementation in #24885.
OpenAPI declaration file content or url
Any spec with optional properties; reproduced with modules/openapi-generator/src/test/resources/3_0/java/jspecify.yaml.
Generation Details
java -jar openapi-generator-cli.jar generate \
-g jaxrs-spec --library quarkus \
-i modules/openapi-generator/src/test/resources/3_0/java/jspecify.yaml \
-o /tmp/out -p useJspecify=true,useJakartaEe=true,interfaceOnly=true
openapi-generator version
master (7.26.0-SNAPSHOT). Not a regression — jaxrs-spec has never had the option since useJspecify was introduced in #23256.
Is your feature request related to a problem? Please describe.
The
jaxrs-specgenerator has no JSpecify support.useJspecifyis available on thejavaclient generator and onspring, but not here, so a JAX-RS server contract cannot express its optional properties as@Nullableeven though the same information is already in the OpenAPI document.Unlike the
microprofileclient library in #24883 — which advertised the option and then threw —jaxrs-specnever exposes it at all:Passing it anyway is silently ignored rather than rejected, which is arguably worse: generation succeeds, exits 0, and produces no annotations and no
package-info.java, so it is easy to believe the option took effect.The generator emits no nullability annotations of any kind today, for any library, even though the base
pom.mustachealready shipscom.google.code.findbugs:jsr305under a<!-- @Nullable annotation -->comment.Describe the solution you'd like
Support
useJspecifyforjaxrs-spec, consistent with thejavaandspringgenerators:@NullMarkedpackage-info.javafor the api and model packages@Nullableon optional properties and operation parameters, with type-use placement on qualified types (java.math.@Nullable BigDecimal)org.jspecify:jspecifydependency in the generated pom, replacingjsr305when the flag is on (asnative,resttemplateand the other java client libraries already do)This is worth doing at the generator level rather than per library:
pojo.mustacheand the parameter partials are shared by all six libraries (default,quarkus,thorntail,openliberty,helidon,kumuluzee), and onlyquarkusoverridesformParams. One set of template changes covers all of them.The
quarkuslibrary in particular benefits, since generated servers are commonly consumed from Quarkus and Kotlin, both of which act on JSpecify metadata, and NullAway can then enforce the contract's optionality at compile time.Describe alternatives you've considered
Leaving it unsupported. That keeps the generator as-is but means the
requiredinformation in the contract is discarded at the Java boundary, and every caller has to re-derive it from the spec.Scoping it to
library=quarkusonly was also considered, but the sharedpojo.mustachehas to be edited either way — only the gating would differ — so restricting it would add a rejection path without reducing the change.Additional context
Two things that are specific to this generator and not obvious from how the java client does it:
applyJspecify()has to run after thesupportingFiles.clear()inJavaJAXRSSpecServerCodegen#processOpts, which otherwise drops the@NullMarkedpackage-info files it registers.The
nullable*andpackageInfotemplates have to be added underJavaJaxRS/spec. The java client libraries all resolve against one sharedJavatemplate directory, butjaxrs-specsets its ownembeddedTemplateDirwith no fallback, so they cannot simply be inherited.Also worth noting for whoever picks this up:
jaxrs-cxf-cdiextendsJavaJAXRSSpecServerCodegenbut sets its owncxf-cditemplate directory, so it inherits any new cliOption while producing none of the output — it needsremoveOption(USE_JSPECIFY), alongside the existingremoveOption(GENERATE_JSON_CREATOR).I have an implementation in #24885.
OpenAPI declaration file content or url
Any spec with optional properties; reproduced with
modules/openapi-generator/src/test/resources/3_0/java/jspecify.yaml.Generation Details
openapi-generator version
master (7.26.0-SNAPSHOT). Not a regression —
jaxrs-spechas never had the option sinceuseJspecifywas introduced in #23256.