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 заканчивается всеми типами из зависимых модулей (что я связываю, чтобы избежать с помощью эпизодов).
Если вы хотите увидеть полные файлы 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:
- https://java.net/jira/browse/JAXB-1044
- https://java.net/jira/browse/JAXB-1045
- https://java.net/jira/browse/JAXB-1046
Эти проблемы вызывают проблемы, когда каталог и файлы привязки используются вместе. Это было также причиной того, что разрешение артефактов 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 каталога предлагает больше возможностей.
Надеюсь, поможет.