Para unir lo que otros ya han dicho o insinuado, las reglas por las cuales JAXB XJC decide si se debe colocar la @XmlRootElementanotación en una clase generada no son triviales ( vea este artículo ).
@XmlRootElementexiste 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.@XmlRootElementproporciona esta información
Sin embargo, la anotación es solo una conveniencia: JAXB no lo requiere. La alternativa a es utilizar JAXBElementobjetos 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 JAXBElementenvoltorios 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 ObjectFactorymé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 unnewobjeto. (¿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
jcen 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.xjbcontenido 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
@XmlRootElementcuando 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
@XmlRootElementanotació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
@XmlRootElementJAXB no genera ninguno . Estos contenedores están disponibles en laObjectFactoryclase 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:simplees suficienteEn su mayoría, creará XmlRootElements para importar definiciones xsd.
2. Divide tus
jaxb2-maven-pluginejecucionesHe 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