Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Самодокументированный JAX-WS с помощью XSD Restrictions

Anna | 1.06.2014 | нет комментариев
В этой статье я расскажу о создании самодокументируемого web обслуживания (jax-ws), тот, что применяется элементы XSD Restrictions.

Изложение задачи

В книге «Программист прагматик» есть глава, посвящённая документации. В ней сказано, что должен быть один источник информации, а на основе него генерироваться производные формы этой информации. скажем, в одном формате хранится каждая информация о структуре таблиц (это может быть файл всякого подходящего либо собственного формата), а на основе неё генерируются сами таблицы, документация по этим таблицам, DAO объекты для работы с таблицами. Плюсы это подхода в том, между производными формами представления информации не будет рассинхронизации, чай исключительное место, где будет редактироваться информация — это тот изначальный источник.
Минусы в том, что все заинтересованные люди обязаны уметь править данный файл и обязаны быть конвертеры в надобные форматы.
В web services эти представления именуется contract first и contract last. Contract first — когда вначале создаётся wsdl, а по ней генерируется Java код. Contract last — напротив, вначале Java код, а по нему wsdl.
Про плюсы и минусы дозволено почитать по ссылкам: docs.spring.io/spring-ws/sites/1.5/reference/html/why-contract-first.html stackoverflow.com/questions/763827/which-is-the-better-approach-to-web-services-contract-first-or-contract-last

В этой статье я разгляжу создание SOAP Web Service с самодокументацией, что бы получить схожее решение — каждая информация о web services будет содержаться в нём самом. Получается эдакий «contract last» — вначале пишется код, а потом по нему получается документация в виде wsdl, которая содержит максимум информации об этом web сервисе — комментарии ко каждому способам и типам, с которыми сервис работает и огромную часть логики проверки на корректность данных. Для чего это решение может быть благотворно? В том случае, когда каждая разработка сконцентрирована на написании кода и wsdl генерируется на основе него, а не напротив. Либо когда трудно содержать документацию первоначально в wsdl. Но если веб способы пишутся по аналитике, то эту аналитику отличнее всё же беречь в wsdl. Т.е. вначале wsdl, а по ней генерируются способы, классы и читаемая документация. Напротив будут задачи проверки соответствия теснее написанного обслуживания с тех. заданием.
Проверку на корректность входных данных тоже отличнее перенести на сторону xsd, что бы дозволено было проверить запрос без подключения в web сервису и что бы эта логика была видна (в xsd), а не была зашита где то в недрах обслуживания.

Варианты решения

На нынешний момент получить wsdl дозволено из всякого jax-ws приложения. Но типовые jax-ws/jaxb аннотации не поддерживают документацию к веб сервисам — для этого необходимо пользоваться вероятностями, которые предоставляют сторонние framework’и. А определенно — apache CXF (jax-ws) предоставляет аннотацию WSDLDocumentation, которая используется к веб способам и в которой указывается изложение веб способа, которое в последствие попадёт в wsdl. Для документирования xml сущностей, которые будут применяться в веб способах, применяется библиотека jaxb-facets (dsg.tuwien.ac.at/staff/hummer/tools/jaxb-facets.htmlgithub.com/whummer/jaxb-facets). Она разрешает, так же как CXF для веб способов, документировать классы и поля xml bean’ов. По мимо этого она добавляет поддержку XSD Restrictions — дополнительных ограничений на значения полей xml. (изложение XSD Restrictions находится тут www.w3schools.com/schema/schema_facets.asp) Это будет пригодно, когда необходима логика проверки корректности значений труднее чем обязательный/не непременный — т.к. jaxb не в полной мере поддерживает вероятности xsd по части валидации. А определенно, будет допустимо указать ограничения на минимальное, наивысшее значения, применять регулярные выражения, применять разные методы обработки строк на пустые значения, установить ограничения на длину значения.

Реализация

В качестве примера сделаем примитивный веб сервис с несколькими способами.
В статье я опишу определенные примеры с кусками кода. Каждый же сервис дозволено скачать по ссылкеdl.dropboxusercontent.com/u/7519092/jax-ws-example.zip Это IDEA maven план. В IDEA дозволено открыть либо импортом IDEA плана либо импортом maven плана. В pom.xml настроена генерация wsdl файла с трансформацией его в html с поддержкой xslt, но к сожалению,данный wsdl не содержит тега documentation из jaxb-facets, правда в генерируемом wsdl (доступным по ссылке <путь к приложению>/web_service/WebService?wsdl) данный тег есть. Так же в плана отличается использование аннотаций — там аннотации используются к get способам, а в этих примерах к полям класса. Это сделано для того, что бы сократить статью. Что бы использовать аннотации к полям класса необходимо либо не делать get способы либо указать @XmlAccessorType(XmlAccessType.FIELD).

Примеры

В качестве примера разглядим несколько определенных задач

Лимитация на наивысшее и минимальные значение даты и времени.

Для date:

@XmlSchemaType(name = "date")
@Facets(minInclusive = "1900-01-01", maxInclusive = "9999-12-31Z")
Date date;

Сгенерируемая xsd схема:

<xs:element minOccurs="0" name="date">
	<xs:simpleType>
		<xs:restriction base="xs:date">
			<xs:maxInclusive value="9999-12-31Z"/>
			<xs:minInclusive value="1900-01-01"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>
@XmlSchemaType(name = "dateTime")
@Facets(minInclusive = "1900-01-01T00:00:00", maxInclusive = "9999-12-31T23:59:59")
Date dateTime;
<xs:element minOccurs="0" name="dateTime">
	<xs:simpleType>
		<xs:restriction base="xs:dateTime">
			<xs:maxInclusive value="9999-12-31T23:59:59"/>
			<xs:minInclusive value="1900-01-01T00:00:00"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

(Аннотация Facets из библиотеки jaxb-facets)

У нас необходимо было применять т.к. СУБД поддерживала не весть диапазон дат, доступных в Java. Т.е. в web service дозволено передать дат, скажем, 1000-01-01 и в Java она правильно распарсится, но при записи в CУБД будет оплошность, т.к. она не поддерживает такой диапазон дат. И что бы ограничить принимаемые значения вводится это лимитация.
Для даты максимальная дата указана с учётом часового пояса. Необходимо, что бы поддерживались выходные даты 9999-12-31 с часовым поясом (скажем 9999-12-31 04:00). Если этого не делать, то при сериализации этого значения (при отдаче заказчику) будет оплошность xsd validation.

Лимитация на определенную длину поля
@Facets(length = 16)
String id;
<xs:element minOccurs="0" name="id">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:length value="16"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Необходимо, скажем, когда поле является уникальным идентификатором определённой длинны либо каким то иным идентификатором определенной длинны — номер паспорта, карточки.

Правда в случае id дозволено выделить обособленный тип Id:

public class Id {
	@Facets(length = 16)
	@XmlAttribute
	String attr;
}

И применять его так:

Id id;

Так у нас будет очевидно указано, что это переменная — неповторимый идентификатор, при этом все лимитация будут трудиться.

Обнуление полей

Некоторые необязательные поля необходимо обнулять. Для строк это делается дюже легко — шлётся пустой тег (e.g. <name/>) и при unmarshalling’е (реформирование xml запроса в java объекты) получим легко пустую строку (String.isEmpty() == true). И её абсолютно дозволено интерпретировать как строку, которую необходимо установить в null.

Но если необходимо обнулить числа либо даты, то при передаче пустого тега будет оплошность:
Unmarshalling Error: cvc-datatype-valid.1.2.1: ” is not a valid value for ‘integer’

Это абсолютно объяснимо — пустой тег невозможно представить в виде числа (null не считается — null это отсутсвие тега).

Решить это дозволено с поддержкой default значения для поля

@XmlElement(defaultValue = "-2147483648")
Integer id;
<xs:element default="-2147483648" minOccurs="0" name="id" type="xs:int"/>

При этом если передать пустой тег (<id/>) в Java переменная id примет значение -2147483648 (это Integer.MIN_VALUE). Это решение немножко схоже Null Object Pattern — когда необходимо указать, что очевидно передаётся null значение (а не легко не указали значение), то передаём особый null объект.
en.wikipedia.org/wiki/Null_Object_pattern

Для дат данный же подход будет выглядеть так:

@XmlSchemaType(name = "date")
@XmlElement(defaultValue = "1900-01-01")
Date date;
<xs:element default="1900-01-01" minOccurs="0" name="date" type="xs:date"/>
@XmlSchemaType(name = "dateTime")
@XmlElement(defaultValue = "1900-01-01T00:00:00")
Date dateTime;
<xs:element default="1900-01-01T00:00:00" minOccurs="0" name="dateTime" type="xs:dateTime"/>
Документирование

Документирование полей делается с поддержкой аннотации Documentation (из библиотеки jaxb-facets).

@XmlSchemaType(name = "date")
@Documentation("Пример ограничения даты")
@Facets(minInclusive = "1900-01-01", maxInclusive = "9999-12-31Z")
Date date;
<xs:element minOccurs="0" name="date">
	<xs:annotation>
		<xs:documentation>Пример ограничения даты</xs:documentation>
	</xs:annotation>
	<xs:simpleType>
		<xs:restriction base="xs:date">
			<xs:maxInclusive value="9999-12-31Z"/>
			<xs:minInclusive value="1900-01-01"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Документирование способов web service делается с поддержкой аннотации WSDLDocumentation из CXF.

@WSDLDocumentation("Пример документации для способа. Способ показывает работы с XML Schema Restrictions")
String facetsExampleMethod(FacetsExample request);
<wsdl:operation name="facetsExampleMethod">
	<wsdl:documentation>
Пример документации для способа. Способ показывает работы с XML Schema Restrictions
	</wsdl:documentation>
	<wsdl:input message="tns:facetsExampleMethod" name="facetsExampleMethod"/>
	<wsdl:output message="tns:facetsExampleMethodResponse" name="facetsExampleMethodResponse"/>
</wsdl:operation>

В последующем изложение к этим полям и способам дозволено посмотреть в wsdl.

Генерация документации по сервису (wsdl to html)

Для реформировании сгенерированной wsdl в читаемый вид воспользуемся файлом xslttomi.vanek.sk/index.php?page=wsdl-viewer Так же SoapUI может генерировать читаемый html. Всё это описано на StackOverflow:
stackoverflow.com/questions/686103/generating-html-documentation-from-wsdl Реформирование в html на этапе сборки реализовано в pom.xml Дальше эта страница будет доступна по адресу <путь к приложению>/WebService.html
Не сколько примечаний по генерации html:
Параметры web способов правильно отображаются только если указан @SOAPBinding(style = SOAPBinding.Style.RPC).
Аннотация Documentation попадает в wsdl и, соответственно, в документацию в html только при runtime генерации wsdl из работающего обслуживания. При сборке wsdl не содержит документации. Отчего так — не знаю. Скорее каждого оплошность генератора wsdl.

Остальные вероятности jaxb-facets

Лаконично расскажу о остальных вероятностях jaxb-facets, которые я применял:
Проверка значения по регулярному выражению — Facets.pattern.
Установка логики обработки пробельных символов — Facets.whiteSpace. Пробельные символы дозволено рассматривать, убирать, заменять на пробелы (для табов и символов переноса строки). Работает только при проверке в xsd, т.е. в Java код попадёт значение.

Источник: programmingmaster.ru

 

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB