Обращение к Web-сервису
Материал из BiTel WiKi
Строка 1: | Строка 1: | ||
+ | == Генерация кода и обращение к сервису == | ||
1. Получение WSDL файла с описанием сервиса. | 1. Получение WSDL файла с описанием сервиса. | ||
Загрузка браузером либо иным способом по URL вида: '''http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl''' WSDL файла. | Загрузка браузером либо иным способом по URL вида: '''http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl''' WSDL файла. | ||
Строка 14: | Строка 15: | ||
.... | .... | ||
// код где-то внутри функции | // код где-то внутри функции | ||
- | WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); | + | WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); |
WebServicePortType port = service.getWebServiceSoap(); | WebServicePortType port = service.getWebServiceSoap(); | ||
// вызов собственно функции сервиса | // вызов собственно функции сервиса | ||
Строка 33: | Строка 34: | ||
Название класса-сервиса и класса-порта (WebService и WebServicePortType) может различаться для разных сервисов. | Название класса-сервиса и класса-порта (WebService и WebServicePortType) может различаться для разных сервисов. | ||
+ | |||
+ | == Http Basic авторизация == | ||
+ | Для Basic авторизации при вызове сервиса нужно дополнить вызов следующим кодом: | ||
+ | <source lang="java"> | ||
+ | .... | ||
+ | // код где-то внутри функции | ||
+ | WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); | ||
+ | WebServicePortType port = service.getWebServiceSoap(); | ||
+ | |||
+ | Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext(); | ||
+ | requestContext.put( BindingProvider.USERNAME_PROPERTY, <username> ); | ||
+ | requestContext.put( BindingProvider.PASSWORD_PROPERTY, <pswd> ); | ||
+ | |||
+ | // вызов собственно функции сервиса | ||
+ | String client = port.getClientByINN( "1234567890" ); | ||
+ | </source> | ||
+ | |||
+ | == Http Basic авторизация включая WSDL описание == | ||
+ | Если и WSDL описание сервиса возвращается только по Basic авторизации, то предыдущий пример упадёт на строке создания самого сервиса: | ||
+ | <source lang="java"> | ||
+ | WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); | ||
+ | </source> | ||
+ | |||
+ | Найдено два способа обойти проблему: | ||
+ | |||
+ | === Способ первый === | ||
+ | <source lang="java"> | ||
+ | Authenticator.setDefault( new Authenticator() | ||
+ | { | ||
+ | protected PasswordAuthentication getPasswordAuthentication() | ||
+ | { | ||
+ | // можно дополнительно анализировать this.getRequestingURL().toString() | ||
+ | return new PasswordAuthentication( username, pswd.toCharArray() ); | ||
+ | } | ||
+ | } ); | ||
+ | |||
+ | WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); | ||
+ | WebServicePortType port = service.getWebServiceSoap(); | ||
+ | |||
+ | // вызов собственно функции сервиса | ||
+ | String client = port.getClientByINN( "1234567890" ); | ||
+ | </source> | ||
+ | |||
+ | При этом данный код становится ненужным: | ||
+ | <source lang="java"> | ||
+ | Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext(); | ||
+ | requestContext.put( BindingProvider.USERNAME_PROPERTY, <username> ); | ||
+ | requestContext.put( BindingProvider.PASSWORD_PROPERTY, <pswd> ); | ||
+ | </source> | ||
+ | |||
+ | Способ плох тем, что: | ||
+ | # При наличии обращений к нескольким сервисам придётся в аунтификаторе анализировать URL ендпоинта сервиса и по нему предлагать логины-пароли, придётся создать глобальное хранилище этих паролей. | ||
+ | # При изменении пароля придётся дорабатывать аунтификатор, чтобы пароли не кэшировались (по-умолчанию они запрашиваются только один раз), либо кэш сбрасывать. | ||
+ | # Аунтификатор устанавливается на всю Java машину и при обращении к нескольким Web-сервисам в разных местах приложения постоянно придётся следить за данным глобальным аунтификатором, чтобы никто его не перетёр. | ||
+ | # Потоконебезопасный способ, теоретически в момент между установкой аунтификатора и созданием сервиса может вклиниться другой поток со своим аунтификатором. | ||
+ | |||
+ | === Способ второй (предпочтительный) === | ||
+ | В создание сервиса передать WSDL из файла либо classpath (предпочтительнее). Т.к. в WSDL описании получается и адрес самого сервиса (endpoint), то далее он переопределяется с помощью опции '''ENDPOINT_ADDRESS_PROPERTY'''. | ||
+ | <source lang="java"> | ||
+ | WebService service = new WebService( "".getClass().getResource( "ru.bgcrm.plugin.ocu.wsdl.ws1c.wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); | ||
+ | |||
+ | WebServicePortType port = service.getWebServiceSoap(); | ||
+ | |||
+ | Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext(); | ||
+ | requestContext.put( BindingProvider.USERNAME_PROPERTY, username ); | ||
+ | requestContext.put( BindingProvider.PASSWORD_PROPERTY, pswd ); | ||
+ | requestContext.put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws" ); | ||
+ | |||
+ | // вызов собственно функции сервиса | ||
+ | String client = port.getClientByINN( "1234567890" ); | ||
+ | </source> |
Версия 09:39, 17 июля 2013
Содержание |
Генерация кода и обращение к сервису
1. Получение WSDL файла с описанием сервиса. Загрузка браузером либо иным способом по URL вида: http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl WSDL файла. Сохраняем в файл, назовём его ws1c.wsdl.
2. Генерация Java классов на основании WSDL описания с помощью утилиты wsimport Oracle JDK, исходные файлы генерируются в пакет ru.bgcrm.plugin.ocu.ws, корневой каталог исходников ~/workspace/CRM/src.
/opt/java/jdk/bin/wsimport ws1c.wsdl -Xnocompile -keep -extension -d ~/workspace/CRM/src -p ru.bgcrm.plugin.ocu.ws
3. Пример вызова Web сервиса:
import ru.bgcrm.plugin.ocu.ws.WebService; import ru.bgcrm.plugin.ocu.ws.WebServicePortType; .... // код где-то внутри функции WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); WebServicePortType port = service.getWebServiceSoap(); // вызов собственно функции сервиса String client = port.getClientByINN( "1234567890" );
Здесь:
- http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws - URL, по которому доступен сервис.
- http://ws1c.ufanet.ru - targetNamespace Web-сервиса.
- WebService - name Web-сервиса.
Параметры targetNamespace и name отображаются в начале WSDL описания, в данном случае так:
<definitions name="WebService" targetNamespace="http://ws1c.ufanet.ru"> <types> ...
Название класса-сервиса и класса-порта (WebService и WebServicePortType) может различаться для разных сервисов.
Http Basic авторизация
Для Basic авторизации при вызове сервиса нужно дополнить вызов следующим кодом:
.... // код где-то внутри функции WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); WebServicePortType port = service.getWebServiceSoap(); Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext(); requestContext.put( BindingProvider.USERNAME_PROPERTY, <username> ); requestContext.put( BindingProvider.PASSWORD_PROPERTY, <pswd> ); // вызов собственно функции сервиса String client = port.getClientByINN( "1234567890" );
Http Basic авторизация включая WSDL описание
Если и WSDL описание сервиса возвращается только по Basic авторизации, то предыдущий пример упадёт на строке создания самого сервиса:
WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) );
Найдено два способа обойти проблему:
Способ первый
Authenticator.setDefault( new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { // можно дополнительно анализировать this.getRequestingURL().toString() return new PasswordAuthentication( username, pswd.toCharArray() ); } } ); WebService service = new WebService( new URL( "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws?wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); WebServicePortType port = service.getWebServiceSoap(); // вызов собственно функции сервиса String client = port.getClientByINN( "1234567890" );
При этом данный код становится ненужным:
Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext(); requestContext.put( BindingProvider.USERNAME_PROPERTY, <username> ); requestContext.put( BindingProvider.PASSWORD_PROPERTY, <pswd> );
Способ плох тем, что:
- При наличии обращений к нескольким сервисам придётся в аунтификаторе анализировать URL ендпоинта сервиса и по нему предлагать логины-пароли, придётся создать глобальное хранилище этих паролей.
- При изменении пароля придётся дорабатывать аунтификатор, чтобы пароли не кэшировались (по-умолчанию они запрашиваются только один раз), либо кэш сбрасывать.
- Аунтификатор устанавливается на всю Java машину и при обращении к нескольким Web-сервисам в разных местах приложения постоянно придётся следить за данным глобальным аунтификатором, чтобы никто его не перетёр.
- Потоконебезопасный способ, теоретически в момент между установкой аунтификатора и созданием сервиса может вклиниться другой поток со своим аунтификатором.
Способ второй (предпочтительный)
В создание сервиса передать WSDL из файла либо classpath (предпочтительнее). Т.к. в WSDL описании получается и адрес самого сервиса (endpoint), то далее он переопределяется с помощью опции ENDPOINT_ADDRESS_PROPERTY.
WebService service = new WebService( "".getClass().getResource( "ru.bgcrm.plugin.ocu.wsdl.ws1c.wsdl" ), new QName( "http://ws1c.ufanet.ru", "WebService" ) ); WebServicePortType port = service.getWebServiceSoap(); Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext(); requestContext.put( BindingProvider.USERNAME_PROPERTY, username ); requestContext.put( BindingProvider.PASSWORD_PROPERTY, pswd ); requestContext.put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws" ); // вызов собственно функции сервиса String client = port.getClientByINN( "1234567890" );