52 votes

Pourquoi JAXB ne trouve-t-il pas mon jaxb.index lorsqu'il est exécuté dans Apache Felix ?

C'est juste là, dans le paquet qu'il devrait indexer. Pourtant, quand j'appelle

JAXBContext jc = JAXBContext.newInstance("my.package.name");

J'obtiens une JAXBException disant que

"mon nom de paquet" ne contient pas ObjectFactory.class ou jaxb.index.

bien qu'il contienne les deux.

Ce qui fonctionne, mais qui n'est pas tout à fait ce que je veux, c'est

JAXBContext jc = JAXBContext.newInstance(my.package.name.SomeClass.class);

Cette question, posée par d'autres personnes, apparaît sur un certain nombre de listes de diffusion et de forums, mais ne semble pas recevoir de réponse.

Je l'exécute sous OpenJDK 6, j'ai donc récupéré les paquets sources et j'ai intégré mon débogueur dans la bibliothèque. Il commence par chercher jaxb.properties, puis cherche les propriétés du système et ne trouvant ni l'un ni l'autre, il essaie de créer le contexte par défaut en utilisant com.sun.internal.xml.bind.v2.ContextFactory. C'est là que l'exception est levée (à l'intérieur de ContextFactor.createContext(String ClassLoader, Map) ), mais je ne peux pas voir ce qui se passe car la source n'est pas là.

ETA :

A partir du code source de ContentFactory, j'ai trouvé aquí Dans le cas de l'utilisation d'une carte de crédit, c'est probablement la partie du code qui ne fonctionne pas comme prévu :

/**
 * Look for jaxb.index file in the specified package and load it's contents
 *
 * @param pkg package name to search in
 * @param classLoader ClassLoader to search in
 * @return a List of Class objects to load, null if there weren't any
 * @throws IOException if there is an error reading the index file
 * @throws JAXBException if there are any errors in the index file
 */
private static List<Class> loadIndexedClasses(String pkg, ClassLoader classLoader) throws IOException, JAXBException {
    final String resource = pkg.replace('.', '/') + "/jaxb.index";
    final InputStream resourceAsStream = classLoader.getResourceAsStream(resource);

    if (resourceAsStream == null) {
        return null;
    }

De mon précédent expérience Je suppose que cela a à voir avec les mécanismes de chargement des classes du conteneur OSGi dans lequel il est exécuté. Malheureusement, je suis encore un peu dépassé par les événements.

60voto

Hanno Fietz Points 8685

Bon, il a fallu creuser un peu, mais la réponse n'est pas si surprenante ni même si compliquée :

JAXB ne peut pas trouver jaxb.index, car par défaut, newInstance(String) utilise le chargeur de classes du thread courant (tel que retourné par Thread.getContextClassLoader() ). Cela ne fonctionne pas dans Felix, car les bundles OSGi et les threads du framework ont des chargeurs de classes séparés.

La solution est d'obtenir un chargeur de classe approprié et d'utiliser newInstance(String, ClassLoader) . J'ai obtenu un chargeur de classe approprié à partir de l'une des classes du paquet qui contient jaxb.index un choix judicieux pour des raisons de flexibilité est probablement ObjectFactory :

ClassLoader cl = my.package.name.ObjectFactory.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance("my.package.name", cl);

Peut-être que vous pourriez aussi accéder au chargeur de classe que le Bundle est utilisée, mais je n'ai pas trouvé comment, et la solution ci-dessus me semble sûre.

6voto

Chaits Points 36

J'ai rencontré un problème similaire avec le projet sur lequel je travaille. Après avoir lu http://jaxb.java.net/faq/index.html#classloader J'ai réalisé que JAXBContext n'est pas capable de trouver le paquet contenant jaxb.index.

Je vais essayer de rendre cela aussi clair que possible.

Nous avons

Bundle A
   -- com.a
      A.java
        aMethod()
        {
            B.bMethod("com.c.C");
        }
MANIFEST.MF
Import-Package: com.b, com.c         

Bundle B
   -- com.b
      B.java
        bmethod(String className)
        {
            Class clazz = Class.forName(className);
        }

Export-Package: com.b

Bundle C
   -- com.c
      C.java
        c()
        {
            System.out.println("hello i am C");
        }

Export-Package: com.c

En relation avec JAXB . la classe B est JAXBContext et bMethod est newInstance()

Si vous êtes familier avec les restrictions des paquets OSGi, il doit être très clair maintenant que Ensemble B n'importe pas le paquet com.c i.e classe C es non visible a classe B donc il ne peut pas instancier C.

La solution serait de passer un ClassLoader à bMéthode. Ce ClassLoader doit provenir d'un le paquet qui importe com.c . Dans ce cas, nous pouvons passer A.class.getClassLoader() depuis le paquet A importe com.c

J'espère que cela vous a été utile.

1voto

wierzbiks Points 11

Si vous utilisez maven dans votre projet, alors utilisez simplement cette bibliothèque :

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-osgi</artifactId>
    <version>2.2.7</version>
</dependency>

Il est créé pour le serveur Glasfish mais fonctionne également avec Tomcat (vérifié). Avec cette bibliothèque, vous pouvez facilement utiliser JAXB avec des bundles OSGI.

0voto

kd304 Points 8369

Edit 2 :

J'ai eu une fois un étrange problème similaire de chargement de classe dans mon application. Si je l'exécutais comme une application normale, tout allait bien, mais lorsque je l'invoquais comme un service Windows, elle commençait à échouer avec des ClassNotFoundExceptions. L'analyse a montré que les threads ont leurs classloaders comme nuls en quelque sorte. J'ai résolu le problème en définissant le SystemClassLoader sur les threads :

// ...
thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
thread.start();
// ...

Je ne sais pas si votre conteneur permet ce genre de changement.

0voto

Zoltan Points 46

Je viens de rencontrer ce problème. Pour moi, la solution a été d'utiliser le JRE d'IBM au lieu de celui d'Oracle. Il semble que l'implémentation de JAXB soit plus favorable à OSGI dans celui-ci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X