Nous utilisons JAXB 2.1 depuis longtemps dans notre système. Nous avons une plate-forme qui est construite avec Ant et génère un tas de paquets qui sont déployés dans un environnement d'exécution OSGi. Nous utilisons Java SE 6.Deux classes ont le même nom de type XML "objectFactory"
Nous utilisons JAXB pendant le processus de construction pour générer des types de données à partir de différents schémas. Ces classes sont empaquetées dans les bundles et utilisées à l'exécution pour sérialiser/désérialiser le contenu. En outre, nous utilisons JAXB dans notre plate-forme en cours d'exécution pour générer des types de données à partir d'autres schémas fournis par l'utilisateur (c'est une sorte de plate-forme MDA).
Dans l'environnement d'exécution OSGi, nous avons un ensemble qui contient les fichiers JAXB et exporte les packages nécessaires. Nous créons une instance JAXBContext avec le chemin de contexte de toutes les usines d'objets générées, ainsi nous pouvons marshall/unmarshall tous nos types de données. Cela a fonctionné jusqu'ici mais maintenant nous essayons de mettre à niveau vers la dernière version stable de JAXB (2.2.4) et nous avons des problèmes essayant de créer le contexte dans l'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 nom de type XML « ObjectFactory » est imprimé pour chacune des usines d'objets générés au cours du processus de construction.
Nous avons vu plusieurs messages dans SO avec la même erreur mais s'appliquant aux types générés, pas à la fabrique d'objets. Nous pensons que JAXB peut ne pas identifier la classe ObjectFactory en tant que fabrique d'objets mais en tant que type de données.
Une possibilité est que nous utilisions la version interne de JAXB en Java 6, nous avons donc décidé d'utiliser la propriété système -Djava.endorsed.dirs et 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 ne fonctionne toujours pas.
Nous pensons que le problème pourrait être que nous utilisons une version différente de JAXB dans le runtime OSGi et dans le processus de construction, donc le code généré n'est pas compatible. Mais peut-être avons-nous tort et il y a un autre problème.
Avez-vous des idées?
Merci d'avance.
(Modifier: plus de détails sur ce sujet)
Nous créons la 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 toutes nos usines d'objets 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 le post Aaron)
J'ai débogué tous les internes de JAXBContextImpl et le fait est que JAXBContextImpl essaie d'obtenir les informations de type de nos classes ObjectFactory, ce qui est faux. En fait, dans com.sun.xml.internal.bind.v2.model.impl.ModelBuilder: 314, l'appel getClassAnnotation() renvoie null mais lorsque je vois l'instance, je peux voir l'annotation XmlRegistry.Le fait est que, à ce stade, XmlRegistry.class.getClassLoader() renvoie null, mais si j'exécute ((Class) c) .getAnnotations() [0] .annotationType(). GetClassLoader() il retourne le classLoader du bundle OSGi "lib.jaxb" qui contient mes jarres JAXB, ce qui est correct. Donc, je suppose que nous chargeons en même temps deux versions différentes de XmlRegistry, l'une du JDK et l'autre des JARB JAVA 2.2.4. La question est: pourquoi? Et, encore plus, au lieu de charger toutes ces classes com.sun.xml.internal. * (Comme JAXBContextImpl), ne pas charger et exécuter com.sun.xml.bind.v2.runtime.JAXBContextImpl à partir de JAXB pots? Au cours du processus de débogage, je peux voir qu'il fait des choses avec réflexion, mais je ne comprends pas pourquoi cela le fait.
Utilisation de Java SE 6 Je vous recommande d'utiliser la dernière version de correctif de votre JAXB impl prenant en charge JAXB 2.1 sauf si vous utilisez une fonctionnalité JAXB 2.2 particulière. –
Désolé que je n'ai pas mentionné cela. La raison de la mise à niveau vers JAXB 2.2.4 est que nous sommes en train de mettre à jour notre version de JAX-WS vers la version 2.2.5 et cela dépend de cette version de JAXB (http://jax-ws.java.net/2.2.5/docs/ ReleaseNotes.html). Sinon, nous pourrions utiliser JAXB 2.1. – Denian
Il semble que votre impl JAXB traite par erreur 'ObjectFactory' en tant que classe de domaine. Cela est probablement dû au fait que l'annotation '@ XmlRegistry' n'est pas reconnue en raison d'une différence de' ClassLoader' entre vos classes de domaine et l'implémentation JAX-WS. Créez-vous le 'JAXBContext' directement ou l'implémentation de JAX-WS le fait-elle? –