Skip to content

Commit bc6433f

Browse files
committed
[jaxrs-spec][quarkus] Migrate the Jakarta path to Quarkus REST
The quarkus library generated for RESTEasy Classic (quarkus-resteasy), while current Quarkus defaults to Quarkus REST. One consequence is that file form parameters were bound to InputStream, which Quarkus REST does not support as a multipart type. Under useJakartaEe=true the generated project now depends on quarkus-rest and binds file form parameters to the RESTEasy Reactive multipart type (`@RestForm FileUpload`). The platform moves to 3.27.4.1 (oldest supported LTS) and the BOM to quarkus-bom, since quarkus-universe-bom was discontinued after 3.0.1 and quarkus-rest does not exist before 3.9. quarkus-hibernate-validator is now declared explicitly because, unlike quarkus-resteasy, quarkus-rest does not pull bean validation in transitively. The compiler release moves to 17 on that path, as Quarkus 3.x requires it, so the quarkus-security sample moves from the JDK 11 samples-jaxrs workflow to samples-jdk17. The useJakartaEe=false path is pinned to Quarkus 1.13.7, which predates Quarkus REST, so it keeps RESTEasy Classic, Java 8 and its InputStream binding unchanged. Refs OpenAPITools#24454
1 parent 9cfe350 commit bc6433f

8 files changed

Lines changed: 113 additions & 9 deletions

File tree

.github/workflows/samples-jaxrs.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ jobs:
3838
- samples/server/petstore/jaxrs-spec-swagger-annotations
3939
- samples/server/petstore/jaxrs-spec-swagger-v3-annotations-jakarta
4040
- samples/server/petstore/jaxrs-spec-swagger-v3-annotations
41-
- samples/server/petstore/jaxrs-spec/quarkus-security
4241
steps:
4342
- uses: actions/checkout@v7
4443
- uses: actions/setup-java@v5

.github/workflows/samples-jdk17.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ on:
2323
- samples/server/petstore/java-helidon-server/v3/mp/**
2424
- samples/server/petstore/java-helidon-server/v3/se/**
2525
- samples/server/petstore/jaxrs-spec-sealed/**
26+
- samples/server/petstore/jaxrs-spec/quarkus-security/**
2627
pull_request:
2728
paths:
2829
# clients
@@ -46,6 +47,7 @@ on:
4647
- samples/server/petstore/java-helidon-server/v3/mp/**
4748
- samples/server/petstore/java-helidon-server/v3/se/**
4849
- samples/server/petstore/jaxrs-spec-sealed/**
50+
- samples/server/petstore/jaxrs-spec/quarkus-security/**
4951
jobs:
5052
build:
5153
name: Build with JDK17
@@ -75,6 +77,7 @@ jobs:
7577
- samples/server/petstore/java-helidon-server/v3/mp/
7678
- samples/server/petstore/java-helidon-server/v3/se
7779
- samples/server/petstore/jaxrs-spec-sealed
80+
- samples/server/petstore/jaxrs-spec/quarkus-security
7881
steps:
7982
- uses: actions/checkout@v7
8083
- uses: actions/setup-java@v5

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,13 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
393393
additionalProperties.put("hasResponseStatusAnnotations", true);
394394
}
395395
}
396+
397+
// The quarkus templates bind file form parameters to org.jboss.resteasy.reactive types, so the
398+
// corresponding imports must only be emitted for API files that actually declare such a parameter.
399+
// Always set explicitly so Mustache does not fall through to the global additionalProperties value.
400+
objs.put("hasFileFormParams", objs.getOperations().getOperation().stream()
401+
.flatMap(op -> op.formParams.stream())
402+
.anyMatch(p -> p.isFile));
396403
return objs;
397404
}
398405

modules/openapi-generator/src/main/resources/JavaJaxRS/spec/libraries/quarkus/api.mustache

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ import java.util.concurrent.CompletableFuture;
3737
{{/useMutiny}}
3838
{{/supportAsync}}
3939

40+
{{#useJakartaEe}}
41+
{{#hasFileFormParams}}
42+
import org.jboss.resteasy.reactive.RestForm;
43+
import org.jboss.resteasy.reactive.multipart.FileUpload;
44+
45+
{{/hasFileFormParams}}
46+
{{/useJakartaEe}}
4047
import java.io.InputStream;
4148
import java.util.Map;
4249
import java.util.List;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{{#isFormParam}}
2+
{{#isDeprecated}}@Deprecated {{/isDeprecated}}{{^isFile}}@FormParam(value = "{{baseName}}") {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{#useJakartaEe}}{{^isArray}}@RestForm(value = "{{baseName}}") FileUpload {{paramName}}{{/isArray}}{{#isArray}}@RestForm(value = "{{baseName}}") List<FileUpload> {{paramName}}{{/isArray}}{{/useJakartaEe}}{{^useJakartaEe}}@FormParam(value = "{{baseName}}") InputStream {{paramName}}InputStream{{/useJakartaEe}}{{/isFile}}{{/isFormParam}}

modules/openapi-generator/src/main/resources/JavaJaxRS/spec/libraries/quarkus/pom.mustache

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,30 @@
1818
<properties>
1919
<compiler-plugin.version>3.8.1</compiler-plugin.version>
2020
<maven.compiler.parameters>true</maven.compiler.parameters>
21+
{{#useJakartaEe}}
22+
<maven.compiler.source>17</maven.compiler.source>
23+
<maven.compiler.target>17</maven.compiler.target>
24+
{{/useJakartaEe}}
25+
{{^useJakartaEe}}
2126
<maven.compiler.source>1.8</maven.compiler.source>
2227
<maven.compiler.target>1.8</maven.compiler.target>
28+
{{/useJakartaEe}}
2329
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2430
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
2531
{{#useJakartaEe}}
26-
<quarkus-plugin.version>3.0.1.Final</quarkus-plugin.version>
27-
<quarkus.platform.version>3.0.1.Final</quarkus.platform.version>
32+
<quarkus-plugin.version>3.27.4.1</quarkus-plugin.version>
33+
<quarkus.platform.version>3.27.4.1</quarkus.platform.version>
2834
{{/useJakartaEe}}
2935
{{^useJakartaEe}}
3036
<quarkus-plugin.version>1.13.7.Final</quarkus-plugin.version>
3137
<quarkus.platform.version>1.13.7.Final</quarkus.platform.version>
3238
{{/useJakartaEe}}
39+
{{#useJakartaEe}}
40+
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
41+
{{/useJakartaEe}}
42+
{{^useJakartaEe}}
3343
<quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
44+
{{/useJakartaEe}}
3445
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
3546
<surefire-plugin.version>2.22.1</surefire-plugin.version>
3647
{{#useJakartaEe}}
@@ -66,10 +77,25 @@
6677
</dependencies>
6778
</dependencyManagement>
6879
<dependencies>
80+
{{#useJakartaEe}}
81+
<dependency>
82+
<groupId>io.quarkus</groupId>
83+
<artifactId>quarkus-rest</artifactId>
84+
</dependency>
85+
{{#useBeanValidation}}
86+
<!-- quarkus-rest does not pull in bean validation transitively, unlike quarkus-resteasy -->
87+
<dependency>
88+
<groupId>io.quarkus</groupId>
89+
<artifactId>quarkus-hibernate-validator</artifactId>
90+
</dependency>
91+
{{/useBeanValidation}}
92+
{{/useJakartaEe}}
93+
{{^useJakartaEe}}
6994
<dependency>
7095
<groupId>io.quarkus</groupId>
7196
<artifactId>quarkus-resteasy</artifactId>
7297
</dependency>
98+
{{/useJakartaEe}}
7399
<dependency>
74100
<groupId>io.quarkus</groupId>
75101
<artifactId>quarkus-junit5</artifactId>

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,4 +2424,59 @@ public void generatesEmailAnnotationOnQueryParameterWhenBeanValidationEnabled()
24242424
assertFileContains(api, "import javax.validation.constraints.*;");
24252425
assertFileContains(api, "@QueryParam(\"email\")", "@Email", "String email");
24262426
}
2427+
2428+
/**
2429+
* On Quarkus REST a file form parameter is bound to the RESTEasy Reactive multipart type.
2430+
* {@code InputStream} is not a supported multipart type there.
2431+
*/
2432+
@Test
2433+
public void testQuarkusJakartaBindsFileFormParamToFileUpload() throws IOException {
2434+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
2435+
output.deleteOnExit();
2436+
String outputPath = output.getAbsolutePath().replace('\\', '/');
2437+
2438+
final CodegenConfigurator configurator = new CodegenConfigurator()
2439+
.setGeneratorName("jaxrs-spec")
2440+
.setLibrary(QUARKUS_LIBRARY)
2441+
.setAdditionalProperties(Map.of(USE_JAKARTA_EE, "true"))
2442+
.setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml")
2443+
.setOutputDir(outputPath);
2444+
2445+
DefaultGenerator generator = new DefaultGenerator(false);
2446+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
2447+
validateJavaSourceFiles(files);
2448+
2449+
Path api = Paths.get(outputPath + "/src/gen/java/org/openapitools/api/MultipartSingleApi.java");
2450+
assertFileContains(api, "import org.jboss.resteasy.reactive.RestForm;");
2451+
assertFileContains(api, "import org.jboss.resteasy.reactive.multipart.FileUpload;");
2452+
assertFileContains(api, "@RestForm(value = \"file\") FileUpload _file");
2453+
// the project targets Quarkus REST rather than RESTEasy Classic
2454+
assertFileContains(Paths.get(outputPath + "/pom.xml"), "<artifactId>quarkus-rest</artifactId>");
2455+
}
2456+
2457+
/**
2458+
* The javax path is pinned to Quarkus 1.13.7, which predates Quarkus REST, so it keeps
2459+
* RESTEasy Classic and its {@code InputStream} binding.
2460+
*/
2461+
@Test
2462+
public void testQuarkusJavaxKeepsResteasyClassicFileBinding() throws IOException {
2463+
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
2464+
output.deleteOnExit();
2465+
String outputPath = output.getAbsolutePath().replace('\\', '/');
2466+
2467+
final CodegenConfigurator configurator = new CodegenConfigurator()
2468+
.setGeneratorName("jaxrs-spec")
2469+
.setLibrary(QUARKUS_LIBRARY)
2470+
.setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml")
2471+
.setOutputDir(outputPath);
2472+
2473+
DefaultGenerator generator = new DefaultGenerator(false);
2474+
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
2475+
validateJavaSourceFiles(files);
2476+
2477+
Path api = Paths.get(outputPath + "/src/gen/java/org/openapitools/api/MultipartSingleApi.java");
2478+
assertFileContains(api, "@FormParam(value = \"file\") InputStream _fileInputStream");
2479+
assertFileNotContains(api, "import org.jboss.resteasy.reactive.multipart.FileUpload;");
2480+
assertFileContains(Paths.get(outputPath + "/pom.xml"), "<artifactId>quarkus-resteasy</artifactId>");
2481+
}
24272482
}

samples/server/petstore/jaxrs-spec/quarkus-security/pom.xml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
<properties>
1212
<compiler-plugin.version>3.8.1</compiler-plugin.version>
1313
<maven.compiler.parameters>true</maven.compiler.parameters>
14-
<maven.compiler.source>1.8</maven.compiler.source>
15-
<maven.compiler.target>1.8</maven.compiler.target>
14+
<maven.compiler.source>17</maven.compiler.source>
15+
<maven.compiler.target>17</maven.compiler.target>
1616
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1717
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
18-
<quarkus-plugin.version>3.0.1.Final</quarkus-plugin.version>
19-
<quarkus.platform.version>3.0.1.Final</quarkus.platform.version>
20-
<quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
18+
<quarkus-plugin.version>3.27.4.1</quarkus-plugin.version>
19+
<quarkus.platform.version>3.27.4.1</quarkus.platform.version>
20+
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
2121
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
2222
<surefire-plugin.version>2.22.1</surefire-plugin.version>
2323
<jakarta.ws.rs-version>3.1.0</jakarta.ws.rs-version>
@@ -38,7 +38,12 @@
3838
<dependencies>
3939
<dependency>
4040
<groupId>io.quarkus</groupId>
41-
<artifactId>quarkus-resteasy</artifactId>
41+
<artifactId>quarkus-rest</artifactId>
42+
</dependency>
43+
<!-- quarkus-rest does not pull in bean validation transitively, unlike quarkus-resteasy -->
44+
<dependency>
45+
<groupId>io.quarkus</groupId>
46+
<artifactId>quarkus-hibernate-validator</artifactId>
4247
</dependency>
4348
<dependency>
4449
<groupId>io.quarkus</groupId>

0 commit comments

Comments
 (0)