Для маршаллинга soap-объектов используем org.springframework.oxm.jaxb.Jaxb2Marshaller - удобный и быстрый.
На этапе отладки взаимодействия между двумя системами решено было
использовать и валидацию по xsd-схемам, чтобы эффективнее отлавливать
нарушения контракта. Выбранный маршаллер отлично справляется с этой
задачей - необходимо указать ему одну или несколько схем, по которым
проводить валидацию, и проверка начнётся.
Поскольку для конфигурации нашего приложения используется
springframework, то создание маршаллера выглядит так (всё в одном для
простоты):
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPaths">
<array>
<value>com. ... .message.refunder</value>
</array>
</property>
<property name="schemas">
<array>
<!-- в качестве параметра может быть любая из реализаций org.springframework.core.io.Resource -->
<bean class="org.springframework.core.io.ClassRelativeResourceLoader$ClassRelativeContextResource">
<constructor-arg name="path" value="Refunder.xsd"/>
<constructor-arg name="clazz" value="com. ... .SoapUtil"/>
</bean>
</array>
</property>
</bean>
</constructor-arg>
contextPaths - это перечень директорий, в которых размещаются сгенерированные jaxb-объекты (можно задать и конкретные классы или пакеты, например);
schemas - перечень схем для валидации.
Если маршаллер "знает" хотя бы про одну схему, он пытается выполнять
валидацию всего, что через него проходит. Если валидация не нужна -
свойство schemas устанавливать не нужно.
Всё классно и то, что в данном случае надо!
Всё классно и то, что в данном случае надо!
Ну, и в качестве завершающего штриха захотелось было сделать дополнительную
настройку типа "выполнять валидацию или нет" - булев флаг, который можно
задавать не в spring-конфигурации, а в текстовом properties-файле. Идея
в том, чтобы заранее подготовить перечень xsd-схем. И передавать этот
перечень вместе с флагом (а флаг можно получить с помощью placeholder из
properties-файла) в прикладной код, который работает с маршаллером. И
при значении флага "true" делать вызывать marshaller.setSchemas(перечень схем). В результате не надо лезть в spring-файлы и искать, а где же
там настраивается маршаллер. Достаточно в легко доступном текстовом
файле изменить флаг. Например, это удобно коллегам из отдела внедрения и сопровождения.
Но не тут-то было. После реализации идеи маршаллер напрочь "забыл" о том, что надо проводить валидацию.
При осмотре кода самого маршаллера выяснилось, что задать-то перечень
схем для проверки можно в любой момент времени с помощью того же метода:
public void setSchemas(Resource[] schemaResources)
Но - реальная загрузка схем из перечня выполняется только один раз, при создании бина и где-то в недрах самого springframework.
В деталях - маршаллер реализует интерфейс
org.springframework.beans.factory.InitializingBean и его метод void
afterPropertiesSet(); он вызывается после установки свойств бина, и к
моменту получения объекта в прикладном коде оказывается уже выполненным.
И вот в нём-то и выполняется private Schema loadSchema(...)! А
поскольку последний закрыт для доступа, но и вызвать его в прикладном
коде для перезагрузки схем не выходит. Грустно :(, придётся писать ещё немного кода и создавать экземпляр маршаллера самостоятельно.
Комментариев нет:
Отправить комментарий