Skip to content

Commit

Permalink
Introduce JAXB fixes
Browse files Browse the repository at this point in the history
- Add missing NativeImageProxyDefinitionBuildItem
- Support XmlSeeAlso annotations
- Fix separator in jaxb index file
  • Loading branch information
dufoli authored and gastaldi committed Sep 8, 2021
1 parent 5717733 commit 4026386
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/native-tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
{
"category": "Misc4",
"timeout": 65,
"test-modules": "picocli-native, gradle, micrometer-mp-metrics, micrometer-prometheus, logging-json, jaxp, opentelemetry",
"test-modules": "picocli-native, gradle, micrometer-mp-metrics, micrometer-prometheus, logging-json, jaxp, jaxb, opentelemetry",
"os-name": "ubuntu-latest"
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.jaxb.deployment;

import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.lang.annotation.Annotation;
Expand All @@ -10,7 +11,6 @@
import java.util.List;
import java.util.stream.Stream;

import javax.inject.Inject;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlAccessOrder;
import javax.xml.bind.annotation.XmlAccessorType;
Expand Down Expand Up @@ -47,10 +47,10 @@

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget.Kind;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;

import com.sun.xml.bind.v2.model.annotation.Locatable;
import org.jboss.jandex.Type;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
Expand Down Expand Up @@ -108,15 +108,13 @@ class JaxbProcessor {
private static final DotName XML_SCHEMA = DotName.createSimple(XmlSchema.class.getName());
private static final DotName XML_JAVA_TYPE_ADAPTER = DotName.createSimple(XmlJavaTypeAdapter.class.getName());
private static final DotName XML_ANY_ELEMENT = DotName.createSimple(XmlAnyElement.class.getName());
private static final DotName XML_SEE_ALSO = DotName.createSimple(XmlSeeAlso.class.getName());

private static final List<DotName> JAXB_ROOT_ANNOTATIONS = Arrays.asList(XML_ROOT_ELEMENT, XML_TYPE, XML_REGISTRY);

private static final List<DotName> IGNORE_TYPES = Collections
.singletonList(DotName.createSimple("javax.xml.datatype.XMLGregorianCalendar"));

@Inject
ApplicationArchivesBuildItem applicationArchivesBuildItem;

@BuildStep
void processAnnotationsAndIndexFiles(
BuildProducer<NativeImageSystemPropertyBuildItem> nativeImageProps,
Expand All @@ -127,7 +125,8 @@ void processAnnotationsAndIndexFiles(
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<NativeImageResourceBuildItem> resource,
BuildProducer<NativeImageResourceBundleBuildItem> resourceBundle,
BuildProducer<RuntimeInitializedClassBuildItem> runtimeClasses) {
BuildProducer<RuntimeInitializedClassBuildItem> runtimeClasses,
ApplicationArchivesBuildItem applicationArchivesBuildItem) {

IndexView index = combinedIndexBuildItem.getIndex();

Expand Down Expand Up @@ -170,18 +169,133 @@ void processAnnotationsAndIndexFiles(
JAXB_ANNOTATIONS.stream()
.map(Class::getName)
.forEach(className -> {
proxyDefinitions.produce(new NativeImageProxyDefinitionBuildItem(className, Locatable.class.getName()));
proxyDefinitions.produce(new NativeImageProxyDefinitionBuildItem(className,
"com.sun.xml.bind.v2.model.annotation.Locatable"));
addReflectiveClass(reflectiveClass, true, false, className);
});

proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.marshaller.CharacterEscapeHandler"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.txw2.output.CharacterEscapeHandler"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.episode.Bindings"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.episode.SchemaBindings"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.episode.Klass"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.episode.Package"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Annotated"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Annotation"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Any"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Appinfo"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.AttrDecls"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.AttributeType"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ComplexContent"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ComplexExtension"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ComplexRestriction"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ComplexType"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ComplexTypeHost"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ComplexTypeModel"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem(
"com.sun.xml.bind.v2.schemagen.xmlschema.ContentModelContainer"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Documentation"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Element"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ExplicitGroup"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.ExtensionType"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.FixedOrDefault"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Import"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.List"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.LocalAttribute"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.LocalElement"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.NestedParticle"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.NoFixedFacet"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Occurs"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Particle"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Redefinable"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Schema"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SchemaTop"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SimpleContent"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SimpleDerivation"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SimpleExtension"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SimpleRestriction"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem(
"com.sun.xml.bind.v2.schemagen.xmlschema.SimpleRestrictionModel"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SimpleType"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.SimpleTypeHost"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.TopLevelAttribute"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.TopLevelElement"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.TypeDefParticle"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.TypeHost"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Union"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.bind.v2.schemagen.xmlschema.Wildcard"));
proxyDefinitions
.produce(new NativeImageProxyDefinitionBuildItem("com.sun.xml.txw2.TypedXmlWriter"));

for (JaxbFileRootBuildItem i : fileRoots) {
try (Stream<Path> stream = iterateResources(i.getFileRoot())) {
try (Stream<Path> stream = iterateResources(applicationArchivesBuildItem, i.getFileRoot())) {
stream.filter(p -> p.getFileName().toString().equals("jaxb.index"))
.forEach(p1 -> handleJaxbFile(p1, resource, reflectiveClass));
}
}
}

@BuildStep
void seeAlso(CombinedIndexBuildItem combinedIndexBuildItem,
BuildProducer<ReflectiveClassBuildItem> reflectiveItems) {
IndexView index = combinedIndexBuildItem.getIndex();
for (AnnotationInstance xmlSeeAlsoAnn : index.getAnnotations(XML_SEE_ALSO)) {
AnnotationValue value = xmlSeeAlsoAnn.value();
Type[] types = value.asClassArray();
for (Type t : types) {
reflectiveItems.produce(new ReflectiveClassBuildItem(false, false, t.name().toString()));
}
}
}

@BuildStep
void ignoreWarnings(BuildProducer<ReflectiveHierarchyIgnoreWarningBuildItem> ignoreWarningProducer) {
for (DotName type : IGNORE_TYPES) {
Expand Down Expand Up @@ -221,7 +335,8 @@ private void handleJaxbFile(Path p, BuildProducer<NativeImageResourceBuildItem>
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
try {
String path = p.toAbsolutePath().toString().substring(1);
String pkg = p.toAbsolutePath().getParent().toString().substring(1).replace("/", ".") + ".";
String pkg = p.toAbsolutePath().getParent().toString().substring(1)
.replace(File.separator, ".") + ".";

resource.produce(new NativeImageResourceBuildItem(path));

Expand All @@ -242,7 +357,7 @@ private void handleJaxbFile(Path p, BuildProducer<NativeImageResourceBuildItem>
}
}

private Stream<Path> iterateResources(String path) {
private Stream<Path> iterateResources(ApplicationArchivesBuildItem applicationArchivesBuildItem, String path) {
return applicationArchivesBuildItem.getAllApplicationArchives().stream()
.map(arch -> arch.getChildPath(path))
.filter(p -> p != null && Files.isDirectory(p))
Expand Down
83 changes: 83 additions & 0 deletions integration-tests/jaxb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-integration-tests-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-integration-test-jaxb</artifactId>
<name>Quarkus - Integration Tests - JAXB</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jaxb</artifactId>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>

<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jaxb-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


</project>
24 changes: 24 additions & 0 deletions integration-tests/jaxb/src/main/java/io/quarkus/it/jaxb/Book.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.quarkus.it.jaxb;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Book {

private String title;

public Book() {
}

public Book(String title) {
this.title = title;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.it.jaxb;

import java.io.StringWriter;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

@Path("/jaxb")
@ApplicationScoped
public class JaxbResource {

@Path("/book")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getBook(@QueryParam("name") String name)
throws JAXBException {
Book book = new Book();
book.setTitle(name);
JAXBContext context = JAXBContext.newInstance(book.getClass());
Marshaller marshaller = context.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(book, sw);
return sw.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Book
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.quarkus.it.jaxb;

import io.quarkus.test.junit.NativeImageTest;

@NativeImageTest
public class JaxbIT extends JaxbTest {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkus.it.jaxb;

import static org.hamcrest.Matchers.is;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;

@QuarkusTest
public class JaxbTest {

@Test
public void book() {
RestAssured.given().when()
.param("name", "Foundation")
.get("/jaxb/book")
.then()
.statusCode(200)
.body(is(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><book><title>Foundation</title></book>"));
}
}
Loading

0 comments on commit 4026386

Please sign in to comment.