diff --git a/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java b/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java index 17768f6d8e62b..3d488e9d012d9 100644 --- a/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java +++ b/extensions/jaxb/deployment/src/main/java/io/quarkus/jaxb/deployment/JaxbProcessor.java @@ -70,6 +70,7 @@ import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBundleBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageSystemPropertyBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyIgnoreWarningBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; @@ -186,6 +187,7 @@ void processAnnotationsAndIndexFiles( BuildProducer proxyDefinitions, CombinedIndexBuildItem combinedIndexBuildItem, List fileRoots, + BuildProducer reflectiveHierarchies, BuildProducer reflectiveClass, BuildProducer resource, BuildProducer resourceBundle, @@ -202,10 +204,11 @@ void processAnnotationsAndIndexFiles( for (DotName jaxbRootAnnotation : JAXB_ROOT_ANNOTATIONS) { for (AnnotationInstance jaxbRootAnnotationInstance : index .getAnnotations(jaxbRootAnnotation)) { - if (jaxbRootAnnotationInstance.target().kind() == Kind.CLASS) { - String className = jaxbRootAnnotationInstance.target().asClass().name().toString(); - reflectiveClass.produce(ReflectiveClassBuildItem.builder(className).methods().fields().build()); - classesToBeBound.add(className); + if (jaxbRootAnnotationInstance.target().kind() == Kind.CLASS + && !JAXB_ANNOTATIONS.contains(jaxbRootAnnotationInstance.target().asClass().getClass())) { + DotName targetClass = jaxbRootAnnotationInstance.target().asClass().name(); + addReflectiveHierarchyClass(targetClass, reflectiveHierarchies, index); + classesToBeBound.add(targetClass.toString()); jaxbRootAnnotationsDetected = true; } } @@ -412,6 +415,17 @@ public static Stream safeWalk(Path p) { } } + private void addReflectiveHierarchyClass(DotName className, + BuildProducer reflectiveHierarchy, + IndexView index) { + Type jandexType = Type.create(className, Type.Kind.CLASS); + reflectiveHierarchy.produce(new ReflectiveHierarchyBuildItem.Builder() + .type(jandexType) + .index(index) + .source(getClass().getSimpleName() + " > " + jandexType.name().toString()) + .build()); + } + private void addReflectiveClass(BuildProducer reflectiveClass, boolean methods, boolean fields, String... className) { reflectiveClass.produce(new ReflectiveClassBuildItem(methods, fields, className)); diff --git a/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/BookIBANField.java b/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/BookIBANField.java new file mode 100644 index 0000000000000..5fc7a28bdcfa9 --- /dev/null +++ b/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/BookIBANField.java @@ -0,0 +1,24 @@ +package io.quarkus.it.jaxb; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlTransient; + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlTransient +public abstract class BookIBANField { + @XmlElement + private String IBAN; + + public BookIBANField() { + } + + public void setIBAN(String IBAN) { + this.IBAN = IBAN; + } + + public String getIBAN() { + return IBAN; + } +} diff --git a/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/BookWithParent.java b/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/BookWithParent.java new file mode 100644 index 0000000000000..d4d81b481e267 --- /dev/null +++ b/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/BookWithParent.java @@ -0,0 +1,27 @@ +package io.quarkus.it.jaxb; + +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlType; + +@XmlRootElement +@XmlType(propOrder = { "IBAN", "title" }) +public class BookWithParent extends BookIBANField { + @XmlElement + private String title; + + public BookWithParent() { + } + + public BookWithParent(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/JaxbResource.java b/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/JaxbResource.java index b03507a82089e..d6a9b8e386574 100644 --- a/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/JaxbResource.java +++ b/integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/JaxbResource.java @@ -65,4 +65,19 @@ public io.quarkus.it.jaxb.Response seeAlso() { return response; } + //Test for Jaxb with parent class field + @Path("/bookwithparent") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getBookWithParent(@QueryParam("name") String name, @QueryParam("iban") String iban) throws JAXBException { + BookWithParent bookWithParent = new BookWithParent(); + bookWithParent.setTitle(name); + bookWithParent.setIBAN(iban); + JAXBContext context = JAXBContext.newInstance(bookWithParent.getClass()); + Marshaller marshaller = context.createMarshaller(); + StringWriter sw = new StringWriter(); + marshaller.marshal(bookWithParent, sw); + return sw.toString(); + } + } diff --git a/integration-tests/jaxb/src/test/java/io/quarkus/it/jaxb/JaxbIT.java b/integration-tests/jaxb/src/test/java/io/quarkus/it/jaxb/JaxbIT.java index ae862b4a11e41..06611d4a0c081 100644 --- a/integration-tests/jaxb/src/test/java/io/quarkus/it/jaxb/JaxbIT.java +++ b/integration-tests/jaxb/src/test/java/io/quarkus/it/jaxb/JaxbIT.java @@ -1,8 +1,24 @@ package io.quarkus.it.jaxb; +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + import io.quarkus.test.junit.QuarkusIntegrationTest; @QuarkusIntegrationTest public class JaxbIT extends JaxbTest { - + //We have to test native executable of Jaxb + @Test + public void bookWithParent() { + given().when() + .param("name", "Foundation") + .param("iban", "4242") + .get("/jaxb/bookwithparent") + .then() + .statusCode(200) + .body(is( + "4242Foundation")); + } }