WADL (
язык описания веб-приложений ) — это REST, что WSDL для SOAP. Само существование этого языка вызывает много споров (см:
Нужно ли нам WADL? И
К WADL или не WADL ). Я могу вспомнить несколько законных вариантов использования WADL, но если вы уже здесь, вы, вероятно, не ищите еще одного обсуждения. Итак, давайте перейдем к самому WADL.
В принципе WADL похож на WSDL, но структура языка сильно отличается. Хотя WSDL определяет простой список сообщений и операций, которые либо потребляют, либо производят некоторые из них, WADL подчеркивает иерархическую природу веб-сервисов RESTful. В REST основным артефактом является ресурс. Каждый ресурс (существительное) представлен как URI. Каждый ресурс может определять как операции CRUD (глаголы, реализованные как методы HTTP), так и вложенные ресурсы. Вложенный ресурс тесно связан с родительским ресурсом, обычно представляющим владельца.
Простым примером будет http://example.com/api/books ресурс, представляющий список книг. Вы можете (HTTP) получить этот ресурс, то есть получить весь список. Вы также можете ПОЛУЧИТЬ http://example.com/api/books/7 ресурс, извлекая сведения о 7-й книге в разделе книг. Или вы можете даже ПОСТАВИТЬ новую версию или УДАЛИТЬ ресурс в целом, используя тот же URI. Вы не ограничены одним уровнем вложенности: GETting http://example.com/api/books/7/reviews?page=2&size=10 найдет вторую страницу (до 10 элементов) отзывов о 7-й книге. Очевидно, что вы также можете разместить другие ресурсы рядом с книгами, например, http://example.com/api/readers.
Возникло требование формально и точно описать каждый доступный ресурс, метод, запрос и ответ, как это могли сделать ребята из WSDL. WADL — это один из вариантов описания «доступных URI», хотя некоторые считают, что хорошо написанный REST-сервис должен быть самоописательным (см.
HATEOAS ). Тем не менее, вот простой, пустой WADL-документ:
<application xmlns="http://wadl.dev.java.net/2009/02"> <resources base="http://example.com/api"/> </application>
Ничего особенного здесь. Обратите внимание, что тег <resources> определяет базовый адрес API. Все именованные ресурсы, которые мы только что добавим, относятся к этому адресу. Также вы можете определить несколько тегов <resources> для описания более одного API. Итак, давайте добавим простой ресурс:
<application xmlns="http://wadl.dev.java.net/2009/02"> <resources base="http://example.com/api"> <resource path="books"> <method name="GET"/> <method name="POST"/> </resource> </resources> </application>
Это определяет ресурс в http://example.com/api/books двумя возможными способами: GET для получения всего списка и POST для создания (добавления) нового элемента. В зависимости от ваших требований вы можете также разрешить метод DELETE (чтобы удалить все элементы), и WADL несет ответственность за документирование того, что разрешено.
Помните наш пример в начале: / books / 7? Очевидно, что 7 является лишь примером, и мы не будем объявлять все возможные идентификаторы книг в WADL. Вместо этого есть удобный синтаксис заполнителя: есть два важных аспекта, на которые следует обратить внимание: во-первых,
<application xmlns="http://wadl.dev.java.net/2009/02"> <resources base="http://example.com/api"> <resource path="books"> <method name="GET"/> <resource path="{bookId}"> <param required="true" style="template" name="bookId"/> <method name="GET"/> </resource> </resource> </resources> </application>
Заполнитель {bookId} был использован вместо вложенного ресурса. Во-вторых, чтобы было понятно, мы документируем этот заполнитель с помощью тега <param />. Скоро мы увидим, как его можно использовать в сочетании с методами. Просто чтобы убедиться, что вы все еще со мной, в приведенном выше документе описаны ресурсы GET / books и GET / books / some_id.
Веб-сервис становится сложным, однако он описывает довольно много операций. Прежде всего GET / books / 42 / reviews является действительной операцией. Но интересной частью является вложенный тег <request />. Как видите, мы можем описать параметры каждого метода независимо. В нашем случае были определены необязательные параметры запроса (в отличие от параметров шаблона, использовавшихся ранее для заполнителей URI). Это дает клиенту дополнительные знания о допустимых параметрах страницы и размера запроса. Это означает, что / books / 7 / reviews? Page = 2 & size = 10 является допустимым идентификатором ресурса. И упоминал ли я, что к каждому ресурсу, методу и параметру может быть прикреплена документация в соответствии со спецификацией WADL?
Мы остановимся здесь и упомянем только об оставшихся кусочках WADL. Прежде всего, как вы уже, наверное, догадались, для каждого <method /> возможен также дочерний тег <response />. И запрос, и ответ могут определять точную грамматику (например, в схеме XML), которой должен следовать либо запрос, либо ответ. Ответ также может документировать возможные коды ответов HTTP. Но поскольку мы будем использовать знания, которые вы приобрели до сих пор, в приложении с первым кодом, я намеренно оставил определение <grammars />. WADL является гибким и позволяет вам определять столько информации, сколько вам нужно.
Итак, мы знаем основы WADL, теперь мы хотели бы использовать его, возможно, в качестве потребителя или производителя в приложении на основе Java. К счастью, есть
wadl.xsd Описание XML-схемы самого языка, который мы можем использовать для создания аннотаций JAXB с POJO для работы (используя инструмент xjc в JDK):
$ wget http://www.w3.org/Submission/wadl/wadl.xsd $ xjc wadl.xsd
И там это … висит! Жизнь разработчика программного обеспечения полна вызовов и нетривиальных проблем. А иногда это просто раздражающий сетевой фильтр, который заставляет исчезать подозрительные пакеты (вместе с полчаса вашей жизни). Нетрудно обнаружить проблему, если вспомнить ту статью, написанную примерно в 2008 году:
Излишний трафик DTD W3C :
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
Доступ к
xml.xsd из браузера мгновенно возвращает HTML-страницу, но инструмент xjc ждет вечно. Помогла локальная загрузка этого файла и исправление атрибута schemaLocation в wadl.xsd. Это всегда мелочи …
$ xjc wadl.xsd parsing a schema... compiling a schema... net/java/dev/wadl/_2009/_02/Application.java net/java/dev/wadl/_2009/_02/Doc.java net/java/dev/wadl/_2009/_02/Grammars.java net/java/dev/wadl/_2009/_02/HTTPMethods.java net/java/dev/wadl/_2009/_02/Include.java net/java/dev/wadl/_2009/_02/Link.java net/java/dev/wadl/_2009/_02/Method.java net/java/dev/wadl/_2009/_02/ObjectFactory.java net/java/dev/wadl/_2009/_02/Option.java net/java/dev/wadl/_2009/_02/Param.java net/java/dev/wadl/_2009/_02/ParamStyle.java net/java/dev/wadl/_2009/_02/Representation.java net/java/dev/wadl/_2009/_02/Request.java net/java/dev/wadl/_2009/_02/Resource.java net/java/dev/wadl/_2009/_02/ResourceType.java net/java/dev/wadl/_2009/_02/Resources.java net/java/dev/wadl/_2009/_02/Response.java net/java/dev/wadl/_2009/_02/package-info.java
Поскольку мы будем использовать эти классы в проекте, основанном на maven (и я ненавижу фиксировать сгенерированные классы в исходный репозиторий), давайте переместим выполнение xjc в жизненный цикл maven:
Что ж, pom.xml — не самый лаконичный формат за всю историю … Неважно, это будет генерировать классы WADL XML во время каждой сборки, прежде чем исходный код будет скомпилирован. Я также люблю плагин fluent-api, который добавляет методы * () вместе с обычными сеттерами, возвращая это, чтобы разрешить цепочку. Довольно удобно. Наконец, мы определяем более приятное имя пакета для сгенерированных артефактов (если вы находите имя пакета net.java.dev.wadl._2009._02 достаточно приятным, вы можете пропустить этот шаг) и добавляете префикс Wadl ко всем сгенерированным классам файла bindings.xjb:
Теперь мы готовы производить и использовать WADL в формате XML с использованием классов JAXB и POJO. Обладая этими знаниями и фундаментом, мы готовы разработать интересную библиотеку, о которой пойдет речь в следующей статье.
От http://nurkiewicz.blogspot.com/2012/01/gentle-introduction-to-wadl-in-java.html