2009-06-25 41 views
50

Está justo allí, en el paquete que debería indexar. Aún así, cuando llamo¿Por qué JAXB no puede encontrar mi jaxb.index cuando se ejecuta dentro de Apache Felix?

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

me siento un JAXBException diciendo que

"my.package.name" doesnt contiene ObjectFactory.class o jaxb.index

aunque contiene ambos.

Lo que funciona, pero no es exactamente lo que quiero, es

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

Esta pregunta de varias otras personas aparece en bastantes listas de correo y foros, pero aparentemente no obtener respuestas.

Estoy ejecutando esto en OpenJDK 6, así que obtuve los paquetes fuente y puse mi depurador en la biblioteca. Comienza buscando jaxb.properties, luego busca las propiedades del sistema y, si no puede encontrarlas, intenta crear el contexto predeterminado utilizando com.sun.internal.xml.bind.v2.ContextFactory. Allí, se lanza la excepción (dentro de ContextFactor.createContext(String ClassLoader, Map)), pero no puedo ver qué está sucediendo porque la fuente no está aquí.

ETA:

A juzgar por el código fuente de contentfactory, he encontrado here, esta es probablemente la pieza de código que no funciona según lo previsto:

/** 
* 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; 
    } 

Desde mi previousexperience, Supongo que esto tiene que ver con los mecanismos de carga de clases del contenedor OSGi en el que se está ejecutando. Desafortunadamente, todavía estoy un poco fuera de mi alcance aquí.

+0

Quise decir por favor, publique el seguimiento de la pila de excepción. – akarnokd

+0

La publicación ya se está haciendo un poco larga, pero ya he rastreado el origen de la excepción, acabo de publicar esto arriba. –

Respuesta

57

OK, esto tomó bastante excavación, pero la respuesta no es tan sorprendente y ni siquiera es tan complicado:

JAXB no puede encontrar jaxb.index, porque por defecto, newInstance(String) utiliza el cargador de clases del hilo actual (como se devuelve por Thread.getContextClassLoader()). Esto no funciona dentro de Felix, porque los paquetes OSGi y los subprocesos del framework tienen cargadores de clases separados.

La solución es obtener un cargador de clases adecuado de alguna parte y usar newInstance(String, ClassLoader).Tengo un cargador de clase adecuada de una de las clases del paquete que contiene jaxb.index, una buena opción por razones de flexibilidad, probablemente es ObjectFactory:

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

Tal vez también se puede conseguir en el cargador de clases que la instancia Bundle está utilizando , pero no pude entender cómo, y la solución anterior parece segura para mí.

+1

Esto en realidad resulta ser un problema bastante desagradable en entornos OSGi cuando está utilizando librerías que no están diseñadas para OSGi y hace suposiciones sobre el cargador de clases que obtienen. Este es el motivo por el cual las personas afirman que Eclipselink es el único proveedor de JPA que trabaja en OSGi (no sé si eso sigue siendo cierto). –

+1

ContextClassLoader; Al configurar el cargador de clases, primero debe verificar si ya hay uno configurado, de ser así, guárdelo como variable local y luego reinícielo en un bloque finally después de llamar a JAX; no sabe qué más está usando los hacks del cargador de clases. .. – earcam

+0

¿Hay algún artículo de Jira relacionado con este problema? tropezamos aquí y puedo dar fe de que la solución funciona, solo me pregunto si este es un tema desconocido del proyecto apache-felix – Monachus

0

Edición 2:

Una vez tuve un problema de carga de clases extraña similar en mi solicitud. Si lo ejecutaba como una aplicación normal, todo estaba bien, pero cuando lo invoqué como un Servicio de Windows, comenzó a fallar con ClassNotFoundExceptions. El análisis mostró que los hilos tienen sus cargadores de clases como nulos de alguna manera. He resuelto el problema mediante el establecimiento de la SystemClassLoader en las roscas:

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

No sabe si su envase permite que este tipo de cambio, aunque.

+0

Bueno, podría ser (no sé), pero me parece que debería haber algún lugar donde pueda poner el archivo para que el cargador de clases utilizado lo encuentre. –

6

Me enfrenté a un problema similar con el proyecto en el que estoy trabajando. Después de leer http://jaxb.java.net/faq/index.html#classloader me di cuenta de que JAXBContext no puede encontrar el paquete que contiene jaxb.index.

Intentaré dejar esto lo más claro posible.

Tenemos

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 

Relacionar a JAXB. clase B es JAXBContext y bMethod es newInstance()

Si está familiarizado con las restricciones de paquetes OSGi, entonces debe ser muy claro ahora que Paquete B no está Importación paquete com.c es decir clase C se no visible a clase B por lo tanto no puede crear una instancia C.

La solución sería pasar un ClassLoader a bMethod. Este ClassLoader debe provenir de un paquete que está importando com.c. En este caso podemos pasar A.class.getClassLoader() desde paquete A es la importación de com.c

esperanza era útil.

0

Acabo de encontrarme con este problema. Para mí, la solución fue utilizar JRE de IBM en lugar de Oracle. Parece que la implementación de JAXB es más amigable con OSGI en eso.

4

Para el mismo problema, lo resolví poniendo manualmente el paquete en la importación.

1

Si está utilizando experto en su proyecto, a continuación, sólo tiene que utilizar esta biblioteca:

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

Es creado para el servidor glasfish sino también trabajando con Tomcat (comprobado). Con esta biblioteca puede usar JAXB fácilmente con paquetes OSGI.

+0

funcionó muy bien para mí – user617136

0

he resuelto con éxito esto añadiendo el paquete de mis clases generadas contienen ObjectFactory a la parte de mi definición <Private-Package> paquete, además de org.jvnet.jaxb2_commons.*

-1

Mi solución fue:

JAXBContext contexto = JAXBContext.newInstance (nueva Clase [] {"my.package.nombre "});

O

JAXBContext context = JAXBContext.newInstance (nuevo [] {class.getName (Clase)});

O

una solución completa:

public static <T> T deserializeFile(Class<T> _class, String _xml) { 

     try { 

      JAXBContext context = JAXBContext.newInstance(new Class[]{_class}); 
      Unmarshaller um = context.createUnmarshaller(); 

      File file = new File(_xml); 
      Object obj = um.unmarshal(file); 

      return _class.cast(obj); 

     } catch (JAXBException exc) { 
      return null; 
     } 
    } 

funciona al 100%

0

Puede haber otro escenario que puede dar este problema.

Al instalar e iniciar un paquete que exportan el paquete que contiene el jaxb.index o objectFactory.java

Entonces, por favor asegúrese de que los paquetes que importan las clases se detienen o señalando el nombre del paquete correcto.

También puedes ver las declaraciones de exportación e importación en el pom.xml

Frente problema similar en un recipiente ServiceMix (karaf) osgi

0

Para mí el problema es que una prueba de unidad que no estaba relacionado con el módulo que he desarrollado no tenía una dependencia en él pom.xml a mi módulo. El UT todavía reconoció mi módulo debido a la obtención de la lista de paquetes del archivo de configuración compartido.

Cuando se ejecuta la UT que no compilar el nuevo módulo por lo que no generó la ObjectFactory.java por lo tanto, he recibido el error a pesar de que cuando compilé el módulo pude ver el ObjectFactory.java

agregó la siguiente dependencia:

<dependency> 
    <groupId>com.myCompany</groupId> 
    <artifactId>my-module-name</artifactId> 
    <version>${project.version}</version> 
    <scope>test</scope> 
</dependency> 
Cuestiones relacionadas