Java jaxb:枚举列表上的奇怪类强制转换异常

Java jaxb:枚举列表上的奇怪类强制转换异常,java,xml,jaxb,java-8,oxm,Java,Xml,Jaxb,Java 8,Oxm,我正在使用jaxb从xsd文件生成java类。xsd包含元素的定义,其内容是在与枚举相同的xsd中定义的常量列表 当使用JAXB参考实现从oracle的jdk1.7(v2.2.4-2)生成类时,可以迭代枚举列表并为它们分配相同类型的变量 但是,当使用oracle的jdk1.8(build1.8.0_45-b15-发布日期的最新版本)JAXB参考实现(v2.2.8-b130911.1802)生成类时,就不可能再将列表元素分配给枚举类型的变量 任何使用增强for循环分配或迭代的尝试都以ClassCa

我正在使用
jaxb
xsd
文件生成java类。
xsd
包含元素的定义,其内容是在与枚举相同的
xsd
中定义的常量列表

当使用JAXB参考实现从oracle的
jdk1.7
v2.2.4-2
)生成类时,可以迭代枚举列表并为它们分配相同类型的变量

但是,当使用oracle的
jdk1.8
(build
1.8.0_45-b15
-发布日期的最新版本)JAXB参考实现(
v2.2.8-b130911.1802
)生成类时,就不可能再将列表元素分配给枚举类型的变量

任何使用增强for循环分配或迭代的尝试都以
ClassCastException

java.lang.ClassCastException: java.lang.String cannot be cast to so.jaxb.enums.generated.GConstNameType
    at so.jaxb.enums.domain.TestReader.readTest(TestReader.java:36)
    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:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
在这两种情况下,列表本身都使用正确的枚举类型参数化

下面是再现上述问题的代码:

XSD文件

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns="http://www.w3.org/2001/XMLSchema" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://www.foo.com/xmlns/test"
    targetNamespace="http://www.foo.com/xmlns/test"
    attributeFormDefault="unqualified"
    elementFormDefault="qualified">

    <xs:simpleType name="GConstType">
        <xs:list itemType="tns:GConstNameType" />
    </xs:simpleType>
    <xs:simpleType name="GConstNameType">
        <xs:restriction base="xs:string">
            <xs:enumeration value="FOO" />
            <xs:enumeration value="BAR" />
            <xs:enumeration value="BAZ" />
        </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="TestType">
        <xs:all>
            <xs:element name="const-name-list" 
                type="tns:GConstType" minOccurs="0" maxOccurs="1" />
        </xs:all>
    </xs:complexType>

    <xs:element name="test" type="tns:TestType" />

</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<t:test xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:t="http://www.foo.com/xmlns/test"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <t:const-name-list>FOO BAR</t:const-name-list>

</t:test>
输出jdk1.8

java.lang.String
java.lang.String
<ClassCastException>

  • 这怎么可能/这里发生了什么
  • 上面显示的架构定义对于定义枚举是否不正确
  • 如何解决这个问题而不必使用
    XmlAdapter
    (一种适用于所有jdk版本的方法)

编辑

两个生成的包之间唯一的代码差异

删除注释

@XmlSchemaType(name = "anySimpleType")
使
jdk1.8
生成的代码完全可用

  • 为什么较新的
    JAXB
    实现将枚举映射到
    anySimpleType

您可以将xsd更改为:

 <xs:complexType name="TestType">
    <xs:sequence>
        <xs:element name="const-name-list">
            <xs:simpleType>
                <xs:list itemType="tns:GConstNameType"/>
            </xs:simpleType>
        </xs:element>
    </xs:sequence>
</xs:complexType>

<xs:simpleType name="GConstNameType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="FOO"/>
        <xs:enumeration value="BAR"/>
        <xs:enumeration value="BAZ"/>
    </xs:restriction>
</xs:simpleType>

这是在Java8上工作的

新的解析器有一些新的限制

更新:您可以使用以下内容发表评论:



您是否尝试过使用而不是?Java8似乎对XML字符串可以或不可以是什么不太宽容。@medveshonok117按照建议尝试了
xs:token
,但
xcj
仍在生成
@XmlSchemaType(name=“anySimpleType”)
,这导致了JAXB GH项目中的
ClassCastException
。谢谢您的回答。虽然这可以解决这个问题,但我发现每次需要时都必须内联定义类型,而不是定义一次并使用属性type=“…”引用它,这不是很明智的做法。你能详细说明一下这些限制吗?是否有任何规范告诉我们枚举列表现在必须这样定义(两个定义是等效的)?无论如何,我认为生成
String
s列表并注入
GConstNameType
列表与其说是一个限制,不如说是一个bug。限制反过来起作用;-)@A4L您是指列表的定义吗?是的,简单类型
GConstType
,在您的版本中是匿名的,因为它是内联的。@A4L我安装了最新的xsd。嘿,我看到了您的更新,但没有时间评估它。您的第二个建议也很有效,但我发现第一个变体更好,因为与第二个相比,它仅以最小的方式更改了原始的
xsd
。我将接受您的回答,因为它提供了一种变通方法,可以处理从
xjc
的两个版本生成的代码。没有奖励,因为没有提供进一步的解释:(,但无论如何,再次感谢您的时间和帮助!
C:\Oracle\Java\jdk1.7\bin\xjc.exe D:\dev\java\Tests\src\so\jaxb\enums\resources\test.xsd -b D:\dev\java\Tests\src\so\jaxb\enums\resources -d D:\dev\java\Tests/src -p so.jaxb.enums.generated -extension 
C:\Oracle\Java\jdk1.8\bin\xjc.exe D:\dev\java\Tests\src\so\jaxb\enums\resources\test.xsd -b D:\dev\java\Tests\src\so\jaxb\enums\resources -d D:\dev\java\Tests/src -p so.jaxb.enums.generated -extension 
@XmlSchemaType(name = "anySimpleType")
 <xs:complexType name="TestType">
    <xs:sequence>
        <xs:element name="const-name-list">
            <xs:simpleType>
                <xs:list itemType="tns:GConstNameType"/>
            </xs:simpleType>
        </xs:element>
    </xs:sequence>
</xs:complexType>

<xs:simpleType name="GConstNameType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="FOO"/>
        <xs:enumeration value="BAR"/>
        <xs:enumeration value="BAZ"/>
    </xs:restriction>
</xs:simpleType>
<xs:complexType name="TestType">
    <xs:complexContent>
        <xs:extension base="tns:ListType">
            <xs:sequence/>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="ListType">
    <xs:sequence>
        <xs:element name="const-name-list">
            <xs:simpleType>
                <xs:list itemType="tns:GConstNameType"/>
            </xs:simpleType>
        </xs:element>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="SecondTestType">
    <xs:complexContent>
        <xs:extension base="tns:ListType">
            <xs:sequence/>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:simpleType name="GConstNameType">
    <xs:restriction base="xs:string">
        <xs:enumeration value="FOO"/>
        <xs:enumeration value="BAR"/>
        <xs:enumeration value="BAZ"/>
    </xs:restriction>
</xs:simpleType>