Извикване на SOAP уеб услуга в Java

1. Общ преглед

В този урок ще научим как да изградим SOAP клиент в Java с JAX-WS RI . Първо ще генерираме клиентския код с помощта на помощната програма wsimport и след това ще го тестваме с помощта на JUnit.

За тези, които започват, нашето въведение в JAX-WS предоставя чудесен опит по темата.

2. Уеб услугата

Преди да започнем да изграждаме клиент, се нуждаем от сървър. В този случай сървър, излагащ JAX-WS уеб услуга.

За целите на този урок ще използваме уеб услуга, която ще ни извлече данни за дадена държава, като получи нейното име.

2.1. Резюме на изпълнението

Тъй като се фокусираме върху изграждането на клиента, няма да навлизаме в подробностите за изпълнението на нашата услуга.

Достатъчно е да кажем, че интерфейс CountryService се използва за излагане на уеб услугата на външния свят. За да улесним нещата, ще изградим и внедрим уеб услугата, използвайки javax.xml.ws.Endpoint API в нашия клас CountryServicePublisher .

Ще стартираме CountryServicePublisher като Java приложение, за да публикуваме крайна точка, която ще приема входящите заявки. С други думи, това ще бъде нашият сървър.

След стартиране на сървъра, натискането на URL // localhost: 8888 / ws / country? Wsdl ни дава файл с описание на уеб услугата. WSDL действа като ръководство за разбиране на предложенията на услугата и генериране на код за изпълнение за клиента.

2.2. Език за описание на уеб услугите

Нека да разгледаме WSDL на нашата уеб услуга, държава :


    

Накратко, това е полезната информация, която тя предоставя:

  • можем да извикаме метода findByName с аргумент низ
  • в отговор услугата ще ни върне персонализиран тип държава
  • типовете са дефинирани в xsd схема, генерирана на местоположението // localhost: 8888 / ws / country? xsd = 1 :

    

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

Нека да видим как в следващия раздел.

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

3.1. Плъгин Maven

Първо, нека добавим приставка към нашия pom.xml, за да използваме този инструмент чрез Maven:

 org.codehaus.mojo jaxws-maven-plugin 2.6   wsimport-from-jdk  wsimport      //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 "//localhost:8888/ws/country?wsdl"

Важно е да се има предвид, че крайната точка на услугата трябва да е достъпна, за да се изпълни успешно приставката или командата.

След това нека разгледаме генерираните артефакти.

3.2. Генерирани POJO

Въз основа на 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.

Също така, той генерира изброяване на валута :

@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. CountryService

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

Интерфейсът CountryService декларира същия метод като нашия сървър, findByName :

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

Забележително е, че интерфейсът е маркиран като javax.jws.WebService , със SOAPBinding.Style като RPC, както е определено от WSDL на услугата.

Методът findByName е анотиран, за да декларира, че е javax.jws.WebMethod , с очакваните типове входни и изходни параметри.

3.4. CountryServiceImplService

Следващата ни генерира клас, CountryServiceImplService , се простира javax.xml.ws.Service. Неговата анотация WebServiceClient означава, че това е клиентският изглед на услуга:

@WebServiceClient(name = "CountryServiceImplService", targetNamespace = "//server.ws.soap.baeldung.com/", wsdlLocation = "//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("//server.ws.soap.baeldung.com/", "CountryServiceImplService"); static { URL url = null; WebServiceException e = null; try { url = new URL("//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("//server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService.class); } private static URL __getWsdlLocation() { if (COUNTRYSERVICEIMPLSERVICE_EXCEPTION != null) { throw COUNTRYSERVICEIMPLSERVICE_EXCEPTION; } return COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; } }

Важният метод, който трябва да отбележите тук, е getCountryServiceImplPort . Като се има предвид квалифицирано име на крайната точка на услугата или QName и името на интерфейса на крайната точка на услугата на динамичния прокси сървър, тя връща прокси екземпляр.

За да извикаме уеб услугата, трябва да използваме този прокси, както ще видим скоро .

Using a proxy makes it seem as if we are calling a service locally, abstracting away the intricacies of remote invocation.

4. Testing the Client

Next, we'll write a JUnit test to connect to the web service using the generated client code.

Before we can do that, we need to get the service's proxy instance at the client end:

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

For more advanced scenarios such as enabling or disabling a WebServiceFeature, we can use other generated constructors for CountryServiceImplService.

Now let's look at some tests:

@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 на прокси върна екземпляр на държава, съответстващ на името, което предоставихме. След това използвахме различни гетери на POJO, за да отстояваме очакваните стойности.

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

В този урок видяхме как да извикаме SOAP уеб услуга в Java, използвайки JAX-WS RI и помощната програма wsimport .

Като алтернатива можем да използваме други реализации на JAX-WS като Apache CXF, Apache Axis2 и Spring, за да направим същото.

Както винаги, изходният код е достъпен в GitHub.