Deux classes ont le même type XML nom “objectFactory”
Nous avons été à l'aide de JAXB 2.1 pour une longue période dans notre système. Nous avons une plate-forme qui est construit avec Ant et génère un tas de séries qui sont déployés dans OSGi moment de l'exécution. Nous utilisons Java SE 6.
Nous utilisons JAXB pendant le processus de génération pour générer des types de données à partir de différents schémas. Ces classes sont emballés dans des faisceaux utilisés lors de l'exécution de sérialiser/désérialiser de contenu. En outre, nous utilisons des JAXB dans notre plate-forme d'exécution pour générer les types de données à partir d'autres schémas fournis par l'utilisateur (une sorte de MDA pour la plate-forme).
Dans OSGi d'exécution, nous avons un module qui a l'JAXB et des pots et des exportations les paquets nécessaires. Nous avons créer un JAXBContext exemple avec le chemin de contexte de l'ensemble de l'objet usines générés, afin que nous puissions marshall/unmarshall tous nos types de données.
Qui a travaillé jusqu'à présent, mais maintenant nous sommes en train de mettre à jour vers la dernière version stable de JAXB (2.2.4) et nous sommes d'avoir des problèmes en essayant de créer le contexte d'exécution. Nous obtenons l'exception suivante:
Two classes have the same XML type name "objectFactory". Use @XmlType.name and @XmlType.namespace to assign different names to them.
this problem is related to the following location:
at some.package.ObjectFactory
this problem is related to the following location:
at some.other.package.ObjectFactory
at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:436)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:191)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:187)
... 76 more
L'erreur Deux classes ont le même type XML nom "objectFactory" est imprimé pour chaque objet usines générés pendant le processus de génération.
Nous avons vu plusieurs postes avec la même erreur, mais l'application pour les types générés, et non pas à l'objet de l'usine. Nous pensons que JAXB peut-être pas l'identification de l'ObjectFactory classe comme une fabrique d'objet, mais comme un type de données.
Une possibilité est que nous étions à l'aide de la version interne de JAXB dans la version 6 de Java, nous avons donc décidé d'utiliser le Système de Propriété -Djava.approuvé.dirs et de mettre les trois pots (jaxb-api-2.2.4.jar, jaxb-impl-2.2.4.jar et jaxb-xjc-2.2.4.jar) dans ce chemin, mais toujours pas de travail.
Nous pensons que le problème pourrait être que nous sommes à l'aide d'une version différente de JAXB dans OSGi d'exécution et dans le processus de construction, de sorte que le code généré n'est pas compatible. Mais peut-être que nous sommes dans l'erreur et il y a un autre problème.
Avez-vous des idées?
Merci d'avance.
(Edit: plus de détails sur ce sujet)
Nous à créer le JAXBContext de cette façon:
ClassLoader classLoader = new JAXBServiceClassLoader(getParentClassLoader(),
Collections.unmodifiableMap(objectFactories));
context = JAXBContext.newInstance(contextPath.toString(), classLoader);
où contextPath est une Chaîne qui contient l'ensemble de notre objet d'usines, séparés par ':', et le JAXBServiceClassLoader est:
private static final class JAXBServiceClassLoader extends ClassLoader
{
@NotNull
private final Map<String, Object> objectFactories;
private JAXBServiceClassLoader(@NotNull ClassLoader parent, @NotNull Map<String, Object> objectFactories)
{
super(parent);
this.objectFactories = objectFactories;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException
{
Class<?> ret;
try
{
ret = super.loadClass(name);
}
catch (ClassNotFoundException e)
{
Object objectFactory = objectFactories.get(name);
if (objectFactory != null)
{
ret = objectFactory.getClass();
}
else
{
throw new ClassNotFoundException(name + " class not found");
}
}
return ret;
}
}
(Edit: après Aaron post)
J'ai été le débogage de tous les éléments internes de JAXBContextImpl et le truc, c'est que le JAXBContextImpl est d'essayer d'obtenir le type d'informations à partir de notre ObjectFactory classes, ce qui est faux. En fait, dans com.soleil.xml.interne.bind.v2.de modèle.impl.ModelBuilder:314, le getClassAnnotation() qui renvoie la valeur null mais quand je vois l'exemple, je peux voir l'annotation XmlRegistry.
Le truc, c'est que, à ce point de XmlRegistry.classe.getClassLoader() renvoie null, mais si je lance ((Classe)c).getAnnotations()[0].annotationType().getClassLoader (), elle renvoie le chargeur de classe de l'OSGi bundle "lib.jaxb" qui contient mon JAXB pots, ce qui est correct.
Donc, je suppose que nous sommes de chargement dans le même temps, deux versions différentes de XmlRegistry, l'un à partir du JDK et de l'autre à partir de JAXB 2.2.4 pots. La question est: pourquoi?
Et, plus encore, au lieu de charger tous ces com.soleil.xml.interne.* les classes (comme JAXBContextImpl), ne devrait pas être le chargement et l'exécution de com.soleil.xml.bind.v2.moment de l'exécution.JAXBContextImpl de JAXB de pots? Pendant le processus de débogage je peux voir qu'il fait des trucs avec de la réflexion, mais je ne comprends pas pourquoi le faire.
- À l'aide de Java SE 6, je vous conseille d'utiliser la dernière version du patch version de votre JAXB impl qui prend en charge JAXB 2.1 à moins qu'il y est un particulier, JAXB 2.2 fonctionnalité que vous essayez d'utiliser.
- Désolé de ne pas le mentionner. La raison de la mise à niveau de JAXB 2.2.4, c'est que nous améliorons nos JAX-WS version 2.2.5 et il dépend de la version de JAXB (jax-ws.java.net/2.2.5/docs/ReleaseNotes.html). Sinon, on pourrait utiliser JAXB 2.1.
- Il ressemble à votre JAXB impl-à tort-le traitement de l'
ObjectFactory
comme un domaine de la classe. Ceci est probablement dû à la@XmlRegistry
annotation ne pas être reconnu en raison d'unClassLoader
différence entre les classes de votre domaine et JAX-WS mise en œuvre. Êtes-vous de la création de laJAXBContext
directement ou JAX-WS de mise en œuvre de cette mesure? - Non, dans ce cas, je ne suis pas à l'utiliser via JAX-WS. Je crée directement le JAXBContext passant le chemin de contexte avec tous l'objet d'usines en tant que paramètre. Le code n'a pas du tout changé, j'ai juste remplacé les pots de 2.1.9 par la version 2.2.4.
- Puisque vous êtes dans un environnement OSGi, je crois que vous êtes dans un cas où les classes de votre domaine et JAXB impl font référence à des versions différentes de la JAXB binaires. Ce n'était pas le cas avant car il n'y avait qu'une seule version de la JAXB binaires disponibles. Pouvez-vous modifier votre code, de sorte que lorsque vous créez la JAXBContext vous transmettre le chargeur de classe qui a les classes de votre domaine chargé?
- J'ai édité le post, donc vous pouvez voir le code que nous utilisons pour instancier un JAXBContext.
Vous devez vous connecter pour publier un commentaire.
Nous avons enfin trouvé une solution pour cela.
De la JAXB documentation (Découverte de JAXB mise en œuvre section):
http://jaxb.java.net/nonav/2.2.4-1/docs/api/javax/xml/bind/JAXBContext.html
Nous avons essayé d'ajouter une ressource dans META-INF/services/javax.xml.bind.JAXBContext afin d'imposer l'utilisation de com.soleil.xml.bind.v2.ContextFactory au lieu de Soleil interne de l'usine. Cela ne fonctionne pas, probablement parce que nous sommes à l'aide d'un bundle OSGi.
De toute façon, comme nous utilisons notre propre chargeur de classe, nous avons remplacer la getResourceAsStream() méthode qui est appelée à partir de ContextFinder:343:
Ce n'est pas la plus jolie de la solution, mais il travaille pour nous. Et que le chargeur de classe est utilisé seulement lorsque nous créons de la JAXBContext, il devrait être bon.
Assurez-vous qu'il existe une seule
@XmlRegistry
annotation dans votre classpath (Recherche deXmlRegistry.class
fichier, pas d'utilisation). Peut-être la mauvaise annotation est ramassé.Si cela ne fonctionne pas, créer votre propre classloader qui ne voit qu'une usine. Qui ne devrait pas être nécessaire, mais qui sait.
Essayer de définir un point d'arrêt à JAXBContextImpl.java:436 pour voir quels types de processus et pourquoi.
J'ai eu le même problème, mais une cause différente. Même si il pourrait ne pas fixer les auteurs de problèmes je poste cette réponse à ceux qui, en lisant ce post plus tard et d'avoir le même problème que moi.
J'ai utilisé ce compilateur de configuration du plugin, ce qui exclue package-info.java les fichiers de compilation. Après la suppression de l'exclut tout ce qui a fonctionné comme un charme! Il semble que JAXB inclure quelques définitions importantes dans ces fichiers!
Cassé Config:
De Travail Config:
J'ai eu un problème similaire lorsque vous tentez de déployer un printemps à base de web service soap. J'ai ajouté un paquet à la
contextPaths
d'unorg.springframework.oxm.jaxb.Jaxb2Marshaller
printemps bean. Le problème était que la même classe était dans d'autres packages inclus dans la mêmecontextPaths
. J'ai modifié le script Ant pour exclure les autres classes du package j'étais en ajoutant, que cela a résolu le problème.