Рубрики
Без рубрики

Вызов веб-службы SOAP в Java

Узнайте, как создать SOAP-клиент на Java с помощью JAX-WS RI.

Автор оригинала: Sampada Wagde.

1. Обзор

В этом уроке мы узнаем, как создать SOAP-клиент на Java с помощью JAX-WS RI . Сначала мы сгенерируем клиентский код с помощью утилиты wsimport , а затем протестируем его с помощью JUnit.

Для тех, кто только начинает, наше введение в JAX-WS дает отличную информацию по этому вопросу.

2. Веб-Служба

Прежде чем мы начнем создавать клиент, нам нужен сервер. В этом случае сервер предоставляет веб-службу JAX-WS.

Для целей этого урока мы будем использовать веб-сервис, который будет получать данные о стране, учитывая ее название.

2.1. Резюме осуществления

Поскольку мы сосредоточены на создании клиента, мы не будем вдаваться в детали реализации нашего сервиса.

Достаточно сказать, что интерфейс Country Service используется для предоставления веб-службы внешнему миру. Чтобы все было просто, мы создадим и развернем веб-службу с помощью javax.xml.ws.Endpoint API в нашем классе CountryServicePublisher .

Мы запустим Country Service Publisher как Java-приложение для публикации конечной точки, которая будет принимать входящие запросы. Другими словами, это будет наш сервер.

После запуска сервера нажмите на URL-адрес http://localhost:8888/ws/country?wsdl предоставляет нам файл описания веб-службы. WSDL служит руководством для понимания предложений службы и создания кода реализации для клиента.

2.2. Язык Описания Веб-Сервисов

Давайте посмотрим на WSDL нашего веб-сервиса, страна :



    targetNamespace="http://server.ws.soap.baeldung.com/" name="CountryServiceImplService">
    
        
            
        
    
    
        
    
    
        
    
    
        
            
            
        
    
    
        
        
            
            
                
            
            
                
            
        
    
    
        
            
        
    

В двух словах, это полезная информация, которую он предоставляет:

  • мы можем вызвать метод findByName с аргументом string
  • в ответ сервис вернет нам пользовательский тип страны
  • типы определяются в схеме xsd , созданной в местоположении http://localhost:8888/ws/country?xsd=1 :


    targetNamespace="http://server.ws.soap.baeldung.com/">
    
        
            
            
            
            
        
    
    
        
            
            
            
        
    

Это все, что нам нужно для реализации клиента.

Давайте посмотрим, как это сделать в следующем разделе.

3. Использование wsimport для создания клиентского кода

3.1. Плагин Maven

Во-первых, давайте добавим плагин в ваш pom.xml чтобы использовать этот инструмент через Maven:

 
    org.codehaus.mojo
    jaxws-maven-plugin
    2.6
     
         
            wsimport-from-jdk
            
                wsimport
            
        
    
    
        
            http://localhost:8888/ws/country?wsdl 
        
        true 
        com.baeldung.soap.ws.client.generated 
        src/main/java
    

Во-вторых, давайте выполним этот плагин:

mvn clean jaxws:wsimport

Вот и все! Приведенная выше команда сгенерирует код в указанном пакете com.baeldung.soap.ws.client.generated внутри sourceDestDir , который мы предоставили в конфигурации плагина.

Другой способ добиться того же – использовать утилиту wsimport //. Он поставляется из коробки со стандартным дистрибутивом JDK 8 и может быть найден в каталоге JAVA_HOME/bin .

Чтобы сгенерировать клиентский код с помощью wsimport , мы можем перейти к корневому каталогу проекта и выполнить эту команду:

JAVA_HOME/bin/wsimport -s src/main/java/ -keep -p com.baeldung.soap.ws.client.generated "http://localhost:8888/ws/country?wsdl"

Важно иметь в виду, что конечная точка службы должна быть доступна для успешного выполнения плагина или команды.

Далее давайте рассмотрим сгенерированные артефакты.

3.2. Генерируемые POJOs

На основе xsd , который мы видели ранее, инструмент создаст файл с именем Country.java :

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "country", propOrder = { "capital", "currency", "name", "population" })
public class Country {
    protected String capital;
    @XmlSchemaType(name = "string")
    protected Currency currency;
    protected String name;
    protected int population;
    // standard getters and setters
}

Как мы видим, сгенерированный класс украшен аннотациями JAXB для маршалинга и разархивирования объекта в XML и из XML.

Кроме того, он генерирует Валюту перечисление:

@XmlType(name = "currency")
@XmlEnum
public enum Currency {
    EUR, INR, USD;
    public String value() {
        return name();
    }
    public static Currency fromValue(String v) {
        return valueOf(v);
    }
}

3.3. Страновая служба

Второй сгенерированный артефакт-это интерфейс, который действует как прокси-сервер для реальной веб-службы.

Интерфейс Country Service объявляет тот же метод, что и наш сервер, findByName :

@WebService(name = "CountryService", targetNamespace = "http://server.ws.soap.baeldung.com/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
@XmlSeeAlso({ ObjectFactory.class })
public interface CountryService {
    @WebMethod
    @WebResult(partName = "return")
    @Action(input = "http://server.ws.soap.baeldung.com/CountryService/findByNameRequest", 
      output = "http://server.ws.soap.baeldung.com/CountryService/findByNameResponse")
    public Country findByName(@WebParam(name = "arg0", partName = "arg0") String arg0);
}

Примечательно, что интерфейс помечен как javax.jws.WebService с привязкой SOAP.Стиль как RPC, как определено WSDL службы.

Метод findByName аннотируется , чтобы объявить, что это javax.jws.WebMethod , с его ожидаемыми типами входных и выходных параметров.

3.4. Сервис CountryServiceImpl

Наш следующий сгенерированный класс, CountryServiceImpl Service , расширяет javax.xml.ws.Service. Его аннотация Клиент веб-службы означает, что это представление клиента службы:

@WebServiceClient(name = "CountryServiceImplService", 
  targetNamespace = "http://server.ws.soap.baeldung.com/", 
  wsdlLocation = "http://localhost:8888/ws/country?wsdl")
public class CountryServiceImplService extends Service {

    private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION;
    private final static WebServiceException COUNTRYSERVICEIMPLSERVICE_EXCEPTION;
    private final static QName COUNTRYSERVICEIMPLSERVICE_QNAME = 
      new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplService");

    static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL("http://localhost:8888/ws/country?wsdl");
        } catch (MalformedURLException ex) {
            e = new WebServiceException(ex);
        }
        COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION = url;
        COUNTRYSERVICEIMPLSERVICE_EXCEPTION = e;
    }

    public CountryServiceImplService() {
        super(__getWsdlLocation(), COUNTRYSERVICEIMPLSERVICE_QNAME);
    }

    // other constructors 

    @WebEndpoint(name = "CountryServiceImplPort")
    public CountryService getCountryServiceImplPort() {
        return super.getPort(new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplPort"), 
          CountryService.class);
    }

    private static URL __getWsdlLocation() {
        if (COUNTRYSERVICEIMPLSERVICE_EXCEPTION != null) {
            throw COUNTRYSERVICEIMPLSERVICE_EXCEPTION;
        }
        return COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION;
    }

}

Важным методом, который следует отметить здесь, является get CountryServiceImpl Port . Учитывая полное имя конечной точки службы или QName и имя интерфейса конечной точки службы динамического прокси-сервера, он возвращает экземпляр прокси-сервера.

Чтобы вызвать веб-службу, нам нужно использовать этот прокси-сервер, как мы вскоре увидим .

Использование прокси-сервера создает впечатление, что мы вызываем службу локально, абстрагируясь от тонкостей удаленного вызова.

4. Тестирование клиента

Затем мы напишем тест JUnit для подключения к веб-службе с помощью сгенерированного клиентского кода.

Прежде чем мы сможем это сделать, нам нужно получить экземпляр прокси-сервера службы на стороне клиента:

@BeforeClass
public static void setup() {
    CountryServiceImplService service = new CountryServiceImplService();
    CountryService countryService = service.getCountryServiceImplPort();
}

Для более сложных сценариев , таких как включение или отключение WebServiceFeature , мы можем использовать другие сгенерированные конструкторы для CountryServiceImplService .

Теперь давайте рассмотрим некоторые тесты:

@Test
public void givenCountryService_whenCountryIndia_thenCapitalIsNewDelhi() {
    assertEquals("New Delhi", countryService.findByName("India").getCapital());
}

@Test
public void givenCountryService_whenCountryFrance_thenPopulationCorrect() {
    assertEquals(66710000, countryService.findByName("France").getPopulation());
}

@Test
public void givenCountryService_whenCountryUSA_thenCurrencyUSD() {
    assertEquals(Currency.USD, countryService.findByName("USA").getCurrency());
}

Как мы видим, вызов методов удаленной службы стал таким же простым, как вызов методов локально. Метод прокси-сервера findByName вернул экземпляр Country , соответствующий name , который мы предоставили. Затем мы использовали различные геттеры POJO для утверждения ожидаемых значений.

5. Заключение

В этом уроке мы рассмотрели, как вызвать веб-службу SOAP на Java с помощью JAX-WS RI и утилиты wsimport .

В качестве альтернативы мы можем использовать другие реализации JAX-WS, такие как Apache CXF, Apache Axis2 и Spring, чтобы сделать то же самое.

Как всегда, исходный код доступен на GitHub .