Варианты JAXBContext.newInstance
Я экспериментирую с различными формами метода newInstance в классе JAXBContext (я использую реализацию Sun JAXB по умолчанию, которая поставляется с Oracle JDK 1.7).
Мне не ясно, когда это просто передать методу newInstance конкретные классы по сравнению с классом ObjectFactory. Я должен отметить, что я использую JAXB исключительно для разбора XML файлов, т.е. Только в направлении XML- > Java.
Здесь абсолютно минимальный код, демонстрирующий мою точку зрения:
xsd file
<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified"
xmlns ="http://www.w3.org/2001/XMLSchema"
xmlns:a ="http://www.example.org/A"
targetNamespace="http://www.example.org/A">
<element name="root" type="a:RootType"></element>
<complexType name="RootType">
<sequence>
<element name="value" type="string"></element>
</sequence>
</complexType>
</schema>
Учитывая вышеупомянутый XSD, следующие вызовы JAXBInstance.newInstance преуспевают в создании контекста, который может анализировать образец a.xml:
- jc = JAXBContext.newInstance( "example.a" );
- jc = JAXBContext.newInstance(example.a.ObjectFactory.class);
- jc = JAXBContext.newInstance(example.a.RootType.class, example.a.ObjectFactory.class);
Однако при прохождении example.a.RootType.class не удается выполнить javax.xml.bind.UnmarshalException во время выполнения:
jc = JAXBContext.newInstance(example.a.RootType.class); // this fails at runtime.
Может ли кто-нибудь пролить свет? Причина, по которой я экспериментирую в этих вариантах JAXBContext:: newInstance, заключается в том, что я наткнулся на эту проблему, где принятый ответ включал в себя возможность "создание контекста JAXB, основанного на отдельных классах, а не на объектных фабриках". Пример a.xml и код JAXB Java, который я использую, следует в конце сообщения.
используется пример a.xml
<?xml version="1.0" encoding="UTF-8"?>
<a:root xmlns:a="http://www.example.org/A"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/A A.xsd">
<a:value>foo</a:value>
</a:root>
код анализа JAXB
public static void main (String args[]) throws JAXBException, FileNotFoundException {
JAXBContext jc = null;
message("using package context (press any key:)");
jc = JAXBContext.newInstance("example.a");
work(jc); // SUCCEEDS
message("using Object factory (press any key):");
jc = JAXBContext.newInstance(example.a.ObjectFactory.class);
work(jc); // SUCCEEDS
message("using class enumeration (press any key):");
try {
jc = JAXBContext.newInstance(example.a.RootType.class);
work(jc); // FAILS
} catch (javax.xml.bind.UnmarshalException e) {
e.printStackTrace();
}
message("using class enumeration and Object factory too (press any key):");
jc = JAXBContext.newInstance(example.a.RootType.class, example.a.ObjectFactory.class);
work(jc); // SUCCEEDS
}
private static void work(JAXBContext jc) throws JAXBException, FileNotFoundException {
Unmarshaller u = jc.createUnmarshaller();
RootType root = ((JAXBElement<RootType>)u.unmarshal( new FileInputStream( "a.xml" ))).getValue();
System.out.println( root.getValue() );
}
Ответы
Ответ 1
Модель JAXB, созданная с помощью XML-схемы
При создании JAXBContext
из модели, сгенерированной из XML-схемы, я всегда рекомендую сделать это в имени пакета сгенерированных классов.
JAXBContext jc = JAXBContext.newInstance("example.a");
Еще лучше использовать метод newInstance
, который принимает параметр ClassLoader
. Это избавит вас от горя, когда вы перейдете от среды Java SE к среде Java EE.
JAXBContext jc = JAXBContext.newInstance("example.a", example.a.ObjectFactory.class.getClassLoader());
Когда вы создаете JAXBContext
в имени пакета, JAXB impl предполагает, что вы сгенерировали модель из схемы XML и вытягиваете класс ObjectFactory
, поскольку он всегда генерирует класс, аннотированный с помощью @XmlRegistry
с этим именем.
Начиная с модели Java
Это когда я рекомендую людям использовать методы newInstance
, которые принимают классы. При начальной загрузке JAXBContext
из классов JAXB нет ничего особенного в классе под названием ObjectFactory
. Роль ObjectFactory
может быть воспроизведена любым классом, аннотированным с помощью @XmlRegistry
, поэтому он не будет автоматически искать. Вот почему ваш прецедент работал, когда вы явно ссылались на ObjectFactory
и не сработали, когда вы этого не сделали.