Статьи

Фильтр проверки схемы Gotchas with Mule Studio

Ранее в этом месяце я представил концепцию Mule, которая требовала использования фильтра проверки схемы . Вариант использования был довольно простым. XML-сообщения поступают через SOAP-запрос, и некоторые поля во входящем сообщении должны были проверяться по множеству XML-схем.

Что ж, это идеальный сценарий использования для Schema Validator, который поставляется вместе с Mule. Это элемент, который вы можете выбросить из палитры Mule Studio прямо в ваш поток.

Схема-валидатор

Схема-валидатор

Конфигурация этого элемента немного сложнее. Это принимает разделенный запятыми список схем для проверки полезной нагрузки. Справедливо, но вы сразу же столкнулись с первой проблемой. Как найти URL, который работает как в Mule Studio, так и в автономном Mule, если ваши схемы являются частью classpath?

Обычно в Spring вы делаете это, предварительно ожидая ваш URL с помощью « classpath:» . К сожалению, это не работает с этим фильтром. Мы решили проблему, поместив схемы в папку src / main / resources в Mule Studio. Из фильтра проверки схемы мы ссылались на них с помощью переменной $ {app.home} :

<mulexml:schema-validation-filter schemaLocations="${app.home}/classes/MyXsd1_v2.1.0.xsd,${app.home}/classes/xsd/MyXsd2_v1.2.0.xsd" returnResult="true"/>

Вторая проблема, которая сразу же возникает, заключается в том, что средство проверки схемы успешно игнорирует любые
xs: import или
xs: include в ваших схемах. При запуске средства проверки схемы произойдет сбой, исключение будет выглядеть примерно так (подробности об исключении удалены для простоты).

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schemaValidator': Invocation of init method failed; nested exception is org.mule.api.lifecycle.InitialisationException: src-resolve: Cannot resolve the name 'xxxyyy' to a(n) 'type definition' component.
	...
Caused by: org.mule.api.lifecycle.InitialisationException: src-resolve: Cannot resolve the name 'xxxyyy' to a(n) 'type definition' component.
	...
Caused by: org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'xxxyyy' to a(n) 'type definition' component.
	...

Это связано с классом;
javax.xml.validation.SchemaFactory . Фильтр проверки схемы Mule использует этот класс для построения схем, чтобы иметь возможность проверки. Этот фабричный класс игнорирует любые XSD «include» и «import». (Смотрите
здесь для получения дополнительной информации.)

К счастью, есть решение. Фильтр проверки схемы Mule позволяет вам настраивать собственный распознаватель ресурсов. Это класс, который используется для загрузки внешних ресурсов, например XSD «включает» и «импортирует». Мы написали очень простой распознаватель ресурсов, который загружает внешние ресурсы из пути к классам:

package com.ricston.xml;

import java.io.IOException;
import java.io.InputStream;

import org.apache.xerces.dom.DOMInputImpl;
import org.mule.util.IOUtils;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;

public class ClasspathResourceResolver implements LSResourceResolver {

	@Override
	public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {

		try {
			InputStream resource = IOUtils.getResourceAsStream(systemId, getClass());
			return new DOMInputImpl(publicId, systemId, baseURI, resource, null);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}
}

Как видите, это предельно просто. Всего 2 строки кода Java. Идея в том, что мы загружаем внешний ресурс, переданный SchemaFactory, с помощью библиотеки Mule IOUtils. После загрузки мы должны передать обратно экземпляр
org.w3c.dom.ls.LSInput . Мы использовали 
org.apache.xerces.dom.DOMInputImpl, чтобы помочь нам в этом.

Последний шаг теперь состоит в том, чтобы настроить фильтр проверки схемы для использования нашего пользовательского распознавателя ресурсов:

<spring:bean id="classpathResourceResolver" name="classpathResourceResolver" class="com.ricston.xml.ClasspathResourceResolver"/>
 
<mulexml:schema-validation-filter schemaLocations="${app.home}/classes/MyXsd1_v2.1.0.xsd,${app.home}/classes/xsd/MyXsd2_v1.2.0.xsd" returnResult="true" resourceResolver-ref="classpathResourceResolver"/>

Конечно, вы можете написать свой собственный загрузчик ресурсов для загрузки ресурсов из абсолютных путей, относительных путей или любого другого метода, который вы хотели бы реализовать. Достаточно просто взять наш 
ClasspathResourceResolver и преобразовать его в соответствии с вашими потребностями.

Еще одна проблема, с которой я столкнулся при использовании этого фильтра, — это способ его обработки. Если вы предоставите ему XML, который не соответствует какой-либо схеме, он молча блокирует ваше сообщение. По умолчанию в журналах ничего не отображается. Чтобы увидеть ошибки, вам нужно настроить  класс SchemaValidationFilter для входа на уровень отладки через log4j:

log4j.logger.org.mule.module.xml.filters.SchemaValidationFilter=DEBUG

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