Обзор

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

Как решить проблему вручную (без плагина)?

  1. Скачиваем WSDL
  2. Скачиваем все xsd из импортов (рекурсивно)
  3. Исправляем schemaLocation’ы по необходимости
  4. 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.

Исходники примера можно посмотреть на гитхабе

Особенности примера:

  1. Используем gradle для сборки
  2. У нас есть 3 xsd схемы. WSDL генерируется при запуске сервера.
  3. Сервис доступен по URL $baseUrl/ws/countries.wsdl
  4. В проекте схемы находятся в директории 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'