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 c071c5dd6b Register BeanDescription.findJsonValueAccessor for
reflection
c071c5dd6b is described below
commit c071c5dd6b0f1e124e33d765a7f13a85c9cbeb70
Author: James Netherton <[email protected]>
AuthorDate: Mon Sep 21 11:15:24 2026 +0100
Register BeanDescription.findJsonValueAccessor for reflection
Swagger ModelResolver looks the method up with a method name that the native
image builder cannot fold, so in native mode @JsonValue types were rendered
as
object schemas and every resolved model logged a WARN and an ERROR.
Fixes #9195
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
.../deployment/SupportSwaggerProcessor.java | 13 ++++++
.../component/openapijava/it/OpenApiRoutes.java | 19 +++++++++
.../openapijava/it/model/JsonValueForm.java | 47 ++++++++++++++++++++++
.../openapijava/it/model/JsonValueFormWrapper.java | 35 ++++++++++++++++
.../component/openapijava/it/v3/OpenApiV3Test.java | 16 ++++++++
5 files changed, 130 insertions(+)
diff --git
a/extensions-support/swagger/deployment/src/main/java/org/apache/camel/quarkus/support/swagger/deployment/SupportSwaggerProcessor.java
b/extensions-support/swagger/deployment/src/main/java/org/apache/camel/quarkus/support/swagger/deployment/SupportSwaggerProcessor.java
index 3aba033161..815b8a57ee 100644
---
a/extensions-support/swagger/deployment/src/main/java/org/apache/camel/quarkus/support/swagger/deployment/SupportSwaggerProcessor.java
+++
b/extensions-support/swagger/deployment/src/main/java/org/apache/camel/quarkus/support/swagger/deployment/SupportSwaggerProcessor.java
@@ -19,11 +19,14 @@ package org.apache.camel.quarkus.support.swagger.deployment;
import java.util.Set;
import java.util.stream.Collectors;
+import com.fasterxml.jackson.databind.BeanDescription;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
+import io.swagger.v3.core.jackson.ModelResolver;
import io.swagger.v3.oas.models.media.Schema;
import org.jboss.jandex.ClassInfo;
@@ -61,4 +64,14 @@ class SupportSwaggerProcessor {
.methods()
.build());
}
+
+ @BuildStep
+ ReflectiveMethodBuildItem jsonValueAccessorMethod() {
+ // ModelResolver.findJsonValueType looks the method up with a method
name that the image builder cannot fold
+ return new ReflectiveMethodBuildItem(
+ ModelResolver.class.getName() + " requires reflective access
to it",
+ BeanDescription.class.getName(),
+ "findJsonValueAccessor",
+ new String[0]);
+ }
}
diff --git
a/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
index e317835f6f..b41b41df94 100644
---
a/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
+++
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
@@ -29,6 +29,7 @@ import org.apache.camel.model.rest.RestParamType;
import
org.apache.camel.quarkus.component.openapijava.it.model.AllOfFormWrapper;
import
org.apache.camel.quarkus.component.openapijava.it.model.AnyOfFormWrapper;
import org.apache.camel.quarkus.component.openapijava.it.model.Fruit;
+import
org.apache.camel.quarkus.component.openapijava.it.model.JsonValueFormWrapper;
import
org.apache.camel.quarkus.component.openapijava.it.model.OneOfFormWrapper;
@ApplicationScoped
@@ -265,6 +266,21 @@ public class OpenApiRoutes extends RouteBuilder {
.to("seda:res");
+ rest("/form")
+ .post("/jsonValue")
+ .tag("JsonValue")
+ .bindingMode(RestBindingMode.json)
+ .description("JsonValue rest service")
+
+ .consumes("application/json")
+ .produces("application/json")
+ .type(JsonValueFormWrapper.class)
+ .responseMessage()
+ .code(200).message("Ok")
+ .endResponseMessage()
+
+ .to("direct:jsonValueForm");
+
rest("/form")
.post("/anyOf")
.tag("AnyOf")
@@ -280,6 +296,9 @@ public class OpenApiRoutes extends RouteBuilder {
.to("seda:res");
+ from("direct:jsonValueForm")
+ .setBody(constant("{\"result\": \"Ok\"}"));
+
from("direct:fruits")
.setBody().constant(getFruits())
.marshal().json();
diff --git
a/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/model/JsonValueForm.java
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/model/JsonValueForm.java
new file mode 100644
index 0000000000..a67703a23e
--- /dev/null
+++
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/model/JsonValueForm.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.quarkus.component.openapijava.it.model;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+/**
+ * A class that Jackson serializes as a simple string via the {@link
JsonValue} annotated accessor.
+ */
+@RegisterForReflection
+public class JsonValueForm {
+
+ String code;
+ String description;
+
+ @JsonValue
+ public String getCode() {
+ return this.code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git
a/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/model/JsonValueFormWrapper.java
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/model/JsonValueFormWrapper.java
new file mode 100644
index 0000000000..b1f53cb7d2
--- /dev/null
+++
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/model/JsonValueFormWrapper.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.quarkus.component.openapijava.it.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+@RegisterForReflection
+public class JsonValueFormWrapper {
+
+ @JsonProperty("form")
+ JsonValueForm form;
+
+ public JsonValueForm getForm() {
+ return this.form;
+ }
+
+ public void setForm(JsonValueForm form) {
+ this.form = form;
+ }
+}
diff --git
a/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/v3/OpenApiV3Test.java
b/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/v3/OpenApiV3Test.java
index 9596590bab..3ae8806826 100644
---
a/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/v3/OpenApiV3Test.java
+++
b/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/v3/OpenApiV3Test.java
@@ -375,6 +375,22 @@ public class OpenApiV3Test {
is("#/components/schemas/AnyOfForm"));
}
+ @ParameterizedTest
+ @EnumSource(OpenApiContentType.class)
+ public void openApiJsonValue(OpenApiContentType contentType) {
+ RestAssured.given()
+ .header("Accept", contentType.getMimeType())
+ .get("/openapi")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.schemas.JsonValueFormWrapper.type",
is("object"),
+ // The @JsonValue accessor determines the schema, so
the remaining bean properties must not leak
+
"components.schemas.JsonValueFormWrapper.properties.form.type", is("string"),
+ "components.schemas", not(hasKey("JsonValueForm")));
+ }
+
@ParameterizedTest
@EnumSource(OpenApiContentType.class)
public void arrayTypes(OpenApiContentType contentType) {