В прошлом посте мы начали рассказывать о разработке на платформе WSO2 и сделали REST API-сервис. Сегодня мы продолжаем тему: в этом посте поделюсь с вами тем, как мы в WSO2 создаем SOAP-сервисы. В этом посте я делаю акцент на различиях, поэтому на случай каких-то общих вопросов можете параллельно открыть пост про REST API. В WSO2 Integration Studio создаем новый проект (File – New – Integration Project). Назовем его, например, Rosstat Service. Не забываем создать RegistryResources, поскольку SOAP-сервис в любом случае предусматривает WSDL/XSD, а их нужно где-то хранить Добавляем в каждый из отмеченных каталогов пустой файл с именем ".gitkeep" для контроля версий: Далее настраиваем остальные параметры в зависимости от проекта. Все ссылки репозитория WSO2 Nexus во всех файлах "pom.xml" меняем на ваши собственные. У нас, соответственно, https://maven.wso2.org/nexus/content/groups/wso2-public/ меняется на https://nexus.gts.rus.socgen/repository/maven-wso2-public/. Создадим шаблон для вызова внешнего сервиса CallAPI. В типе шаблона нужно выбрать Sequence Template. С точки зрения кода шаблон будет таким же, как и при создании REST API-сервиса, поскольку мы принимаем SOAP, а вызываем REST: Теперь создаем шаблон для обработки ошибок SOAPFault. Здесь нужно обратить внимание, какая версия протокола SOAP используется, 1.1 или 1.2. От этого будут зависеть некоторые параметры формирования ошибки, в частности, различаться ContentType. Вот код обработчика для SOAP 1.1: При возникновении ошибки этот обработчик передает XML-сообщение с уникальным id, по которому можно будет легко ее найти в логах. Также не забудьте проставить свою версию SOAP для SOAPFault: description="SoapFault" version="soap11". А вот код обработчика для SOAP 1.2: Теперь создаем общие шаги — Sequence — для обработки входящих ошибок: FaultSequence перехватывает исключения, которые могут произойти при обработке запроса, и вызывает шаблон SOAPFault, который мы только что сделали:  Создадим обработчик Inbound для приема входящих запросов: В параметре ENV_SERVICE_NAME указываем название сервиса. Это же имя будет использоваться в LoggerService для записи логов в отдельный файл. В параметре "onError" здесь и далее в инструкции указываем ссылку на ранее созданный обработчик ошибок: onError="Rosstat_FaultSequence". Здесь есть небольшие отличия от REST. Сгенирировав uuid, мы идем в SOAP Envelope – Body и оттуда получаем название метода. В протоколе SOAP название метода передается именно в теле. Теперь сделаем Outbound — обработчик, который будет заносить в лог факт обработки запроса. И наконец, новый обработчик, которого не было в REST API. UnsupportedSequence используется для обработки ошибки, когда метод был объявлен в WSDL, но не был реализован (или мы сами не хотим его выставлять).  Здесь тоже используется шаблон SOAPFault. В сообщении ошибки мы выдаем «Unsupported service»: Еще один обработчик, которого не было в REST API — обработчик конкретного метода (операции) GetOrganizationInfo. В REST API мы это делали на уровне API с помощью <resource>, здесь это устроено иначе.  Логируем запрос, вызываем HTPP-сервис и логируем ответ:  Теперь нам нужно создать обработчик запросов. Здесь мы удаляем все транспортные заголовки, превращаем SOAP в JSON, задаем формат из трех полей и  ContentType, логируем запрос, вызываем CallTemplate и проверяем, что вернулся код 200. Если да, то мы вызываем sequence для обратной трансформации, если нет — логируем ошибку, вызываем шаблон SOAPfault: Следующий шаг — MappingOUT — обратная трансформация из JSON в SOAP: Здесь мы сохраняем в локальные переменные из JSON интересные нам id, type и name и генерируем payload для xml-ки SOAPResponse: Конечно, удаляем все ненужные транспортные заголовки из REST API, как и в прошлом случае. Обязательно нужно сделать и последовательность для HealthCheck — ​​проверку готовности сервиса принимать траффик (Readness Probe). Он пригодится, когда мы будем деплоить всё в Kubernetes или OpenShift. Далее создадим endpoint для вызова внешних сервисов. Здесь всё так же, как и с REST API. В модуле RosstatServiceRegistryResources (в нашем примере) выбираем New – RegistryResource и в появившемся окне — From existing template.  Далее выставляем параметры.  ResourceName: RosstatOrganizationInfo (указываем имя файла WSDL без расширения) ArtifactName: RosstatOrganizationInfoWSDL (то же самое, что и для ResourceName, только добавляем в конце суффикс WSDL)Template: выбираем из списка значение WSDL FileRegistry: выбираем из списка значение confRegistryPath: resources/rosstat/wsdl Аналогичным образом добавляем XSD-схемы. ResourceName: RosstatOrganizationInfo (указываем имя файла XSD без расширения)ArtifactName: RosstatOrganizationInfoXSD (то же самое, что и для ResourceName, только добавляем в конце суффикс XSD)Template: выбираем из списка значение XSD FileRegistry: выбираем из списка значение confRegistryPath: resources/rosstat/wsdl С SOAP и другими протоколами, кроме REST API, используется ProxyService. Сделаем новый ProxyService, используя ранее созданные Template, Sequence, Endpoint. Выбираем тип Custom Proxy и указываем транспортные протоколы http и https:   В режиме Design ProxyService будет выглядеть вот так:  Атрибут name у корневого элемента proxy является именем SOAP-сервиса. Значение должно совпадать с тем, что будет в URL после /services/: https://localhost:8253/services/RosstatService?wsdl. Мы также добавили в код валидацию запроса по XSD: В блоке "publishWSDL" нужно обязательно указать ссылки на WSDL-файл и XSD-схемы (если их несколько), которые были добавлены в проект на предыдущем шаге. Это необходимо как раз для валидации и получения корректных файлов WSDL/XSD через адрес https://localhost:8253/services/RosstatService?wsdl.   Если сервис должен работать по SOAP 1.1/1.2, необходимо отключить REST и ненужную версию протокола SOAP. Для SOAP 1.1: Для SOAP 1.2: Открывает pom-файл в модуле RosstatServiceCompositeExporter и выбираем все созданные артефакты в модулях RosstatServiceConfig и RosstatServiceRegistryResources: Сборка сервиса через Maven организована так же, как и в случае с REST API. Дальнейшие действия зависят от конкретного проекта. Как я указывал в прошлой статье, мы пишем интеграционные тесты с использованием Postman и заглушки для BackendService с Wiremock.  Если у вас появились вопросы по разработке на WSO2, буду рад ответить на них в комментариях. Мы планируем продолжать серию публикаций по этой платформе, так что подписывайтесь, если интересно, и пишите, что еще хотели бы о ней узнать. IT Architect, WSO2, API Management, IBM WebShpere