Maven Jaxb генерирует ошибки при компиляции модуля, который зависит от нескольких модулей

У меня есть проект Eclipse Maven, состоящий из нескольких модулей, некоторые из которых содержат схемы XML, для которых я хочу сгенерировать классы (используя Jaxb). План моего проекта выглядит следующим образом:

schemas\core (pom)
schemas\core\types (jar)
schemas\vehicle (pom)
schemas\vehicle\automobile (jar)
schemas\vehicle\civic (jar)

Проекты, которые содержат схемы:

schemas\core\types (xsd\types.xsd)
schemas\vehicle\automobile (xsd\automobile.xsd)
schemas\vehicle\civic (xsd\civic.xsd)

Некоторые из модулей содержат схемы, которые импортируют схемы из других модулей:

automobile.xsd imports types.xsd
civic.xsd imports types.xsd, automobile.xsd

Поскольку схемы расположены в разных проектах, я использую средство определения каталога classpath вместе с файлами каталогов для определения местоположения схем.

Автомобильный проект зависит от схем в проекте типов. Вот запись в файле каталога (catalog.xml):

<rewriteSystem systemIdStartString="http://schemas/core/types/" rewritePrefix="classpath:xsd/" />

Обратите внимание на использование classpath:xsd/, чтобы указать каталогизатору каталога найти схемы в classpath.

Я также использую эпизоды, чтобы предотвратить повторное создание классов типов внутри автомобильного проекта. Вот фрагмент из моего pom.xml:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.3</version>
    <configuration>
        <episodes>
            <episode>
                <groupId>schemas.core</groupId>
                <artifactId>types</artifactId>
                <version>1.0-SNAPSHOT</version>
            </episode>
        <episodes>
        <catalog>src/main/resources/catalog.xml</catalog>
        <catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
        <extension>true</extension>
        ....

Когда я запускаю mvn clean install на автомобильный проект, все работает, файл. Схема types.xsd разрешается в пути к классам, и классы в конечном итоге генерируются.

Там, где я сталкиваюсь с проблемами, я пытаюсь скомпилировать проект civic.

Гражданский проект зависит от обоих типов:.xsd и automotive.xsd. Я использую файл каталога (catalog.xml), чтобы определить расположение схем:

<rewriteSystem systemIdStartString="http://schemas/core/types/" rewritePrefix="classpath:xsd/" />
<rewriteSystem systemIdStartString="http://schemas/vehicle/automobile/" rewritePrefix="classpath:xsd/" />

Я использую эпизоды, чтобы предотвратить повторную генерацию классов. Вот фрагмент из pom.xml для civic:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.3</version>
    <configuration>
        <episodes>
            <episode>
                <groupId>schemas.core</groupId>
                <artifactId>types</artifactId>
                <version>1.0-SNAPSHOT</version>
            </episode>
            <episode>
                <groupId>schemas.vehicle</groupId>
                <artifactId>automobile</artifactId>
                <version>1.0-SNAPSHOT</version>
            </episode>
        </episodes>
        <catalog>src/main/resources/catalog.xml</catalog>
        <catalogResolver>org.jvnet.jaxb2.maven2.resolver.tools.ClasspathCatalogResolver</catalogResolver>
        <extension>true</extension>
        ...

Когда я пытаюсь запустить mvn clean install для гражданского проекта, у меня возникают проблемы. Он жалуется на неспособность разрешить общедоступные / системные идентификаторы. Вот некоторые сообщения об ошибках, которые я получаю:

Could not resolve publicId [null], systemId [jar:file:/_m2repository/schemas/vehicle/automobile/1.0-SNAPSHOT/automobile-1.0-SNAPSHOT.jar!http://schemas/core/types/types.xsd]
[ERROR] Error while parsing schema(s).Location [].
com.sun.istack.SAXParseException2; 
IOException thrown when processing "jar:file:/_m2repository/schemas/vehicle/automobile/1.0-SNAPSHOT/automobile-1.0-SNAPSHOT.jar!http://schemas/core/types/types.xsd".
Exception: java.net.MalformedURLException: no !/ in spec.
....

По какой-то причине он не может найти types.xsd при попытке проанализировать файл JAR из автомобильного проекта.

Кто-нибудь знает, почему это может происходить?

Спасибо.

Примечание. Я экспериментировал с привязкой, чтобы заставить вещи работать, и я нашел один способ. Если я удаляю эпизоды из файла pom.xml, я больше не получаю сообщение об ошибке, однако, проект civic заканчивается всеми типами из зависимых модулей (что я связываю, чтобы избежать с помощью эпизодов).

Гражданский проект генерирует Java-классы

Если вы хотите увидеть полные файлы catalog.xml и pom.xml для каждого проекта, перейдите по следующим ссылкам:

типы: http://pastebin.com/Uym3DY6X

автомобиль: http://pastebin.com/VQM4MPuW

Гражданское: http://pastebin.com/eGSVGwmE

3 ответа

Решение

У меня та же проблема. Схема C импортирует B и A, B импортирует A. Формирование источников для A, работает, B также хорошо, а для C появляется MalformedUrlException.

Я все еще исследую ошибку, но обходной путь должен использовать systemIdSuffix (Oasis spec 1.1), чтобы соответствовать systemId и переписать его. Вам нужно сделать следующее:

Удалите элемент catalogResolver из конфигурации плагина в poms.

Замените содержимое файла каталога для проекта "автомобиль" следующим:

<systemSuffix systemIdSuffix="types.xsd" uri="maven:schemas.core:types!/types.xsd"/>

Замените содержимое файла каталога для проекта 'civic' следующим:

<systemSuffix systemIdSuffix="types.xsd" uri="maven:schemas.core:types!/types.xsd"/>
<systemSuffix systemIdSuffix="automobile.xsd" uri="maven:schemas.vehicle:automobile!/automobile.xsd"/>

Дайте мне знать, если это работает для вас.

Автор maven-jaxb2-plugin Вот.

Я только что выпустил 0.10.0 версия maven-jaxb2-plugin, В этом выпуске исправлена проблема MAVEN_JAXB2_PLUGIN-82, связанная с указанными проблемами.

Это было на самом деле НЕ ошибка в maven-jaxb2-plugin, но проблема (или, лучше сказать, несколько проблем) в самом XJC:

Эти проблемы вызывают проблемы, когда каталог и файлы привязки используются вместе. Это было также причиной того, что разрешение артефактов Maven в некоторых случаях работало некорректно.

В выпуске 0.10.0 я реализовал обходные пути для JAXB-1044 и JAXB-1045. Я попытаюсь доставить свои исправления в XJC с помощью запросов на извлечение, но вы знаете, я не уверен, когда / если парни Oracle примут мои PR.

в maven-jaxb2-plugin Я теперь реализовал довольно надежные обходные пути. Смотрите этот тестовый проект здесь:

https://github.com/highsource/maven-jaxb2-plugin/tree/master/tests/MAVEN_JAXB2_PLUGIN-82

Это делает именно то, что вы хотите: разрешает схему через каталог И преобразователь Maven в ресурс из другого артефакта. В основном это переписывание:

REWRITE_SYSTEM "http://www.ab.org" "maven:org.jvnet.jaxb2.maven2:maven-jaxb2-plugin-tests-MAVEN_JAXB2_PLUGIN-82-a:jar::!"

сейчас работает нормально.

В случае проблем сделать mvn -X и проверьте вывод, вы также увидите операторы каталога в журнале. Это может дать вам подсказки, что не работает.

Вот еще один проект, который использует схемы, привязки и сам каталог из одного центрального артефакта:

https://github.com/highsource/w3c-schemas

Отрывки из ПОМ:

                    <schemas>
                        <schema>
                            <url>http://www.w3.org/1999/xlink.xsd</url>
                        </schema>
                    </schemas>

                    <schemaIncludes/>
                    <bindings>
                        <binding>
                            <dependencyResource>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>w3c-schemas</artifactId>
                                <resource>globalBindings.xjb</resource>
                                <version>${project.version}</version>
                            </dependencyResource>
                        </binding>
                    </bindings>
                    <catalogs>
                        <catalog>
                            <dependencyResource>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>w3c-schemas</artifactId>
                                <resource>catalog.cat</resource>
                                <version>${project.version}</version>
                            </dependencyResource>
                        </catalog>
                    </catalogs>

Каталог:

REWRITE_SYSTEM "http://www.w3.org" "maven:org.hisrc.w3c:w3c-schemas:jar::!/w3c"

Переплет:

<jaxb:bindings schemaLocation="http://www.w3.org/1999/xlink.xsd" node="/xs:schema">
    <jaxb:schemaBindings>
        <jaxb:package name="org.hisrc.w3c.xlink.v_1_0"/>
    </jaxb:schemaBindings>
</jaxb:bindings>

Итак, как все это работает:

  • Схемы, а также каталог и глобальные привязки хранятся в центральном артефакте. w3c-schemas,
  • Проект хочет скомпилировать URL http://www.w3.org/1999/xlink.xsd,
  • Каталог переписывает этот URL в systemId maven:org.hisrc.w3c:w3c-schemas:jar::!/w3c/1999/xlink.xsd, (Есть /w3c/1999/xlink.xsd ресурс в w3c-schemas банка).
  • Затем этот systemId разрешается моим распознавателем каталога Maven (доставлен мой maven-jaxb2-plugin) в "реальный" URL, который будет некоторым jar:... URL, указывающий на ресурс внутри w3c-schemas JAR артефакт в локальном хранилище.
  • Таким образом, схема не загружается из Интернета, а берется с локального ресурса.
  • Обходной путь сохраняет "исходные" системные идентификаторы, поэтому вы можете настроить схему, используя ее исходный URL. (Разрешенный systemId не будет удобен.)
  • Файл каталога и файл глобальных привязок будут одинаковыми для всех отдельных проектов, поэтому они также помещаются в центральный артефакт и на него ссылаются с помощью dependencyResource,

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

Я изменил эти проекты двумя способами:

1) Иметь проект A с двумя пространствами имен и файлом локального каталога. Имейте проект B в зависимости от этого, используя эпизод A в B.

2) Иметь проект A, проект B и проект C. B полагается на A, а C полагается на B.

В обоих случаях я получил то же исключение, что и вы. Но я начал понимать в ситуации 2, что происходит.

Это исключение: com.sun.istack.SAXParseException2; Исключение IOException при обработке "jar: file: /Users/sjaak/.m2/repository/org/tst/b-working/1.0/b-working-1.0.jar! http://www.a1.org/a1/a1.xsd ". Исключение: java.net.MalformedURLException: нет!/ В спец.

Таким образом, он пытается разрешить пространство имен http://www.a1.org/a1/a1.xsd относительно проекта B при создании проекта C. Я проследил проблему до com.sun.tools.xjc.reader.internalizerAbstractReferenceFinderImpl, метод StartElement.

Решением, которое я использую, является адаптация org.jvnet.jaxb2.maven2:maven-jaxb2-plugin. Я использовал их MavenCatalogResolver (по умолчанию, как указано выше) и сделал небольшое изменение, просто не предлагая весь systemId: jar: file: /Users/sjaak/.m2/repository/org/tst/b-working/1.0/ б-рабочая 1.0.jar! http://www.a1.org/a1/a1.xsd, но вместо этого используйте шаблон, который предлагает только часть после восклицательного знака для разрешения.

Вот код:

package org.jvnet.jaxb2.maven2.resolver.tools;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;

import org.jvnet.jaxb2.maven2.DependencyResource;
import org.jvnet.jaxb2.maven2.DependencyResourceResolver;

import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MavenCatalogResolver extends
        com.sun.org.apache.xml.internal.resolver.tools.CatalogResolver {

    private final static Pattern PTRN = Pattern.compile("^jar:file:(.*).jar!(.*)$");

    public static final String URI_SCHEME_MAVEN = "maven";
    private final DependencyResourceResolver dependencyResourceResolver;
    private final CatalogManager catalogManager;

    public MavenCatalogResolver(CatalogManager catalogManager,
            DependencyResourceResolver dependencyResourceResolver) {
        super(catalogManager);
        this.catalogManager = catalogManager;
        if (dependencyResourceResolver == null) {
            throw new IllegalArgumentException(
                    "Dependency resource resolver must not be null.");
        }
        this.dependencyResourceResolver = dependencyResourceResolver;
    }

    @Override
    public String getResolvedEntity(String publicId, String systemId) 
    {
        String result;
         Matcher matcher = PTRN.matcher(systemId);
         if (matcher.matches())
         {      
              result = super.getResolvedEntity(publicId, matcher.group(2));
         }
         else
         {
              result = super.getResolvedEntity(publicId, systemId);          
         }
        if (result == null) {
            return null;
        }

        try {
            final URI uri = new URI(result);
            if (URI_SCHEME_MAVEN.equals(uri.getScheme())) {
                final String schemeSpecificPart = uri.getSchemeSpecificPart();
                try {
                    final DependencyResource dependencyResource = DependencyResource
                            .valueOf(schemeSpecificPart);
                    try {
                        final URL url = dependencyResourceResolver
                                .resolveDependencyResource(dependencyResource);
                        String resolved = url.toString();
                        return resolved;
                    } catch (Exception ex) {
                        catalogManager.debug.message(1, MessageFormat.format(
                                "Error resolving dependency resource [{0}].",
                                dependencyResource));
                    }

                } catch (IllegalArgumentException iaex) {
                    catalogManager.debug.message(1, MessageFormat.format(
                            "Error parsing dependency descriptor [{0}].",
                            schemeSpecificPart));

                }
                return null;
            } else {
                return result;
            }
        } catch (URISyntaxException urisex) {

            return result;
        }
    }

}

Это на самом деле исправило мою проблему. Я буду расследовать немного больше. У меня такое ощущение, что может быть какой-то аргумент XJC, который я мог бы использовать, или, возможно, формат XML каталога предлагает больше возможностей.

Надеюсь, поможет.

Другие вопросы по тегам