Pour lier ce que d'autres ont déjà déclaré ou laissé entendre, les règles selon lesquelles JAXB XJC décide de mettre ou non l' @XmlRootElement
annotation sur une classe générée ne sont pas triviales ( voir cet article ).
@XmlRootElement
existe parce que le runtime JAXB nécessite certaines informations afin de marshaler / démarsaler un objet donné, en particulier le nom de l'élément XML et l'espace de noms. Vous ne pouvez pas simplement passer un vieil objet au Marshaller. @XmlRootElement
fournit ces informations.
L'annotation n'est cependant qu'une commodité - JAXB n'en a pas besoin. L'alternative à est d'utiliser des JAXBElement
objets wrapper, qui fournissent les mêmes informations que @XmlRootElement
, mais sous la forme d'un objet, plutôt que d'une annotation.
Cependant, les JAXBElement
objets sont difficiles à construire, car vous devez connaître le nom de l'élément XML et l'espace de noms, ce que la logique métier ne connaît généralement pas.
Heureusement, lorsque XJC génère un modèle de classe, il génère également une classe appelée ObjectFactory
. Ceci est en partie là pour la compatibilité ascendante avec JAXB v1, mais c'est aussi là pour que XJC place des méthodes d'usine générées qui créent des JAXBElement
wrappers autour de vos propres objets. Il gère le nom et l'espace de noms XML pour vous, vous n'avez donc pas à vous en préoccuper. Il vous suffit de parcourir les ObjectFactory
méthodes (et pour les grands schémas, il peut y en avoir des centaines) pour trouver celle dont vous avez besoin.
new ObjectFactory().createPositionReport(positionReport)
retourneJAXBElement<PositionReport>
JXBElement
? Dans mon cas, la méthode d'usine est 0-aire et renvoie juste unnew
objet. (Pourquoi certaines classes reçoivent-elles des assistants de wrapper JAXBElement et d'autres non?) Je suppose que dans ce cas, nous devons créer le wrapper nous-mêmes?Ceci est mentionné au bas du billet de blog déjà lié ci-dessus, mais cela fonctionne comme un régal pour moi:
la source
jc
contient l'extrait ci-dessus?Comme indiqué dans l'une des réponses ci-dessus, vous n'obtiendrez pas de XMLRootElement sur votre élément racine si dans le XSD son type est défini comme un type nommé, car ce type nommé pourrait être utilisé ailleurs dans votre XSD. Essayez de lui donner un type anonyme, c'est-à-dire au lieu de:
tu aurais:
la source
@XmlRootElement n'est pas nécessaire pour unmarshalling - si l'on utilise la forme à 2 paramètres de Unmarshaller # unmarshall.
Donc, si au lieu de faire:
il faut faire:
Ce dernier code ne nécessitera pas d'annotation @XmlRootElement au niveau de la classe UserType.
la source
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 réponse de Joe (Joe 26 juin 09 à 17:26) le fait pour moi. La réponse simple est que l'absence d'une annotation @XmlRootElement ne pose aucun problème si vous marshalez un JAXBElement. La chose qui m'a dérouté est que l'ObjectFactory généré a 2 méthodes createMyRootElement - la première ne prend aucun paramètre et donne l'objet non enveloppé, la seconde prend l'objet non enveloppé et le retourne enveloppé dans un JAXBElement, et la mise en forme que JAXBElement fonctionne bien. Voici le code de base que j'ai utilisé (je suis nouveau dans ce domaine, donc excuses si le code n'est pas formaté correctement dans cette réponse), largement extrait du texte du lien :
la source
Vous pouvez résoudre ce problème en utilisant la liaison de Comment générer des classes @XmlRootElement pour les types de base dans XSD? .
Voici un exemple avec Maven
Voici le
binding.xjb
contenu du fichierla source
Comme vous le savez, la réponse consiste à utiliser ObjectFactory (). Voici un exemple du code qui a fonctionné pour moi :)
la source
Cela ne fonctionne pas non plus pour nous. Mais nous avons trouvé un article largement cité qui ajoute QUELQUES antécédents ... Je vais le lier ici pour le bien de la prochaine personne: http://weblogs.java.net/blog/kohsuke/archive/2006/03 /why_does_jaxb_p.html
la source
Après avoir traîné pendant deux jours, j'ai trouvé la solution au problème. Vous pouvez utiliser la classe ObjectFactory pour contourner les classes qui n'ont pas @XmlRootElement . ObjectFactory a surchargé les méthodes pour l'enrouler autour de JAXBElement.
Méthode: 1 fait la création simple de l'objet.
Méthode: 2 enveloppera l'objet avec @JAXBElement .
Utilisez toujours la méthode: 2 pour éviter javax.xml.bind.MarshalException - avec une exception liée manquant une annotation @XmlRootElement.
Veuillez trouver l'exemple de code ci-dessous
Méthode: 1 fait la création simple de l'objet
Méthode: 2 enveloppera l'objet avec @JAXBElement .
Exemple de code de travail:
la source
Dans le cas où mon expérience de ce problème donne à quelqu'un un Eureka! moment .. je vais ajouter ce qui suit:
J'obtenais également ce problème, lorsque j'utilisais un fichier xsd que j'avais généré en utilisant l'option de menu "Générer xsd à partir d'un document d'instance" d'IntelliJ.
Lorsque j'ai accepté tous les paramètres par défaut de cet outil, il a généré un fichier xsd qui, lorsqu'il est utilisé avec jaxb, génère des fichiers java sans
@XmlRootElement
. Au moment de l'exécution, lorsque j'ai essayé de rassembler, j'ai eu la même exception que celle discutée dans cette question.Je suis retourné à l'outil IntellJ et j'ai vu l'option par défaut dans la liste déroulante "Type de Desgin" (ce que bien sûr je ne comprenais pas .. et toujours pas si je suis honnête) était:
Type de conception:
J'ai changé cela en
, maintenant il a généré un xsd (sensiblement) différent, qui a produit le
@XmlRootElement
lorsqu'il est utilisé avec jaxb. Je ne peux pas dire que je comprends les avantages et les inconvénients, mais cela a fonctionné pour moi.la source
Avec une build Maven, vous pouvez ajouter le
@XmlRootElement
annotationavec le
jaxb2-basics-annotate
plug-in " ".Voir plus d'informations: voir
Configurer Maven pour générer des classes à partir du schéma XML à l'aide de JAXB
et génération de code JAXB XJC
la source
Les wrappers JAXBElement fonctionnent pour les cas où aucun
@XmlRootElement
n'est généré par JAXB. Ces wrappers sont disponibles dans laObjectFactory
classe générée parmaven-jaxb2-plugin
. Par exemple:la source
Avez-vous essayé de changer votre xsd comme ça?
la source
Pour le résoudre, vous devez configurer une liaison xml avant de compiler avec wsimport, en définissant generateElementProperty sur false.
la source
<jaxb:bindings> ... <jaxws:bindings> ... </jaxws:bindings> ... </jaxb:bindings>
Le sujet est assez ancien mais toujours pertinent dans les contextes d'entreprise. J'ai essayé d'éviter de toucher les xsds afin de les mettre à jour facilement à l'avenir. Voici mes solutions ..
1. Surtout
xjc:simple
suffitIl créera principalement des XmlRootElements pour importer des définitions xsd.
2. Divisez vos
jaxb2-maven-plugin
exécutionsJ'ai rencontré que cela fait une énorme différence si vous essayez de générer des classes à partir de plusieurs définitions xsd au lieu d'une définition d'exécution par xsd.
Donc, si vous avez une définition avec plusieurs
<source>
, essayez simplement de les diviser:Le générateur n'acceptera pas le fait qu'une classe pourrait être suffisante et créera donc des classes personnalisées par exécution. Et c'est exactement ce dont j'ai besoin;).
la source