Зачем нужен gradle-download-xml-plugin?
Обзор
Gradle Download Xml позволяет скачивать WSDL,XSD схемы со всеми зависимостями.
Краткое описание проблемы
Для генерации java классов по wsdl-схеме существуют различные утилиты: xjc
, wsimport
и др.
Утилитам дается URL на схему, по которой они генерируют классы. Обычно это выглядит так:
xjc -wsdl http://my-site-name.ru/MyService.wsdl
Иногда, ошибочно, вместо валидного URL на ресурс, в аттрибуте schemaLocation
, указываются локальные пути к файлам.
И данный способ генерации классов оказывается невозможным.
Пример невалидной схемы
<!-- ... -->
<xsd:import
schemaLocation="user.xsd"
namespace="http://example/user">
</xsd:import>
<!-- ... -->
Как решить проблему вручную (без плагина)?
- Скачиваем WSDL
- Скачиваем все xsd из импортов (рекурсивно)
- Исправляем schemaLocation’ы по необходимости
xjc -wsdl local-file.wsdl
Если таких xsd файлов много и иерархия import’ов очень большая - делать это руками довольно долго.
Как выглядит решение проблемы gradle плагином ru.d10xa.download-xml
Плагин добавляет расширение downloadXml к задачам в gradle.
downloadXml {
src(['http://my-site-name.ru/MyService.wsdl'])
dest buildDir
namespaceToFile([
'http://example/ws' : 'service.wsdl',
'http://example/user' : 'xsd/user.xsd',
])
locations {
malformedLocationHandler {
"http://example/$it"
}
}
}
Во время первого запуска задачи, не обязательно указывать namespaceToFile
.
Gradle напишет в консоль нэймспэйсы, которые он нашел. Достаточно вставить их в блок namespaceToFile([])
и заменить расширения xml на wsdl и xsd, соответственно (необходимо для генерации классов).
Пример плохого веб сервиса
О процессе создания SOAP веб сервиса можно почитать на spring.io. В этом руководстве показана реализация веб сервиса использующего один файл xsd.
Исходники примера можно посмотреть на гитхабе
Особенности примера:
- Используем gradle для сборки
- У нас есть 3 xsd схемы. WSDL генерируется при запуске сервера.
- Сервис доступен по URL
$baseUrl/ws/countries.wsdl
- В проекте схемы находятся в директории
src/main/resources/static
. К ним можно обратиться как к обычным статическим ресурсам $baseUrl/country.xsd, $baseUrl/currency.xsd
В jdk8 по умолчанию отключен доступ ко вложенным схемам. Включить эту возможность можно определив системную переменную javax.xml.accessExternalSchema = all.
- all - дает доступ к внешним схемам по всем протоколам.
Создадим файл $JAVA_HOME/jre/lib/jaxp.properties
со следующим содержимым:
javax.xml.accessExternalSchema = all
Подробнее о доступе можно почитать в документации
Запускаем веб сервис
Клонируем проект в локальную папку и запустим (порт 8081 можно заменить на любой свободный)
git clone https://github.com/d10xa/spring-boot-ws-bad-practice.git
cd spring-boot-ws-bad-practice
./gradlew bootRun -Pserver.port=8081
Используем плагин
Перейдем в директорию download-xml-plugin-example (в проекте, рядом с веб сервисом). В файле build.gradle описаны задачи:
- download - скачивает схемы в директорию build
- xjc - запускает ant задачу, генерирует классы. Классы создаются в директории
generated
- build - собирает jar
Выполнив команду ./gradlew build
, мы скачаем схемы, сгенерируем классы и соберем jar.
cd download-xml-plugin-example
./gradlew build -Pbase.url=http://localhost:8081
Ограниченный доступ к схемам
Иногда для доступа к схемам используется базовая HTTP-авторизация. Для этого в расширение downloadXml добавим username, password:
username 'foo'
password 'bar'