java-класс, использующий jaxb api, который не работает в jira с: Поставщик com.sun.xml.bind.v2.ContextFactory not found - PullRequest
5 голосов
/ 22 июня 2010

Я пишу плагин для Jira, который включает в себя анализ XML-документов.Я использую JAXB для этого (XML для pojos и наоборот). Итак, есть класс, который генерирует XML из pojos, используя JAXB.это выглядит как ...

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();

  } 
}

Упомянутые пакеты будут поставляться с дистрибутивом JDK (rt.jar).так что я не передавал ничего другого для запуска класса.

, когда я запускаю его из командной строки, используя 'java', он работает правильно.но, когда я упаковываю его как банку и помещаю как плагин в Jira, происходит сбой со следующей ошибкой

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)

Это на той же машине.Единственное отличие, которое я мог видеть, в отличие от запуска из командной строки, когда я развернул его в Jira, он вызывает не main (), а m1 () путем создания экземпляров.это на одной машине.я не знаю, как Jira запускает приложение (так как я запускаю из командной строки).

Ответы [ 3 ]

6 голосов
/ 08 мая 2012

Я знаю, что это своего рода поздний ответ, но для людей, приземляющихся здесь, есть несколько вещей, не упомянутых в других постах, которые важны при разработке плагинов для JIRA (и других продуктов Atlassian).

Первый JIRA, точнее Atlassian, имеет два типа плагинов, см. Различия между плагинами1 и плагинами2

Поскольку это было ClassNotFoundException (и JIRA v4.0.1), я предполагаю, что подключаемый модуль представляет собой Plugin2, который может использоваться в JIRA v4 и более поздних версиях.

Начиная с JIRA v4, JIRA действует как контейнер OSGi, и, следовательно, Plugin2 является пакетом OSGi. В OSGi каждый пакет имеет свой собственный набор загрузчиков классов. Это позволяет различным пакетам иметь разные версии одних и тех же jar-файлов и, в числе прочего, оперативно развертываться. Однако выгода заключается в том, что не все пакеты из JDK по умолчанию доступны для этих загрузчиков классов. Это объясняется в разделе Плагины, комплекты и OSGi на веб-странице Atlassian Developers . Более подробное описание можно найти в блоге Отображение пути к загрузочному классу в OSGi в Springsource. Второй абзац там даже имеет заголовок NoClassDefFoundError: com.sun…

Так много для теории.

При разработке подключаемого модуля для JIRA с помощью Atlassian SDK Maven используется за кулисами, см. Документация по Atlassian Plugin SDK . Так что в проекте плагина будет pom.xml. Чтобы включить пакеты JDK в плагин, можно добавить тег <SystemProperties> к maven-jira-plugin (для других продуктов Atlassian есть соответствующий плагин maven), и установите свойство bootdelegation (и вы можете установить java в 1.6 для maven-compiler-plugin ):

...
<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>
...

Указанные пакеты будут доступны для пакета. Имейте в виду, однако, что делегирование загрузки не является решением всех проблем и должно использоваться только с ограничениями. Узнайте больше на Boot Delegation и Избегайте взлома Classloader .

Под зависимостями можно установить jaxb-api нужную версию:

...
<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>
...

Не всегда необходимо явно иметь зависимость от jaxb-api . Например, плагин atlassian-rest-common выше имеет транзитивную зависимость от jaxb-api . Важно понимать настройку scope . Посмотрите на Установка инструкций OSGi Manifest в вашем плагине (на той же странице, что и Плагины, комплекты и OSGi , но далее).

Заинтригованный может узнать больше на Спецификации OSGi Alliance и Сообщество OSGi Wiki .

5 голосов
/ 24 июня 2010

Наконец я смог выяснить причину.

При загрузке плагинов в JIRA (Феликс) задействовано много ClassLoaders.который не будет делегировать 'bootstrap' ClassLoader.И, следовательно, проблема.

Чтобы узнать, какой ClassLoader загрузил класс JAXBContext, используйте JAXBContext.class.getClassLoader(), который напечатает некоторый Феликс ClassLoader.

Он загружал класс из jaxb-api.jar вместо того, чтобы полагаться на rt.jar, но они реализовали классы немного по-другому.rt.jar версия использует com.sun.xml.bind.internal.v2.ContextFactory, где jaxb-api версия использует com.sun.xml.bind.v2.ContextFactory.

Я могу решить проблему, используя перегруженный метод JAXB, который примет другой параметр как ClassLoader.

Прошло довольно много времени.Но я удивлен внутренними деталями и моим невежеством

0 голосов
/ 23 июня 2010

Пакет com.sun.xml.bind является частью JAXB RI (http://jaxb.dev.java.net/),, так что вы, вероятно, где-то в своем пути к классам.

Java6 имеет свою собственную версию JAXB, включенную в пакет com.sun.xml.internal.bind, поэтому вам обычно не требуется RI в Java6.

RI может , созданный для работы с Java6, но это тяжелое сражение, и обычно заканчивается такой проблемой.

...