Обращение к Web-сервису

Материал из BiTel WiKi

Перейти к: навигация, поиск

Содержание

Генерация кода и обращение к сервису

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" );

Здесь:

  1. http://bumer.core.ufanet.ru/ufanettest/ws/ws1c.1cws - URL, по которому доступен сервис.
  2. http://ws1c.ufanet.ru - targetNamespace Web-сервиса.
  3. 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> );

Способ плох тем, что:

  1. При наличии обращений к нескольким сервисам придётся в аунтификаторе анализировать URL ендпоинта сервиса и по нему предлагать логины-пароли, придётся создать глобальное хранилище этих паролей.
  2. При изменении пароля придётся дорабатывать аунтификатор, чтобы пароли не кэшировались (по-умолчанию они запрашиваются только один раз), либо кэш сбрасывать.
  3. Аунтификатор устанавливается на всю Java машину и при обращении к нескольким Web-сервисам в разных местах приложения постоянно придётся следить за данным глобальным аунтификатором, чтобы никто его не перетёр.
  4. Потоконебезопасный способ, теоретически в момент между установкой аунтификатора и созданием сервиса может вклиниться другой поток со своим аунтификатором.

Способ второй (предпочтительный)

В создание сервиса передать 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" );
Личные инструменты