Чтобы связать воедино то, что другие уже заявили или намекнули, правила, по которым JAXB XJC решает, помещать @XmlRootElement
аннотацию в сгенерированный класс, нетривиальны ( см. Эту статью ).
@XmlRootElement
существует, потому что среда выполнения JAXB требует определенной информации для маршалирования / демаршализации заданного объекта, в частности имени элемента XML и пространства имен. Вы не можете просто передать какой-нибудь старый объект маршаллеру. @XmlRootElement
предоставляет эту информацию.
Однако аннотация - это просто удобство - JAXB этого не требует. Альтернативой является использование JAXBElement
объектов-оболочек, которые предоставляют ту же информацию @XmlRootElement
, но в виде объекта, а не аннотации.
Однако JAXBElement
создавать объекты неудобно, поскольку вам необходимо знать имя элемента XML и пространство имен, чего обычно нет в бизнес-логике.
К счастью, когда XJC генерирует модель класса, он также генерирует класс с именем ObjectFactory
. Это частично для обратной совместимости с JAXB v1, но XJC также может предоставить сгенерированные фабричные методы, которые создают JAXBElement
обертки вокруг ваших собственных объектов. Он обрабатывает имя XML и пространство имен для вас, поэтому вам не нужно беспокоиться об этом. Вам просто нужно просмотреть ObjectFactory
методы (а для больших схем их может быть сотни), чтобы найти тот, который вам нужен.
new ObjectFactory().createPositionReport(positionReport)
возвращаетсяJAXBElement<PositionReport>
JXBElement
? В моем случае фабричный метод имеет 0-арность и просто возвращаетnew
объект. (Почему некоторым классам предоставляются помощники обертки JAXBElement, а другим нет?) Я полагаю, в этом случае мы должны сами создать обертку?Это упомянуто в нижней части поста в блоге, уже связанного выше, но это работает как удовольствие для меня:
источник
jc
в приведенном фрагменте?Как указывалось в одном из приведенных выше ответов, вы не получите XMLRootElement для своего корневого элемента, если в XSD его тип определен как именованный тип, поскольку этот именованный тип может использоваться в другом месте вашего XSD. Попробуйте создать анонимный тип, т.е. вместо:
вам придется:
источник
@XmlRootElement не нужен для демаршаллинга - если используется форма с 2 параметрами Unmarshaller # unmarshall.
Итак, если вместо этого:
нужно сделать:
Последний код не требует аннотации @XmlRootElement на уровне класса UserType.
источник
String pathname = "file.xml"; InputStream stream = new FileInputStream(pathname); JAXBContext jaxbContext = JAXBContext.newInstance(UserType.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader someSource = factory.createXMLEventReader(stream); JAXBElement<UserType> userElement = jaxbUnmarshaller.unmarshal(someSource, UserType.class); UserType user = userElement.getValue();
Ответ Джо (Joe Jun 26 '09 в 17:26) делает это для меня. Простой ответ заключается в том, что отсутствие аннотации @XmlRootElement не является проблемой, если вы упорядочиваете JAXBElement. Меня смутило то, что сгенерированный ObjectFactory имеет 2 метода createMyRootElement - первый не принимает параметров и дает развернутый объект, второй берет развернутый объект и возвращает его, завернутый в JAXBElement, и указывает, что JAXBElement работает нормально. Вот основной код, который я использовал (я новичок в этом, поэтому извиняюсь, если код не отформатирован правильно в этом ответе), в основном из текста ссылки :
источник
Вы можете исправить эту проблему, используя привязку из Как создать классы @XmlRootElement для базовых типов в XSD? ,
Вот пример с Maven
Вот
binding.xjb
содержимое файлаисточник
Как вы знаете, ответ заключается в использовании ObjectFactory (). Вот пример кода, который работал для меня :)
источник
У нас это тоже не работает. Но мы нашли широко цитируемую статью, в которой добавлено НЕКОТОРОЕ предысторию ... Я приведу ссылку на нее здесь ради следующего человека: http://weblogs.java.net/blog/kohsuke/archive/2006/03 /why_does_jaxb_p.html
источник
После двух дней работы я нашел решение этой проблемы. Вы можете использовать класс ObjectFactory для обхода тех классов, которые не имеют @XmlRootElement . ObjectFactory имеет перегруженные методы, чтобы обернуть его вокруг JAXBElement.
Метод: 1 делает простое создание объекта.
Метод: 2 обернет объект с помощью @JAXBElement .
Всегда используйте Method: 2, чтобы избежать javax.xml.bind.MarshalException - со связанным исключением отсутствует аннотация @XmlRootElement.
Пожалуйста, найдите образец кода ниже
Метод: 1 делает простое создание объекта
Метод: 2 обернет объект с помощью @JAXBElement .
Пример рабочего кода:
источник
В случае, если мой опыт этой проблемы дает кому-то Эврика! момент .. Я добавлю следующее:
Я также столкнулся с этой проблемой, когда использовал xsd-файл, сгенерированный с помощью опции меню IntelliJ «Создать xsd из документа экземпляра».
Когда я принял все значения по умолчанию этого инструмента, он сгенерировал xsd-файл, который при использовании с jaxb генерировал java-файлы без
@XmlRootElement
. Во время выполнения, когда я пытался выполнить маршализацию, я получил то же исключение, что обсуждалось в этом вопросе.Я вернулся к инструменту IntellJ и увидел опцию по умолчанию в выпадающем списке «Desgin Type» (которая, конечно, я не понимал .. и все еще не понимаю, если честно) была:
Тип дизайна:
Я изменил это на
, теперь он сгенерировал (существенно) другой xsd, который генерировал
@XmlRootElement
при использовании с jaxb. Не могу сказать, что понимаю все, что нужно, но это сработало для меня.источник
Со сборкой Maven вы можете добавить
@XmlRootElement
аннотациюс "
jaxb2-basics-annotate
" плагином.Смотрите больше информации: см.
Сконфигурируйте Maven для генерации классов из XML-схемы с использованием JAXB
и генерация кода JAXB XJC
источник
Оболочки JAXBElement работают в случаях, когда
@XmlRootElement
JAXB не генерирует no . Эти оболочки доступны вObjectFactory
классе, сгенерированномmaven-jaxb2-plugin
. Например:источник
Вы пытались изменить свой XSD, как это?
источник
Чтобы решить эту проблему, вы должны настроить привязку xml перед тем, как скомпилировать с помощью wsimport, установив generateElementProperty как false.
источник
<jaxb:bindings> ... <jaxws:bindings> ... </jaxws:bindings> ... </jaxb:bindings>
Эта тема довольно старая, но все еще актуальна в контексте предпринимательской деятельности. Я старался не трогать xsds, чтобы легко обновлять их в будущем. Вот мои решения ..
1. В основном
xjc:simple
достаточноВ основном это создаст XmlRootElements для импорта определений xsd.
2. Разделите ваши
jaxb2-maven-plugin
казниЯ столкнулся с тем, что это имеет огромное значение, если вы попытаетесь сгенерировать классы из нескольких определений xsd вместо определения исполнения для xsd.
Поэтому, если у вас есть определение с несколькими
<source>
, просто попробуйте разделить их:Генератор не уловит тот факт, что одного класса может быть достаточно, и, следовательно, создает пользовательские классы для выполнения. И это именно то, что мне нужно;).
источник