尝试编组 VBox 子类时发生 IllegalAnnotationExceptions

IllegalAnnotationExceptions occurs when trying to marshall a VBox subclass

我创建了一个 VBox 的子类,我想使用适配器对其进行编组,但是 JAXB 抛出 IllegalAnnonationExceptions,表示它无法处理接口。是不是适配器用错了?

我在 Java 1.8 中使用 JavaFX 和 JAXB 的内置版本编写这篇文章。

一个最小的、可重现的例子:

import javafx.scene.layout.VBox;

import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.nio.file.Files;
import java.nio.file.Paths;

class Foo extends VBox {
    private int bar;

    public Foo(int bar) {
        this.bar = bar;
    }

    public int getBar() {
        return bar;
    }
}

class XMLfoo {
    public int bar;
}

class XMLfooAdapter extends XmlAdapter<XMLfoo, Foo> {
    @Override public Foo unmarshal(XMLfoo xmLfoo) {
        return new Foo(xmLfoo.bar);
    }

    @Override public XMLfoo marshal(Foo foo) {
        XMLfoo out = new XMLfoo();
        out.bar = foo.getBar();
        return out;
    }
}

public class TestFoo {
    @XmlJavaTypeAdapter(XMLfooAdapter.class) private static Foo foo = new Foo(1);

    public static void main(String[] args) throws Exception{
        JAXB.marshal(foo, Files.newBufferedWriter(Paths.get("foo.xml")));
    }
}

堆栈跟踪:

Exception in thread "main" javax.xml.bind.DataBindingException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
javafx.event.EventDispatcher is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at javafx.event.EventDispatcher
        at public final javafx.event.EventDispatcher javafx.scene.Node.getEventDispatcher()
        at javafx.scene.Node
        at javafx.scene.shape.Shape
        at public final javafx.scene.shape.Shape javafx.scene.layout.Region.getShape()
        at javafx.scene.layout.Region
        at javafx.scene.layout.Pane
        at javafx.scene.layout.VBox
        at Foo
javafx.scene.input.InputMethodRequests is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at javafx.scene.input.InputMethodRequests
        at public final javafx.scene.input.InputMethodRequests javafx.scene.Node.getInputMethodRequests()
        at javafx.scene.Node
        at javafx.scene.shape.Shape
        at public final javafx.scene.shape.Shape javafx.scene.layout.Region.getShape()
        at javafx.scene.layout.Region
        at javafx.scene.layout.Pane
        at javafx.scene.layout.VBox
        at Foo
javafx.event.EventHandler is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at javafx.event.EventHandler
        at public final javafx.event.EventHandler javafx.scene.Node.getOnContextMenuRequested()
        at javafx.scene.Node
        at javafx.scene.shape.Shape
        at public final javafx.scene.shape.Shape javafx.scene.layout.Region.getShape()
        at javafx.scene.layout.Region
        at javafx.scene.layout.Pane
        at javafx.scene.layout.VBox
        at Foo

    at javax.xml.bind.JAXB._marshal(JAXB.java:574)
    at javax.xml.bind.JAXB.marshal(JAXB.java:456)
    at Foo.main(Foo.java:23)
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
javafx.event.EventDispatcher is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at javafx.event.EventDispatcher
        at public final javafx.event.EventDispatcher javafx.scene.Node.getEventDispatcher()
        at javafx.scene.Node
        at javafx.scene.shape.Shape
        at public final javafx.scene.shape.Shape javafx.scene.layout.Region.getShape()
        at javafx.scene.layout.Region
        at javafx.scene.layout.Pane
        at javafx.scene.layout.VBox
        at Foo
javafx.scene.input.InputMethodRequests is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at javafx.scene.input.InputMethodRequests
        at public final javafx.scene.input.InputMethodRequests javafx.scene.Node.getInputMethodRequests()
        at javafx.scene.Node
        at javafx.scene.shape.Shape
        at public final javafx.scene.shape.Shape javafx.scene.layout.Region.getShape()
        at javafx.scene.layout.Region
        at javafx.scene.layout.Pane
        at javafx.scene.layout.VBox
        at Foo
javafx.event.EventHandler is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at javafx.event.EventHandler
        at public final javafx.event.EventHandler javafx.scene.Node.getOnContextMenuRequested()
        at javafx.scene.Node
        at javafx.scene.shape.Shape
        at public final javafx.scene.shape.Shape javafx.scene.layout.Region.getShape()
        at javafx.scene.layout.Region
        at javafx.scene.layout.Pane
        at javafx.scene.layout.VBox
        at Foo

    at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at javax.xml.bind.JAXB$Cache.<init>(JAXB.java:112)
    at javax.xml.bind.JAXB.getContext(JAXB.java:139)
    at javax.xml.bind.JAXB._marshal(JAXB.java:563)
    ... 2 more

根据 Slaw 的评论使其正常工作:

import javafx.scene.layout.VBox;

import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlRootElement;
import java.nio.file.Files;
import java.nio.file.Paths;

class Foo extends VBox {
    private int bar;

    public Foo(int bar) {
        this.bar = bar;
    }

    // To get a Foo back from a XMLfoo
    public Foo(XMLfoo xmLfoo) {
        this.bar = xmLfoo.bar;
    }

    public int getBar() {
        return bar;
    }

    // To convert from Foo to XMLfoo
    public XMLfoo toXML() {
        XMLfoo out = new XMLfoo();
        out.bar = bar;
        return out;
    }
}

@XmlRootElement(name = "Foo")
class XMLfoo {
    public int bar;
}

public class TestFoo {
    public static void main(String[] args) throws Exception {
        JAXB.marshal((new Foo(1)).toXML(), Files.newBufferedWriter(Paths.get("foo.xml")));
        Foo foo = new Foo(JAXB.unmarshal(Files.newBufferedReader(Paths.get("foo.xml")), XMLfoo.class));
    }
}

将创建包含

foo.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Foo>
    <bar>1</bar>
</Foo>