Skip to content

jaxb.index not registered through quarkus-jaxb #48059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
vsevel opened this issue May 26, 2025 · 6 comments
Open

jaxb.index not registered through quarkus-jaxb #48059

vsevel opened this issue May 26, 2025 · 6 comments

Comments

@vsevel
Copy link
Contributor

vsevel commented May 26, 2025

Describe the bug

I have an application that contains a org/acme/jaxb.index and a jaxb annotated org.acme.Employee class , and some code that relies on it when creating a context:

JAXBContext ctx = JAXBContext.newInstance("org.acme");

this is working in jvm mode, but fails in native because the file is not registered.
in native there will be an error saying that a jaxb.index or ObjectFactory class are expected.

Expected behavior

there should be a consistent behavior between jvm and native modes.
we should be able to register automatically jaxb.index either in the main module itself, or one of its dependencies.

Actual behavior

jakarta.xml.bind.JAXBException: "org.acme" doesnt contain ObjectFactory.class or jaxb.index
	at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:241)
	at org.glassfish.jaxb.runtime.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:58)
	at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:322)
	at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:392)

How to Reproduce?

create an application with extension quarkus-jaxb
add src/main/resources/jaxb.index with content:

Employee

create class org.acme.Employee with:

package org.acme;

import jakarta.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "employeeType", namespace = "org.acme", propOrder = { "name", "age" })
@XmlRootElement(name = "employee", namespace = "org.acme")
public class Employee {

    @XmlElement(required = true)
    protected String name;

    protected int age;

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int value) {
        this.age = value;
    }
}

create endpoint:

    @GET
    @Path("/jaxb")
    @Produces(MediaType.TEXT_PLAIN)
    public String jaxb() throws JAXBException {
        JAXBContext ctx = JAXBContext.newInstance("org.acme");
        return ctx.toString();
    }

and test:

    @Test
    void testJaxbEndpoint() {
        given()
                .when().get("/hello/jaxb")
                .then()
                .statusCode(200)
                .body(containsString("Classes known to this context"));
    }

the same test in native will fail.

Output of uname -a or ver

No response

Output of java -version

No response

Mandrel or GraalVM version (if different from Java)

No response

Quarkus version or git rev

3.22

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

I was able to fix it with this additional code in one of our extensions:

    @BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
    void jaxb(final CurateOutcomeBuildItem outcome,
            final BuildProducer<ReflectiveClassBuildItem> reflective, // do not remove
            final BuildProducer<NativeImageResourcePatternsBuildItem> resource) {

        if (hasDependency(outcome, "io.quarkus", "quarkus-jaxb")) {
            Log.info("detected quarkus-jaxb dependency, adding native image resources for jaxb.index");
            resource.produce(NativeImageResourcePatternsBuildItem.builder().includePattern(".*/jaxb.index$").build());
        }
    }

    private boolean hasDependency(final CurateOutcomeBuildItem outcome, String groupId, String artifactId) {
        return outcome.getApplicationModel().getDependencies().stream()
                .anyMatch(resolvedDependency -> groupId.equals(resolvedDependency.getGroupId())
                        && artifactId.equals(resolvedDependency.getArtifactId()));
    }

although functional, the code could probably be more efficient?
as a side note, if I did not include the reflective argument, then we do not enter into the build step??

I looked at the jaxb processor. it has some code already to do some logic about jaxb files. but in my use case I never enter those methods because fileRoots is empty.
and I do not see anybody creating JaxbFileRootBuildItem objects.

see also https://quarkusio.zulipchat.com/#narrow/channel/187030-users/topic/jaxb.2Eindex.20not.20registered.20in.20native

@vsevel vsevel added kind/bug Something isn't working area/native-image labels May 26, 2025
Copy link

quarkus-bot bot commented May 26, 2025

You added a link to a Zulip discussion, please make sure the description of the issue is comprehensive and doesn't require accessing Zulip

This message is automatically generated by a bot.

Copy link

quarkus-bot bot commented May 26, 2025

/cc @Karm (native-image), @galderz (native-image), @gsmet (jaxb), @zakkak (native-image)

@geoand
Copy link
Contributor

geoand commented May 27, 2025

@vsevel can you please attach a sample that exhibits the problem? If we have that, it should be possible to udnerstand exactly why the current code does not handle the case in question.

Thanks

@vsevel
Copy link
Contributor Author

vsevel commented May 27, 2025

here it is: https://github.com/vsevel/quarkus_reproducers/tree/issue_48059_jaxb_native

mvn package -Pnative
docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/jaxb_reproducer .
docker run -i --rm -p 8080:8080 quarkus/jaxb_reproducer
curl localhost:8080/hello/jaxb
2025-05-27 06:43:42,191 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello/jaxb failed, error id: a8b50dc2-47e1-4163-b92d-21ba7c921fd7-1: jakarta.xml.bind.JAXBException: "org.acme" ne contient pas ObjectFactory.class ou jaxb.index
        at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:241)
        at [email protected]/java.lang.reflect.Method.invoke(Method.java:580)
        at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:182)
        at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:140)
        at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:340)
        at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:392)
        at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:349)
        at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:260)
        at org.acme.GreetingResource.jaxb(GreetingResource.java:23)
        at org.acme.GreetingResource$quarkusrestinvoker$jaxb_643671e5f3177961c718a020ab2bfd03b027e3af.invoke(Unknown Source)
        at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
        at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$15.runWith(VertxCoreRecorder.java:637)
        at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
        at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at [email protected]/java.lang.Thread.runWith(Thread.java:1596)
        at [email protected]/java.lang.Thread.run(Thread.java:1583)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:896)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:872)

@geoand
Copy link
Contributor

geoand commented May 27, 2025

🙏

@geoand
Copy link
Contributor

geoand commented May 27, 2025

It seems like JaxbFileRootBuildItem was added specifically for Camel Quarkus and is produced here.

I do wonder whether we should detect these automatically... WDYT @gsmet ?

@geoand geoand added kind/enhancement New feature or request and removed kind/bug Something isn't working labels May 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants