Para unir lo que otros ya han dicho o insinuado, las reglas por las cuales JAXB XJC decide si se debe colocar la @XmlRootElement
anotación en una clase generada no son triviales ( vea este artículo ).
@XmlRootElement
existe porque el tiempo de ejecución JAXB requiere cierta información para ordenar / desunir un objeto dado, específicamente el nombre del elemento XML y el espacio de nombres. No puedes pasar cualquier objeto viejo al Marshaller.@XmlRootElement
proporciona esta información
Sin embargo, la anotación es solo una conveniencia: JAXB no lo requiere. La alternativa a es utilizar JAXBElement
objetos de contenedor, que proporcionan la misma información que@XmlRootElement
, pero en forma de objeto, en lugar de una anotación.
Sin embargo, JAXBElement
objetos son difíciles de construir, ya que necesita conocer el nombre del elemento XML y el espacio de nombres, lo que la lógica empresarial generalmente no conoce.
Afortunadamente, cuando XJC genera un modelo de clase, también genera una clase llamada ObjectFactory
. Esto se debe en parte a la compatibilidad con versiones anteriores de JAXB v1, pero también es un lugar para que XJC coloque métodos de fábrica generados que creen JAXBElement
envoltorios alrededor de sus propios objetos. Maneja el nombre XML y el espacio de nombres por usted, por lo que no necesita preocuparse por eso. Solo necesita mirar a través de los ObjectFactory
métodos (y para un esquema grande, puede haber cientos de ellos) para encontrar el que necesita.
new ObjectFactory().createPositionReport(positionReport)
regresaJAXBElement<PositionReport>
JXBElement
? En mi caso, el método de fábrica es 0-arity y solo devuelve unnew
objeto. (¿Por qué algunas clases reciben ayudantes del contenedor JAXBElement y otras no?) Supongo que en ese caso debemos crear el contenedor nosotros mismos.Esto se menciona en la parte inferior de la publicación del blog ya vinculada anteriormente, pero esto funciona como un placer para mí:
fuente
jc
en el fragmento anterior?Como se insinuó en una de las respuestas anteriores, no obtendrá un XMLRootElement en su elemento raíz si en el XSD su tipo se define como un tipo con nombre, ya que ese tipo con nombre podría usarse en cualquier otro lugar de su XSD. Intente convertirlo en un tipo anónimo, es decir, en lugar de:
tu tendrías:
fuente
@XmlRootElement no es necesario para desmarcar, si uno usa la forma de 2 parámetros de Unmarshaller # unmarshall.
Entonces, si en lugar de hacer:
uno debe hacer:
El último código no requerirá la anotación @XmlRootElement en el nivel de clase UserType.
fuente
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();
La respuesta de Joe (Joe 26 de junio de 2009 a las 17:26) lo hace por mí. La respuesta simple es que la ausencia de una anotación @XmlRootElement no es un problema si reúne un JAXBElement. Lo que me confundió es que ObjectFactory generado tiene 2 métodos createMyRootElement: el primero no toma parámetros y proporciona el objeto sin envolver, el segundo toma el objeto sin envolver y lo devuelve envuelto en un JAXBElement, y calcula que JAXBElement funciona bien. Aquí está el código básico que utilicé (soy nuevo en esto, así que disculpas si el código no está formateado correctamente en esta respuesta), en gran parte del texto del enlace :
fuente
Puede solucionar este problema utilizando el enlace de ¿Cómo generar las clases @XmlRootElement para los tipos base en XSD? .
Aquí hay un ejemplo con Maven
Aquí está el
binding.xjb
contenido del archivofuente
Como sabes, la respuesta es usar ObjectFactory (). Aquí hay una muestra del código que funcionó para mí :)
fuente
Tampoco funciona para nosotros. Pero sí encontramos un artículo ampliamente citado que agrega ALGUNOS antecedentes ... Lo vincularé aquí por el bien de la siguiente persona: http://weblogs.java.net/blog/kohsuke/archive/2006/03 /why_does_jaxb_p.html
fuente
Después de buscar durante dos días, encontré la solución para el problema. Puede usar la clase ObjectFactory para solucionar las clases que no tienen @XmlRootElement . ObjectFactory ha sobrecargado los métodos para envolverlo alrededor de JAXBElement.
Método 1 realiza la creación simple del objeto.
Método: 2 envolverá el objeto con @JAXBElement .
Siempre use Método: 2 para evitar javax.xml.bind.MarshalException: a la excepción vinculada le falta una anotación @XmlRootElement.
Encuentre el código de muestra a continuación
Método: 1 realiza la creación simple del objeto
Método: 2 envolverá el objeto con @JAXBElement .
Código de trabajo de muestra:
fuente
¡En caso de que mi experiencia con este problema le dé a alguien un Eureka! momento .. Agregaré lo siguiente:
También estaba teniendo este problema, cuando usaba un archivo xsd que había generado usando la opción de menú "Generar xsd desde el documento de instancia" de IntelliJ.
Cuando acepté todos los valores predeterminados de esta herramienta, generó un archivo xsd que cuando se usaba con jaxb, generaba archivos java sin
@XmlRootElement
. En el tiempo de ejecución, cuando intenté reunir, obtuve la misma excepción que se discutió en esta pregunta.Regresé a la herramienta IntellJ y vi que la opción predeterminada en el menú desplegable "Desgin Type" (que por supuesto no entendí ... y aún no lo sé si soy sincero) fue:
Tipo de diseño:
Cambié esto a
, ahora generó un (sustancialmente) xsd diferente, que produjo el
@XmlRootElement
cuando se usa con jaxb. No puedo decir que entiendo los entresijos, pero funcionó para mí.fuente
Con una compilación de Maven, puede agregar el
@XmlRootElement
anotacióncon el "
jaxb2-basics-annotate
" complemento.Ver más información: ver
Configure Maven para generar clases a partir del esquema XML utilizando JAXB
y generación de código JAXB XJC
fuente
Los contenedores JAXBElement funcionan para casos en los que
@XmlRootElement
JAXB no genera ninguno . Estos contenedores están disponibles en laObjectFactory
clase generada pormaven-jaxb2-plugin
. Por ejemplo:fuente
¿Intentaste cambiar tu xsd así?
fuente
Para solucionarlo, debe configurar un enlace xml antes de compilar con wsimport, estableciendo generateElementProperty como falso.
fuente
<jaxb:bindings> ... <jaxws:bindings> ... </jaxws:bindings> ... </jaxb:bindings>
El tema es bastante antiguo pero aún relevante en contextos empresariales empresariales. Traté de evitar tocar los xsds para actualizarlos fácilmente en el futuro. Aquí están mis soluciones.
1. Principalmente
xjc:simple
es suficienteEn su mayoría, creará XmlRootElements para importar definiciones xsd.
2. Divide tus
jaxb2-maven-plugin
ejecucionesHe encontrado que hace una gran diferencia si intenta generar clases a partir de múltiples definiciones xsd en lugar de una definición de ejecución por xsd.
Entonces, si tiene una definición con múltiples
<source>
, intente dividirlas:El generador no detectará el hecho de que una clase podría ser suficiente y, por lo tanto, creará clases personalizadas por ejecución. Y eso es exactamente lo que necesito;).
fuente