Как отправить soap запрос java
Перейти к содержимому

Как отправить soap запрос java

  • автор:

Клиент web-сервиса SOAP

Данная статья является продолжением описания WEB-сервиса SOAP. С общим описанием веб-сервисов (что это такое и какие типы веб-сервисов используются) можно познакомиться здесь. Создание и тестирование WEB-сервиса SOAP рассмотрено отдельно на практическом примере в среде разработки Eclipse. Для описания WEB-сервиса SOAP используется язык WSDL В этой статье на рабочем примере будем рассматривать вопрос создания клиента веб-сервисов SOAP. В качестве «подопытных» используем действующие на момент написания статьи два веб-сервиса.

Первый веб-сервис http://www.webservicex.net/uszip.asmx используем для получения почтовых значений ZIP районов города New York. На следующем скриншоте представлены методы WEB-сервиса, которые Вы можете увидеть при нажатии на ссылку. Используем второй по списку метод GetInfoByCity.

Второй веб-сервис BELAVIA включает метод получения списка аэропортов GetAirportsList и метод получения списка рейсов с информацией о вылете/прилёте и состоянии рейса GetTimeTable. По ссылке можно перейти на страницу описания веб-сервиса и посмотреть параметры методов web-сервиса BELAVIA, а также примеры запросов и ответов. В примере будем получать список аэропортов, используя метод GetAirportsList.

Примечание : если по указанным выше ссылкам можно открыть описания WEB-сервисов, то рассматриваемый на странице пример сможет выполнить запрос и получить ответ.

Структура сообщений SOAP

С WEB-сервисом SOAP «разговаривают на языке сообщений» определенного формата. Структура SOAP-сообщения состоит из оболочки, разделенной на две главные части: секция с описанием заголовка и секция с телом сообщения . Следующий код демонстрирует сообщение запроса списка аэропортов веб-сервиса BELAVIA.

Оболочка сообщения () содержит элементы Header и Body, которые также, как и Envelope принадлежат пространству имен http://schemas.xmlsoap.org/soap/envelope/.

SOAPConnectionFactory — класс создания подключения и SOAP сообщения

Для работы с WEB-сервисом SOAP удобнее всего использовать SAAJ (SOAP with Attachments API for Java), который представляет программный интерфейс Java для сообщений SOAP. В пакет SAAJ включен класс SOAPConnection, который позволяет отправлять запросы веб-сервису. Объект подключения SOAPConnection создается с помощью SOAPConnectionFactory, который также используется и для создания SOAP сообщения (SOAPMessage). Следующий код демонстрирует создание SOAPConnection и SOAPMessage.

import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPPart; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPConnection; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPConnectionFactory; . SOAPConnectionFactory soapConnFactory; SOAPConnection soapConnection ; MessageFactory messageFactory ; try < // Создание соединения soapConnFactory = SOAPConnectionFactory.newInstance(); soapConnection = soapConnFactory.createConnection(); // Создание сообщения messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); // Компоненты сообщения SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPBody body = envelope.getBody(); // Закрываем соединение soapConnection.close(); >catch(Exception e)

С помощью объекта MessageFactory создается объект сообщения SOAPMessage, у которого первоначально разделы envelope и header пусты. Объект SOAPPart содержит envelope, в который включается тело сообщения. Для формирования тела сообщения определяется ссылка SOAPBody.

SAAJ также позволяет напрямую создать объект SOAPPart-сообщения из внешнего файла. Так часто отправляемый запрос можно поместить в файл weather.msg, чтобы при необходимости его содержимое загружать в тело SOAP вместо ручного создания. Следующий код демонстрирует формирование тела SOAP сообщения с использованием потока ввода.

// Создание сообщения messageFactory = MessageFactory.newInstance(); SOAPMessage message = messageFactory.createMessage(); // Компоненты сообщения SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPBody body = envelope.getBody(); // Формирование сообщения StreamSource msgSrc; FileInputStream fis = FileInputStream("weather.msg"); msgSrc = new StreamSource(fis); soapPart.setContent(msgSrc); //Сохранение сообщения message.saveChanges();

Класс StreamSource открывает файловый поток ввода FileInputStream и читает готовое к отправке сообщение.

Пример клиента WEB-сервиса SOAP

Создадим простенький проект в Eclipse, структура которого представлена на следующем скриншоте. В проект включим библиотеку saaj.jar и класс SoapClientExample, который будет отправлять WEB-сервисам запросы и получать от них ответы. Проще проект и не представить, но какие возможности . .

Библиотека saaj.jar позволяет использовать в клиенте web-сервиса SOAP программный интерфейс Java для сообщений SAAJ (SOAP with Attachments API for Java).

Структура класса SoapClientExample

SoapClientExample включает методы формирования SOAP сообщения (createSoapEnvelope, createSOAPRequest) и метод вызова веб-сервиса (callSoapWebService). Код методов представлен ниже. Переменные, определяющие параметры Web-сервиса и запроса, вынесены из методов и объявлены глобальными. Метод setSoapParams в зависимости от установленного флага belavia инициализирует параметры запроса одного из используемых web-сервисов.

package com.example; import javax.xml.soap.*; public class SoapClientExample < private boolean belavia = true; private String namespaceURI = null; private String soapUrl = null; private String serviceName = null; private String namespace = null; private String soapAction = null; public SoapClientExample() < setSoapParams(); callSoapWebService(soapUrl, soapAction); >private void setSoapParams() < if (belavia) < namespaceURI = "http://webservices.belavia.by"; soapUrl = "http://86.57.245.235/TimeTable/Service.asmx"; serviceName = "GetAirportsList"; >else < namespaceURI = "http://www.webserviceX.NET"; soapUrl = "http://www.webservicex.net/uszip.asmx"; serviceName = "GetInfoByCity"; >namespace = "ns"; // namespace soapAction = namespaceURI + "/" + serviceName; > private void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException < // код >private SOAPMessage createSOAPRequest(String soapAction) throws Exception < // код >private void callSoapWebService(String destination, String soapService) < // код >public static void main(String[] args) < new SoapClientExample(); System.exit(0); >>
Метод создания оболочки сообщения

Метод createSoapEnvelope формирует тело сообщения в зависимости от установленного флага belavia.

private void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException < SOAPPart soapPart = soapMessage.getSOAPPart(); // SOAP Envelope SOAPEnvelope envelope = soapPart.getEnvelope(); envelope.addNamespaceDeclaration(namespace, namespaceURI); // SOAP Body SOAPBody soapBody = envelope.getBody(); SOAPElement soapBodyElem; SOAPElement soapBodyElem1; if (belavia) < soapBody.addChildElement(serviceName, namespace); >else < soapBodyElem =soapBody.addChildElement(serviceName, namespace); soapBodyElem1=soapBodyElem.addChildElement("USCity",namespace); soapBodyElem1.addTextNode("New York"); >>
Метод создания запроса к веб-сервису

Метод createSOAPRequest подготавливает SOAP сообщение и вызывает метод формирования тела сообщения createSoapEnvelope.

private SOAPMessage createSOAPRequest(String soapAction) throws Exception < MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFactory.createMessage(); createSoapEnvelope(soapMessage); MimeHeaders headers = soapMessage.getMimeHeaders(); headers.addHeader("SOAPAction", soapAction); soapMessage.saveChanges(); // Печать XML текста запроса System.out.println("Request SOAP Message:"); soapMessage.writeTo(System.out); System.out.println("\n"); return soapMessage; >
Метод вызова WEB-сервиса

Метод callSoapWebService используется для отправки запроса и получения ответа. Отправка сообщений SOAP и получение ответов выполняются за один шаг, т.е. синхронно. Сообщение отправляется в момент вызова метода call объекта SOAPConnection, который принимает в качестве аргументов адрес назначения и само сообщение. После этого соединение не закрывается и находится в ожидании ответа. В качестве ответа метод возвращает другой объект также типа SOAPMessage.

Вывод результата запроса выводится в консоль. Но поскольку полученный объект типа SOAPMessage, также является сообщением SOAP, то как и любое XML-сообщение, его можно трансформировать с помощью XSLT. SOAP позволяет выполнить XSLT-преобразование напрямую. В следующем листинге приводится метод printSOAPMessage, в котором выполняется данное преобразование.

Примечание :
1. XSLT (eXtensible Stylesheet Language Transformations) — это язык преобразования XML-документов. При применении таблицы стилей XSLT, состоящей из набора шаблонов, к XML-документу создается конечное дерево, которое может быть сериализовано в виде XML-документа.
2. Метод printSOAPMessage и флаг useXSLT не представлены в общей структуре класса SoapClientExample, поскольку в бо́льшей степени относятся к XML, чем к SOAP.

boolean useXSLT = true; . private void callSoapWebService(String destination, String soapAction) < SOAPConnectionFactory soapFactory = null; SOAPConnection soapConnect = null; SOAPMessage soapRequest = null; SOAPMessage soapResponse = null; try < // Создание SOAP Connection soapFactory = SOAPConnectionFactory.newInstance(); soapConnect = soapFactory.createConnection(); // Создание SOAP Message для отправки soapRequest = createSOAPRequest(soapAction); // Получение SOAP Message soapResponse = soapConnect.call(soapRequest, destination); // Печать SOAP Response if (!useXSLT) < System.out.println("Response SOAP Message:"); soapResponse.writeTo(System.out); System.out.println(); >else printSOAPMessage (soapResponse); soapConnect.close(); > catch (Exception e) < e.printStackTrace(); >> private void printSOAPMessage (SOAPMessage soapResponse) < TransformerFactory transformerFactory; Transformer transformer; try < // Создание XSLT-процессора transformerFactory = TransformerFactory.newInstance(); transformer = transformerFactory.newTransformer(); // Получение содержимого ответа Source content; content = soapResponse.getSOAPPart().getContent(); // Определение выходного потока StreamResult result = new StreamResult(System.out); transformer.transform(content, result); System.out.println(); >catch (Exception e) < e.printStackTrace(); >>

При использовании XSLT в методе printSOAPMessage сначала создается объект Transformer. После этого определяется содержимое content типа javax.xml.transform.Source. Поскольку content выводится только в консоль (System.out), то таблица стилей не используется. При обработке можно выделить как оболочку, так и тело сообщения.

Тестирование примера

Программа выводит в консоль тексты SOAP сообщений как запроса, так и ответа.

Ниже представлен результат выполнения запроса к сервису получения ZIP значений города Нью-Йорка. Ответ представлен в виде массива данных (отображены только первые два и последний элементы массива).

Request SOAP Message:    New York    ----------------------------------------------------------- Response SOAP Message:       New YorkNY10001212E
New YorkNY10002212E
. New YorkNY10292212E

Ответ на запрос получения списка аэропортов также представлен в виде массива данных (отображены только четыре первых и последний элементы массива).

Request SOAP Message:      ----------------------------------------------------------- Response SOAP Message:         . . .     

Скачать пример

Исходный код примера в виде проекта Eclipse soap-client, включающий библиотеку saaj.jar, можно скачать здесь (23 Кб).

Пример SOAP клиента с авторизацей представлен здесь.

SOAP API

В конце 1990-х годов протокол SOAP был разработан для обмена данными в формате XML между клиентом и сервером. Давайте разберемся что такое SOAP API сейчас и в каких случаях его использовать. Поговорим о недостатках, а также почему ему на пятки наступает REST API.

SOAP(Simple Object Access Protocol) — это протокол обмена сообщениями между компьютерными системами.

SOAP API (Application Programming Interface) — это интерфейс, который позволяет взаимодействовать с удаленными сервисами или приложениями с использованием SOAP протокола. SOAP API основан на использовании XML для описания структуры и содержимого сообщений. Сообщения в SOAP API представляют собой XML-документы, которые содержат данные и вызовы методов для удаленного выполнения операций.

Базовые понятия SOAP API

Пакеты. В SOAP API данные передаются в виде пакетов — это обертки для информации, передаваемой между клиентом и сервером. Каждый пакет содержит заголовок (header) и тело (body). В заголовке можно указать дополнительные метаданные, такие как информацию о безопасности или версии протокола. В теле пакета находятся сами данные, которые могут быть представлены в виде XML-структуры.

Правила кодировки. SOAP API работает с XML для кодирования данных. XML (eXtensible Markup Language) использует теги и атрибуты для описания структуры данных. SOAP определяет набор правил, которые определяют, как данные должны быть представлены в XML-формате. Например, SOAP определяет правила для сериализации объектов, передачи значений и обработки ошибок.

Стили взаимодействия. SOAP API поддерживает различные стили взаимодействия, которые определяют, как клиент и сервер обмениваются данными, например:

  • RPC-стиль. В RPC-стиле клиент вызывает удаленный метод на сервере, передавая ему параметры. Сервер выполняет метод и возвращает результат обратно клиенту. RPC-стиль абстрагирует вызовы удаленных методов, делая их похожими на вызовы локальных методов.
  • Document-style. В Document-стиле данные передаются в виде XML-документа. Вместо вызова методов, клиент и сервер обмениваются структурированными XML-данными. Document-style более гибкий и позволяет передавать сложные объекты и атрибуты.

Модель данных SOAP

Модель данных SOAP определяет типы данных, которые могут быть переданы и позволяет определять пользовательские типы данных и их структуру.

Элементы модели данных SOAP

Элементы XML: нужны для представления данных в SOAP сообщениях. Каждый элемент имеет имя и может содержать другие элементы или текстовые данные.

Атрибуты XML: используются для представления дополнительной информации об элементе. Они имеют имя и значение и могут быть использованы для передачи метаданных или управления обработкой данных.

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

Сложные типы данных: структуры и массивы. Структуры содержат несколько элементов разных типов, а массивы — несколько элементов одного типа.

Пространства имен: существуют для разрешения конфликтов имен элементов и типов данных. Пространства имен позволяют уникально идентифицировать элементы и типы данных в рамках SOAP сообщения.

Что может SOAP API

  • Создавать структурированные сообщения: при помощи описания формата сообщений в XML, который понятен для большинства языков программирования и платформ
  • Работать с различными протоколами: такими как HTTP, HTTPS, SMTP, FTP. Это делает его гибким и позволяет интегрировать системы, использующие разные протоколы
  • Поддерживать разные платформы и языки программирования: такие как Java, .NET, PHP. Это делает его доступным для широкого круга разработчиков и позволяет создавать межплатформенные приложения
  • Расширять функциональность: SOAP API позволяет определять собственные пользовательские типы данных и имеет такие расширения, как WS-Security для обеспечения безопасности или WS-ReliableMessaging для обеспечения надежной доставки сообщений.

Популярность и актуальность

SOAP API нашел широкое применение в интеграции между системами, особенно в крупных предприятиях, где требуется обмен данными между приложениями и платформами. Также он используется в веб-сервисах для предоставления API для внешних разработчиков.

В последние годы популярность SOAP снизилась в связи с развитием более легковесных и простых в использовании протоколов, таких как REST (Representational State Transfer). REST API стал более известным из-за своей простоты, гибкости и поддержки форматов данных, таких как JSON.

В итоге, выбор между SOAP API и другими протоколами зависит от конкретных требований и контекста проекта.

Отличия SOAP от REST

Архитектура:

  • REST использует стандартные HTTP-методы, такие как GET, POST, PUT и DELETE
  • SOAP работает с форматом XML для сериализации данных и предоставляет возможность обмена сложными объектами и атрибутами.

Протокол передачи данных:

  • REST основан на протоколе HTTP
  • SOAP более гибок в выборе протокола передачи данных.

Формат данных:

  • REST работает как с JSON, XML, так и с простым текстом.
  • SOAP использует XML для сериализации и передачи данных.

Универсальность и простота использования:

  • REST прост и гибок в использовании.
  • SOAP предоставляет богатый набор функций и поддерживает сложные операции и транзакции. SOAP требует наличия WSDL (Web Services Description Language) для описания веб-служб.

Пример SOAP API

Пример REST API

GET /api/stocks/IBM HTTP/1.1 Host: example.com

В примере SOAP мы видим структурированное XML-сообщение, в котором указывается операция GetStockPrice и параметр StockName со значением IBM.

В примере REST мы видим простой HTTP-запрос GET, в котором указывается адрес ресурса /api/stocks/IBM для получения информации об акции IBM.

В каких случаях используют SOAP API

  • В интеграции сложных систем. SOAP поддерживает передачу сложных объектов и атрибутов, что позволяет эффективно обмениваться данными между системами.
  • Когда есть необходимость в строгих стандартах безопасности с поддержкой SSL. SOAP API использует WS-Security для обеспечения безопасности приложений на уровне предприятия и для связи с унаследованными системами.
  • Когда нужны надежные функции обмена сообщениями. Если вам необходимо гарантировать, что сообщения будут доставлены в надежном порядке и без потерь, то SOAP API обеспечит надежную доставку сообщений между системами при помощи расширения WS-ReliableMessaging.
  • Когда необходимо сохранить конфиденциальность. SOAP API включает в себя соответствие стандарту ACID (Atomicity, Consistency, Isolation, and Durability) и это соответствие уменьшает избыточность и повышает безопасность и целостность сообщений.

Недостатки SOAP

  • Объемные сообщения: SOAP API использует XML для сериализации данных, что приводит к увеличению объема передаваемых сообщений. Проблемы возникают при передаче больших объемов данных или при работе с медленными сетевыми соединениями.
  • Поддержка только одного формата: SOAP API ограничен использованием только XML в качестве формата данных. В некоторых случаях это может означать дополнительные накладные расходы на преобразование данных из других форматов в XML и обратно.
  • Один запрос — один ответ: клиент должен отправить запрос и дождаться ответа от сервера, прежде чем продолжить выполнение следующих операций. Это может привести к блокировке клиентского приложения, если запрос долго обрабатывается.
  • Возможность нарушения работы клиента при смене описания веб-сервиса: смена описания потребует дополнительных усилий для согласования изменений между поставщиком и потребителем сервиса.

Подключение к SOAP (запрос строкой)

Здравствуйте. Пытаюсь написать простейший клиент на Java подключения к вебсервису SOAP. Проверил вариант с SOAP SAAJ. Работает, НО не устраивает тем, что необходимо под каждый SOAP запрос составлять свою объектную модель SOAP. Существуют ли другие аналогичные варианты формирования SOAP request, полностью идентичные типу SOAP SAAJ. Попробовал это заменить

MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage soapMessage = messageFactory.createMessage(); SOAPPart soapPart = soapMessage.getSOAPPart(); String serverURI = "http://ws.cdyne.com/"; // SOAP Envelope SOAPEnvelope envelope = soapPart.getEnvelope(); envelope.addNamespaceDeclaration("example", serverURI); /* Constructed SOAP Request Message: [email protected] 123 */ // SOAP Body SOAPBody soapBody = envelope.getBody(); SOAPElement soapBodyElem = soapBody.addChildElement("VerifyEmail", "example"); SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("email", "example"); soapBodyElem1.addTextNode("[email protected]"); SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("LicenseKey", "example"); soapBodyElem2.addTextNode("123"); MimeHeaders headers = soapMessage.getMimeHeaders();

заменить на

MessageFactory msgFactory = MessageFactory.newInstance(); String reqEnv = "[email protected]123"; SOAPMessage soapMessage = msgFactory.createMessage(null, new ByteArrayInputStream(reqEnv.getBytes())); 
 SOAPMessage message = MessageFactory.newInstance().createMessage(); SOAPPart soapPart = message.getSOAPPart(); soapPart.setContent(new StreamSource(new FileInputStream("c:\\musor\\1.xml"))); 

при том, что результирующий SOAP request везде одинаковый получаю в оставшихся 2-х случаях ошибку

    soap:Client Server did not recognize the value of HTTP Header SOAPAction: .    

НО работает только объектный первый способ на SAAJ. Существуют ли способы другие аналогичные? если да то какие. Заранее благодарю за ответ.

SOAP-запрос, на Java, Android

Если таких запросов будет не очень много, я советую следующий подход:

Скачай SoapUI, сделай новый SOAP-проект, укажи ему этот URL как WSDL.

Он сгенерирует тебе примеры запросов. Убедись, что всё работает. Там и увидишь, как выглядят запросы и ответы.

Потом через обычный API составь нужный XML-документ с нужными параметрами и отправь его обычным же API через HTTP POST (возможно с нужным заголовком SoapAction). Ответ распарсь и вытащи нужную тебе информацию.

С таким подходом код будет понятным и не нужно никаких зависимостей, размер приложения будет небольшой.

Если таких запросов будет много и вручную это всё делать не хочется — подключай библиотеки. В мире Java стандарт де факто это JAX-WS, он даже в JDK встроен. Насчёт Android не знаю, в Android Java поддельная, но отдельной зависимостью скорей всего подключить получится.

Legioner ★★★★★
( 17.01.20 10:10:31 MSK )
Последнее исправление: Legioner 17.01.20 10:11:18 MSK (всего исправлений: 1)

Ответ на: комментарий от Legioner 17.01.20 10:10:31 MSK

С таким подходом код будет понятным и не нужно никаких зависимостей, размер приложения будет небольшой.

Уже попробовал. Поверх http отправлял xml(формат soap) — ответ status code 500, 502. Доступа к логам нет, почему такой статус неизвестно

Насчёт Android не знаю, в Android Java поддельная, но отдельной зависимостью скорей всего подключить получится.

Вот по этому и хочется разобраться в чем дело, дело в сервисе(в http-заголовках) или в самой java на android.

P.S. кстати через soapui — все работает

Booker
( 17.01.20 10:22:39 MSK ) автор топика
Ответ на: комментарий от Legioner 17.01.20 10:10:31 MSK

Увы, нет. В андроиде нет кучи базовых классов, которые нужны библиотекам, нет поддержки части аннотаций, да дофига всего нет.

Если очень надо SOAP, то либо ручками, либо ksoap2. С либой немного проще, но писал её аутист, так что весь выигрыш по времени сожрёт борьба с её костылями.

anonymous
( 17.01.20 10:29:21 MSK )
Ответ на: комментарий от Booker 17.01.20 10:22:39 MSK

Уже попробовал. Поверх http отправлял xml(формат soap) — ответ status code 500, 502. Доступа к логам нет, почему такой статус неизвестно

Заголовок SoapAction проставил? В XML точно ничего не напутал?

Вот по этому и хочется разобраться в чем дело, дело в сервисе(в http-заголовках) или в самой java на android.

А при чём тут Java? Байты везде одинаковые. Можешь для начала взять рабочий текст запроса из SoapUI, как есть прям, сохранить в файл в проекте и его просто по байтам отправлять в POST. А дальше уже «пляши».

P.S. кстати через soapui — все работает

Там можно посмотреть прям весь запрос, как отправляется, включая HTTP заголовки. Проверь.

Ещё, кстати, в SoapUI есть полезная опция — mock. Т.е. можешь запустить SOAP-сервер прям у себя и прописать, что на этот запрос отвечать этим ответом. Там уже будут нормальные сообщения об ошибке. Можно попробовать так отладиться.

Legioner ★★★★★
( 17.01.20 10:51:18 MSK )
Последнее исправление: Legioner 17.01.20 10:57:09 MSK (всего исправлений: 1)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *