Tôi đang sử dụng jaxb
để tạo các lớp java từ tệp xsd
. Các xsd
chứa một định nghĩa của một yếu tố trong đó nội dung là một danh sách các hằng số được xác định trong cùng một xsd
như liệt kê.jaxb: ngoại lệ lớp học lạ trên danh sách enum
Khi các lớp được tạo bằng cách thực hiện tham chiếu JAXB từ oracle's jdk1.7
(v2.2.4-2
), có thể lặp qua danh sách enums và gán cho chúng các biến cùng loại.
Tuy nhiên, khi các lớp được tạo bằng oracle của jdk1.8
(xây dựng 1.8.0_45-b15
- mới nhất của đăng ngày) thực hiện chiếu JAXB (v2.2.8-b130911.1802
) nó không còn có thể gán các yếu tố của danh sách để biến kiểu enum.
Bất kỳ cố gắng để gán hoặc lặp bằng cách sử dụng tăng cường cho vòng kết thúc bằng một 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)
Danh sách chính nó là trong cả hai trường hợp tham số với kiểu enum chính xác.
Dưới đây là một mã tái tạo vấn đề đã nêu ở trên:
tập tin 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>
Kiểm tra tập tin XML
<?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>
đọc thử
public class TestReader {
@Test
public void readTest() throws IOException {
try (InputStream xml = TestReader.class
.getResourceAsStream("/so/jaxb/enums/resources/test.xml");
InputStream xsd = TestReader.class
.getResourceAsStream("/so/jaxb/enums/resources/test.xsd")) {
TestType testType = fromXML(TestType.class, xml, xsd);
List<GConstNameType> constNameList = testType.getConstNameList();
for(Object constName : constNameList) {
System.out.println(constName.getClass().getName());
}
for(GConstNameType constName : constNameList) {
System.out.println(constName);
}
}
}
public static <T> T fromXML(Class<T> _class, InputStream xml, InputStream xsd) {
XMLStreamReader xsr = null;
try {
Source xmlSource = new StreamSource(xml);
Source xsdSource = new StreamSource(xsd);
JAXBContext jaxbContext = JAXBContext.newInstance(_class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Schema schema = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(xsdSource);
unmarshaller.setSchema(schema);
xsr = XMLInputFactory.newInstance().createXMLStreamReader(xmlSource);
JAXBElement<T> jaxbElement = unmarshaller.unmarshal(xsr, _class);
return jaxbElement.getValue();
} catch (JAXBException | SAXException | XMLStreamException | FactoryConfigurationError e) {
throw new RuntimeException(e);
} finally {
try {
if(xsr != null) {
xsr.close();
}
} catch(XMLStreamException e) {
throw new RuntimeException(e);
}
}
}
}
jdk1.7 Output
so.jaxb.enums.generated.GConstNameType
so.jaxb.enums.generated.GConstNameType
FOO
BAR
Output jdk1.8
java.lang.String
java.lang.String
<ClassCastException>
Từ đầu ra ở trên rõ ràng là yếu tố của các loại java.lang.String
được nhập lậu vào danh sách List<GConstNameType>
hoặc Danh sách String
s được đặt thay vì Danh sách GConstNameType
s. Dù sao tên của các enums String
từ tệp xml không được ánh xạ tới hằng số enum java.
Thời gian chạy java trong cả hai trường hợp giống nhau, đó là số jre
từ số jdk1.8
.
Các lệnh sử dụng cho thế hệ:
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
và
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
- như thế nào possibles này/Điều gì đang xảy ra ở đây?
- Định nghĩa lược đồ được hiển thị ở trên không chính xác để xác định một điều tra?
- Cách khắc phục sự cố này mà không phải sử dụng
XmlAdapter
(cách hoạt động trên mọi phiên bản jdk)?
EDIT
Sự khác biệt mã chỉ giữa hai gói tạo
Loại bỏ các chú thích
@XmlSchemaType(name = "anySimpleType")
hiển thị mã được tạo ra jdk1.8
đầy đủ chức năng.
- Tại sao mới hơn
JAXB
triển khai ánh xạ enum thànhanySimpleType
?
Bạn đã cố gắng sử dụng * * thay của * *? Có vẻ như Java8 ít khoan dung hơn về chuỗi XML có thể hoặc không thể. –
medveshonok117
@ medveshonok117 đã thử với 'xs: token' như được đề xuất nhưng' xcj' vẫn tạo '@XmlSchemaType (name =" anySimpleType ")' dẫn đến 'ClassCastException'. – A4L
Sự cố trong dự án GH JAXB: https://github.com/gf-metro/jaxb/issues/21 –