clase Java usando la API JAXB fallando en JIRA con: Provider com.sun.xml.bind.v2.ContextFactory no encontrado

StackOverflow https://stackoverflow.com/questions/3093963

Pregunta

Estoy escribiendo un complemento para JIRA que implica el análisis de documentos XML. Estoy usando JAXB para hacerlo (XML a Pojos y viceversa), así que tengo una clase que genera XML de POJOS usando Jaxb. parece que...

import javax.xml.bind.*;

Class Parser {
  public void m1() {
    ...
    // code which uses classes in javax.xml.bind.*
  }

  public static void main(String args[]){
   Parser p=new Parser();
   p.m1();

  } 
}

Los paquetes mencionados vendrán con Distribución JDK (RT.JAR). Así que no he transmitido nada más para ejecutar la clase.

Cuando lo lance desde la línea de comandos usando 'java', funciona correctamente. Pero, cuando lo empaqué como un frasco y lo pongo como complemento en Jira, está fallando con el siguiente error

javax.xml.bind.JAXBException: Provider com.sun.xml.bind.v2.ContextFactory not found
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:152)
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:299)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337)

Esto está en la misma máquina. La única diferencia que pude ver es diferente al lanzamiento desde la línea de comandos, cuando la implementé en JIRA, no llama a Main () sino M1 () instanciando.

¡Me pregunto qué está pasando! Está en la misma máquina. No sé cómo JIRA lanza la aplicación (ya que estoy lanzando desde la línea de comandos).

¿Fue útil?

Solución

los com.sun.xml.bind El paquete es parte del Jaxb RI (http://jaxb.dev.java.net/), así que probablemente tengas eso en tu clase en alguna parte.

Java6 tiene su propia versión de Jaxb incluida en el com.sun.xml.internal.bind Paquete, por lo que generalmente no necesita el RI en Java6.

El RI pueden Hecho para trabajar con Java6, pero es una batalla cuesta arriba, y generalmente termina con este tipo de problema.

Otros consejos

Sé que esta es una especie de respuesta tardía, pero para las personas que aterrizan aquí hay algunas cosas no mencionadas en las otras publicaciones que son importantes al desarrollar complementos para JIRA (y otros productos atlassianos).

First Jira, o más bien Atlassian, tiene dos tipos de complementos, ver Diferencias entre complementos1 y complementos2

Dado que se trataba de ClassNotFoundException (y JIRA V4.0.1), supongo que el complemento es un complemento2, que se puede usar en JIRA V4 y más tarde.

De JIRA V4, Jira actúa como un contenedor OSGI, y por lo tanto, Plugin2 es un paquete OSGI. En OSGI, cada paquete tiene su propio conjunto de cargadores de clase. Esto permite que diferentes paquetes tengan diferentes versiones de los mismos frascos, y se despliegue en caliente, entre otras cosas. Sin embargo, la captura es que no todos los paquetes del JDK están disponibles por defecto para estos cargadores de clase. Esto se explica en Complementos, paquetes y osgi sobre el Página web de desarrolladores atlassianos. Una descripción más detallada se puede encontrar en el blog. Exponiendo la classpath de arranque en OSGI en Springsource. El segundo párrafo incluso tiene el título NoclassDeffoundError: com.sun ...

Tanto para la teoría.

Al desarrollar un complemento para Jira con el SDK Atlassian, Maven se usa detrás de escena, ver Documentación de SDK del complemento Atlassian. Por lo tanto, habrá un pom.xml en el proyecto de complemento. Para incluir paquetes JDK en el complemento, se puede agregar un <SystemProperties> Etiqueta al maven (Para otros productos Atlassian, hay un complemento Maven correspondiente) y configure el bootdelegation propiedad (y es posible que desee establecer Java en 1.6 para el maven-compilador):

...
<build>
    <plugins>
        <plugin>
            <groupId>com.atlassian.maven.plugins</groupId>
            <artifactId>maven-jira-plugin</artifactId>
            <version>3.7.3</version>
            <extensions>true</extensions>
            <configuration>
                <productVersion>${jira.version}</productVersion>
                <productDataVersion>${jira.data.version}</productDataVersion>
                <systemProperties>
                    <property>
                        <name>atlassian.org.osgi.framework.bootdelegation</name>
                        <value>sun.*,com.sun.*</value>
                    </property>
                </systemProperties>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
        ...
    </plugins>
</build>
...

Los paquetes enumerados estarán disponibles para el paquete. Sin embargo, tenga en cuenta que la delegación de arranque no es una solución de solución de todo, y solo debe usarse con restricción. Lee mas en Delegación de arranque y Evite los trucos de cargadores de clases.

Según las dependencias, se puede establecer el jaxb-api Versión necesaria:

...
<dependencies>
    <dependency>
        <groupId>com.atlassian.jira</groupId>
        <artifactId>atlassian-jira</artifactId>
        <version>${jira.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.atlassian.plugins.rest</groupId>
        <artifactId>atlassian-rest-common</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.4</version>
        <scope>provided</scope>
    </dependency>
    ...
</dependencies>
...

No siempre es necesario tener explícitamente una dependencia de jaxb-api. Por ejemplo el Atlassian-Rest-Common El complemento anterior tiene una dependencia transitiva en jaxb-api. Importante es comprender la configuración de alcance. Mirar Configuración de instrucciones de manifiesto OSGI en su complemento (misma página que Complementos, paquetes y osgi pero más abajo).

Lo intrigado puede aprender más en Especificaciones de alianza de OSGI y Wiki de la comunidad OSGI.

Finalmente pude averiguar la razón.

Hay muchos ClassLoaders involucrado al cargar los complementos en JIRA (Felix). que no delegará a 'bootstrap' ClassLoader. Y de ahí el problema.

Para saber que ClassLoader cargado el JAXBContext clase, usa JAXBContext.class.getClassLoader() que imprimirá algo de Felix ClassLoader.

Cargó la clase desde jaxb-api.jar en lugar de confiar en rt.jar Pero implementaron las clases ligeramente diferentes. rt.jar Usos de la versióncom.sun.xml.bind.internal.v2.ContextFactory dónde jaxb-api Usos de la versión com.sun.xml.bind.v2.ContextFactory.

Puedo resolver el problema utilizando el método de Jaxb sobrevalorado que tomará otro parámetro como ClassLoader.

Tomó bastante tiempo. Pero, me sorprende los detalles internos y mi ignorancia

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top