This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new fee0157898 Add support for type mappings to REST OpenAPI codegen
fee0157898 is described below
commit fee01578984525840e486443fbf952384e98e505
Author: James Netherton <[email protected]>
AuthorDate: Mon Jan 19 09:46:37 2026 +0000
Add support for type mappings to REST OpenAPI codegen
Fixes #8165
---
.../pages/reference/extensions/rest-openapi.adoc | 14 +++++
.../CamelQuarkusSwaggerCodegenProvider.java | 63 +++++++++++-----------
.../runtime/RestOpenApiBuildTimeConfig.java | 15 ++++++
.../rest-openapi/src/main/openapi/example.yaml | 1 +
.../src/main/resources/application.properties | 2 +
.../component/rest/openapi/it/RestOpenapiTest.java | 11 ++++
6 files changed, 75 insertions(+), 31 deletions(-)
diff --git a/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc
b/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc
index d849f50517..39e5ba551c 100644
--- a/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/rest-openapi.adoc
@@ -199,6 +199,20 @@ a|icon:lock[title=Fixed at build time]
[[quarkus-camel-openapi-codegen-locations
A comma separated list of OpenAPI spec locations.
| `string`
|
+
+a|icon:lock[title=Fixed at build time]
[[quarkus-camel-openapi-codegen-type-mappings-type-mappings]]`link:#quarkus-camel-openapi-codegen-type-mappings-type-mappings[quarkus.camel.openapi.codegen.type-mappings."type-mappings"]`
+
+Mappings between swagger spec types and generated code types.
+
+Multiple type mappings can be specified like the following.
+
+[source,properties]
+----
+quarkus.camel.openapi.codegen.type-mappings.Double=java.math.BigDecimal
+quarkus.camel.openapi.codegen.type-mappings.Date=java.time.LocalDate
+----
+| `Map<String,String>`
+|
|===
[.configuration-legend]
diff --git
a/extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/CamelQuarkusSwaggerCodegenProvider.java
b/extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/CamelQuarkusSwaggerCodegenProvider.java
index 293f76f6f5..7270230e7b 100644
---
a/extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/CamelQuarkusSwaggerCodegenProvider.java
+++
b/extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/CamelQuarkusSwaggerCodegenProvider.java
@@ -22,18 +22,20 @@ import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
-import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import io.quarkus.bootstrap.prebuild.CodeGenException;
import io.quarkus.deployment.CodeGenContext;
import io.quarkus.deployment.CodeGenProvider;
+import io.smallrye.config.SmallRyeConfig;
import io.swagger.codegen.v3.ClientOptInput;
import io.swagger.codegen.v3.CodegenArgument;
import io.swagger.codegen.v3.CodegenConstants;
import io.swagger.codegen.v3.DefaultGenerator;
import io.swagger.codegen.v3.config.CodegenConfigurator;
+import
org.apache.camel.quarkus.rest.openapi.runtime.RestOpenApiBuildTimeConfig;
+import
org.apache.camel.quarkus.rest.openapi.runtime.RestOpenApiBuildTimeConfig.CodeGenConfig;
import org.eclipse.microprofile.config.Config;
import org.jboss.logging.Logger;
@@ -66,8 +68,12 @@ public class CamelQuarkusSwaggerCodegenProvider implements
CodeGenProvider {
@Override
public boolean trigger(CodeGenContext context) throws CodeGenException {
- final Config config = context.config();
- if (!config.getValue("quarkus.camel.openapi.codegen.enabled",
Boolean.class)) {
+ final CodeGenConfig config = context.config()
+ .unwrap(SmallRyeConfig.class)
+ .getConfigMapping(RestOpenApiBuildTimeConfig.class)
+ .codegen();
+
+ if (!config.enabled()) {
LOG.info("Skipping " + this.getClass() + " invocation on user's
request");
return false;
}
@@ -86,9 +92,8 @@ public class CamelQuarkusSwaggerCodegenProvider implements
CodeGenProvider {
}
}
- Optional<String> locations =
config.getOptionalValue("quarkus.camel.openapi.codegen.locations",
String.class);
- if (locations.isPresent()) {
- for (String location : locations.get().split(",")) {
+ config.locations().ifPresent(locations -> {
+ for (String location : locations.split(",")) {
try {
URI uri;
if (location.indexOf("://") == -1) {
@@ -102,52 +107,48 @@ public class CamelQuarkusSwaggerCodegenProvider
implements CodeGenProvider {
LOG.warnf(e, "Can not find location %s", location);
}
}
- }
-
- String packageName =
config.getValue("quarkus.camel.openapi.codegen.model-package", String.class);
- String models =
config.getOptionalValue("quarkus.camel.openapi.codegen.models",
String.class).orElse("");
- boolean useBeanValidation =
config.getValue("quarkus.camel.openapi.codegen.use-bean-validation",
Boolean.class);
- boolean notNullJackson =
config.getValue("quarkus.camel.openapi.codegen.not-null-jackson",
Boolean.class);
- boolean ignoreUnknownProperties =
config.getValue("quarkus.camel.openapi.codegen.ignore-unknown-properties",
- Boolean.class);
+ });
for (String specFile : specFiles) {
LOG.infof("Generating models for %s", specFile);
CodegenConfigurator configurator = new CodegenConfigurator();
configurator.setLang("quarkus");
configurator.setLibrary("quarkus3");
- configurator.setModelPackage(packageName);
+ configurator.setModelPackage(config.modelPackage());
configurator.setInputSpecURL(specFile);
configurator.setOutputDir(context.outDir().toAbsolutePath().toString());
- System.setProperty(CodegenConstants.MODELS, models);
+ System.setProperty(CodegenConstants.MODELS,
config.models().orElse(""));
configurator.getCodegenArguments()
.add(new
CodegenArgument().option(CodegenConstants.API_DOCS_OPTION).type("boolean").value("false"));
configurator.getCodegenArguments()
.add(new
CodegenArgument().option(CodegenConstants.MODEL_DOCS_OPTION).type("boolean").value("false"));
- if (useBeanValidation) {
+
+ if (config.useBeanValidation()) {
configurator.getAdditionalProperties().put(USE_BEANVALIDATION, true);
}
- if (notNullJackson) {
+
+ if (config.notNullJackson()) {
configurator.getAdditionalProperties().put(NOT_NULL_JACKSON_ANNOTATION, true);
}
- if (ignoreUnknownProperties) {
+
+ if (config.ignoreUnknownProperties()) {
configurator.getAdditionalProperties().put("ignoreUnknownProperties", true);
}
- config.getPropertyNames().forEach(name -> {
- if
(name.startsWith("quarkus.camel.openapi.codegen.additional-properties")) {
- String key =
name.substring("quarkus.camel.openapi.codegen.additional-properties.".length());
- String value = config.getValue(name, String.class);
- if
(configurator.getAdditionalProperties().containsKey(key)) {
- LOG.warn("Overriding existing property: " + key +
" with value: " + value);
- }
- if (value.equals("true") || value.equals("false")) {
- configurator.getAdditionalProperties().put(key,
Boolean.parseBoolean(value));
- } else {
- configurator.getAdditionalProperties().put(key,
value);
- }
+
+ config.additionalProperties().forEach((key, value) -> {
+ if
(configurator.getAdditionalProperties().containsKey(key)) {
+ LOG.warn("Overriding existing property: " + key + "
with value: " + value);
+ }
+
+ if (value.equals("true") || value.equals("false")) {
+ configurator.getAdditionalProperties().put(key,
Boolean.parseBoolean(value));
+ } else {
+ configurator.getAdditionalProperties().put(key, value);
}
});
+ configurator.setTypeMappings(config.typeMappings());
+
final ClientOptInput input = configurator.toClientOptInput();
new DefaultGenerator().opts(input).generate();
}
diff --git
a/extensions/rest-openapi/runtime/src/main/java/org/apache/camel/quarkus/rest/openapi/runtime/RestOpenApiBuildTimeConfig.java
b/extensions/rest-openapi/runtime/src/main/java/org/apache/camel/quarkus/rest/openapi/runtime/RestOpenApiBuildTimeConfig.java
index 0b1c00d489..f4d1f65d28 100644
---
a/extensions/rest-openapi/runtime/src/main/java/org/apache/camel/quarkus/rest/openapi/runtime/RestOpenApiBuildTimeConfig.java
+++
b/extensions/rest-openapi/runtime/src/main/java/org/apache/camel/quarkus/rest/openapi/runtime/RestOpenApiBuildTimeConfig.java
@@ -99,5 +99,20 @@ public interface RestOpenApiBuildTimeConfig {
* @asciidoclet
*/
Optional<String> locations();
+
+ /**
+ * Mappings between swagger spec types and generated code types.
+ *
+ * Multiple type mappings can be specified like the following.
+ *
+ * [source,properties]
+ * ----
+ *
quarkus.camel.openapi.codegen.type-mappings.Double=java.math.BigDecimal
+ * quarkus.camel.openapi.codegen.type-mappings.Date=java.time.LocalDate
+ * ----
+ *
+ * @asciidoclet
+ */
+ Map<String, String> typeMappings();
}
}
diff --git a/integration-tests/rest-openapi/src/main/openapi/example.yaml
b/integration-tests/rest-openapi/src/main/openapi/example.yaml
index 6361263206..a6a4c393ed 100644
--- a/integration-tests/rest-openapi/src/main/openapi/example.yaml
+++ b/integration-tests/rest-openapi/src/main/openapi/example.yaml
@@ -92,6 +92,7 @@ components:
rating:
description: Rating.
type: number
+ format: double
multipleOf: 0.01
example: 3.14
diff --git
a/integration-tests/rest-openapi/src/main/resources/application.properties
b/integration-tests/rest-openapi/src/main/resources/application.properties
index be86366699..8ab377d704 100644
--- a/integration-tests/rest-openapi/src/main/resources/application.properties
+++ b/integration-tests/rest-openapi/src/main/resources/application.properties
@@ -20,5 +20,7 @@
quarkus.camel.openapi.codegen.model-package=org.apache.camel.quarkus.component.r
quarkus.camel.openapi.codegen.not-null-jackson=true
quarkus.camel.openapi.codegen.ignore-unknown-properties=true
quarkus.camel.openapi.codegen.additional-properties.errorOnUnknownEnum=true
+quarkus.camel.openapi.codegen.type-mappings.Double=java.math.BigDecimal
+quarkus.camel.openapi.codegen.type-mappings.LocalDate=java.time.OffsetDateTime
camel.rest.bindingMode=json
camel.rest.bindingPackageScan=${quarkus.camel.openapi.codegen.model-package}
diff --git
a/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java
b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java
index 0b61197b02..46ea171f23 100644
---
a/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java
+++
b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java
@@ -17,19 +17,23 @@
package org.apache.camel.quarkus.component.rest.openapi.it;
import java.io.File;
+import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.time.OffsetDateTime;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
+import org.apache.camel.quarkus.component.rest.openapi.it.model.Camel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
@QuarkusTest
class RestOpenapiTest {
@@ -131,4 +135,11 @@ class RestOpenapiTest {
.statusCode(200)
.body(is("\"smart camel\""));
}
+
+ @Test
+ void typeMappingConfigurationGeneratesClassWithExpectedTypes() throws
Exception {
+ Class<Camel> camelClass = Camel.class;
+ assertEquals(BigDecimal.class,
camelClass.getDeclaredField("rating").getType());
+ assertEquals(OffsetDateTime.class,
camelClass.getDeclaredField("birthDate").getType());
+ }
}