J'expérimente les différentes formes de la méthode newInstance dans la classe JAXBContext (J'utilise l'implémentation Sun JAXB par défaut fournie avec Oracle JDK 1.7).
Ce n'est pas clair pour moi quand il est juste de passer à la méthode newInstance les classes concrètes par rapport à la classe ObjectFactory. Je dois noter que j'utilise JAXB uniquement pour l'analyse de fichiers XML, c'est-à-dire uniquement dans le sens XML-> Java.
Voici le code absolument minimal qui démontre mon point:
<?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>
Étant donné le XSD ci-dessus, les invocations JAXBInstance.newInstance réussissent à créer un contexte qui peut analyser un exemple a.xml de fichier:
Cependant, le passage de example.a.RootType.class seul échoue avec javax.xml.bind.UnmarshalException lors de l'exécution:
jc = JAXBContext.newInstance(example.a.RootType.class); // this fails at runtime.
Quelqu'un peut-il nous éclairer? La raison pour laquelle j'expérimente sur ces variations JAXBContext :: newInstance est que je suis tombé sur ce problème où la réponse acceptée incluait l'option "construire le contexte JAXB basé sur des classes individuelles plutôt que sur des usines d'objets ". L'exemple a.xml et le [~ # ~] jaxb [~ # ~] Java code que j'utilise suivre à la fin du post.
<?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>
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() );
}
modèle JAXB généré à partir d'un schéma XML
Lors de la création d'un JAXBContext
à partir d'un modèle généré à partir d'un schéma XML, je recommande toujours de le faire sur le nom du package des classes générées.
JAXBContext jc = JAXBContext.newInstance("example.a");
Il est encore préférable d'utiliser une méthode newInstance
qui prend un paramètre ClassLoader
. Cela vous évitera du chagrin lorsque vous passerez d'un environnement Java SE à Java EE).
JAXBContext jc = JAXBContext.newInstance("example.a", example.a.ObjectFactory.class.getClassLoader());
Lorsque vous créez le JAXBContext
sur le nom du package, l'impl JAXB suppose que vous avez généré le modèle à partir d'un schéma XML et extrait la classe ObjectFactory
car il génère toujours la classe annotée avec @XmlRegistry
avec ce nom.
à partir d'un Java
C'est à ce moment que je recommande aux gens d'utiliser les méthodes newInstance
qui prennent des cours. Lors du démarrage d'un JAXBContext
à partir de classes JAXB, il n'y a rien de spécial à propos d'une classe appelée ObjectFactory
. Le rôle de ObjectFactory
peut être joué par n'importe quelle classe annotée avec @XmlRegistry
donc il n'est pas automatiquement recherché. C'est pourquoi votre cas d'utilisation a fonctionné lorsque vous référencez explicitement ObjectFactory
et a échoué lorsque vous ne l'avez pas fait.