Введение в JAX-WS

1. Обзор

Java API для веб-служб XML (JAX-WS) - это стандартизированный API-интерфейс для создания и использования веб-служб SOAP (Simple Object Access Protocol).

В этой статье мы создадим веб-сервис SOAP и подключимся к нему с помощью JAX-WS.

2. МЫЛО

SOAP - это спецификация XML для отправки сообщений по сети.

SOAP тяжело работает с XML, поэтому лучше всего его использовать с инструментами/средами JAX-WS - это инфраструктура, которая упрощает использование SOAP. Это часть стандартной Java.

3. Сверху вниз против снизу вверх

Существует два способа создания веб-сервисов SOAP. Мы можем пойти с подходом сверху вниз или снизу вверх.

При нисходящем (сначала контрактном) подходе создается документ WSDL, а необходимые классы Java генерируются из WSDL. В восходящем (контракт-последний) подходе,

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

4. Язык определения веб-сервисов (WSDL)

WSDL - определение контракта доступных сервисов. Это спецификация входных/выходных сообщений и способ вызова веб-службы. Он не зависит от языка и определен в XML.

Давайте посмотрим на основные элементы документа WSDL.

4.1. Определения

Элемент definitions является корневым элементом всех документов WSDL. Он определяет имя, пространство имен и т. Д. Службы и, как вы можете видеть, может быть довольно просторным

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="http://jaxws.baeldung.com/"
  xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
  xmlns:wsp="http://www.w3.org/ns/ws-policy"
  xmlns:wsp1__2="http://schemas.xmlsoap.org/ws/2004/09/policy"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://jaxws.baeldung.com/"
  name="EmployeeService">
  ...
</definitions>

4.2. Типы

Элемент types определяет типы данных, используемые веб-сервисом. WSDL использует XSD (определение схемы XML) в качестве системы типов, которая помогает с функциональной совместимостью:

<definitions ...>
    ...
    <types>
        <xsd:schema>
            <xsd:import namespace="http://jaxws.baeldung.com/"
              schemaLocation = "http://localhost:8080/employeeservice?xsd=1"/>
        </xsd:schema>
    </types>
    ...
</definitions>

4.3. Сообщения

Элемент message обеспечивает абстрактное определение передаваемых данных. Каждый элемент message описывает ввод или вывод метода службы и возможные исключения:

<definitions ...>
    ...
    <message name="getEmployee">
        <part name="parameters" element="tns:getEmployee"/>
    </message>
    <message name="getEmployeeResponse">
        <part name="parameters" element="tns:getEmployeeResponse"/>
    </message>
    <message name="EmployeeNotFound">
        <part name="fault" element="tns:EmployeeNotFound"/>
    </message>
    ...
</definitions>

4.4. Операции и типы портов

Элемент portType описывает каждую операцию operation , которая может быть выполнена, и все задействованные элементы message . Например, операция getEmployee указывает запрос input , output и возможное исключение fault , выданное веб-службой operation :

<definitions ...>
    ...
    <portType name="EmployeeService">
        <operation name="getEmployee">
            <input
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeRequest"
              message="tns:getEmployee"/>
            <output
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeResponse"
              message="tns:getEmployeeResponse"/>
            <fault message="tns:EmployeeNotFound" name="EmployeeNotFound"
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployee/Fault/EmployeeNotFound"/>
        </operation>
    ....
    </portType>
    ...
</definitions>

4.5. Наручники

Элемент binding предоставляет подробности протокола и формата данных для каждого portType :

<definitions ...>
    ...
    <binding name="EmployeeServiceImplPortBinding"
      type="tns:EmployeeService">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
          style="document"/>
        <operation name="getEmployee">
            <soap:operation soapAction=""/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
            <fault name="EmployeeNotFound">
                <soap:fault name="EmployeeNotFound" use="literal"/>
            </fault>
        </operation>
        ...
    </binding>
    ...
</definitions>

4.6. Услуги и порты

Элемент service определяет порты, поддерживаемые веб-службой.

Элемент port в service определяет name , binding и адрес службы:

<definitions ...>
    ...
    <service name="EmployeeService">
        <port name="EmployeeServiceImplPort"
          binding="tns:EmployeeServiceImplPortBinding">
            <soap:address
              location="http://localhost:8080/employeeservice"/>
        </port>
    </service>
    ...
</definitions>

5. Подход сверху вниз (контракт-первый)

Давайте начнем с нисходящего подхода, создав файл WSDL.

<?xml version="1.0" encoding="UTF-8"?>
<definitions
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="http://topdown.server.jaxws.baeldung.com/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.xmlsoap.org/wsdl/"
  targetNamespace="http://topdown.server.jaxws.baeldung.com/"
  qname="EmployeeServiceTopDown">
    <types>
        <xsd:schema
          targetNamespace="http://topdown.server.jaxws.baeldung.com/">
            <xsd:element name="countEmployeesResponse" type="xsd:int"/>
        </xsd:schema>
    </types>

    <message name="countEmployees">
    </message>
    <message name="countEmployeesResponse">
        <part name="parameters" element="tns:countEmployeesResponse"/>
    </message>
    <portType name="EmployeeServiceTopDown">
        <operation name="countEmployees">
            <input message="tns:countEmployees"/>
            <output message="tns:countEmployeesResponse"/>
        </operation>
    </portType>
    <binding name="EmployeeServiceTopDownSOAP"
      type="tns:EmployeeServiceTopDown">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
          style="document"/>
        <operation name="countEmployees">
            <soap:operation
              soapAction="http://topdown.server.jaxws.baeldung.com/              EmployeeServiceTopDown/countEmployees"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="EmployeeServiceTopDown">
        <port name="EmployeeServiceTopDownSOAP"
          binding="tns:EmployeeServiceTopDownSOAP">
            <soap:address
              location="http://localhost:8080/employeeservicetopdown"/>
        </port>
    </service>
</definitions>

5.1. Генерация исходных файлов веб-службы из WSDL

Чтобы сгенерировать исходные файлы веб-службы из документа WSDL, мы можем использовать инструмент wsimport , который является частью JDK (по ссылке:/java-home-on-windows-7-8-10-mac-os-x-linux[$ JAVA__HOME]/BIN).

Из командной строки:

wsimport -s . -p com.baeldung.jaxws.server.topdown employeeservicetopdown.wsdl

Используемые параметры командной строки: -p указывает целевой пакет. -s указывает, куда поместить сгенерированные исходные файлы.

Сгенерированные файлы:

  • EmployeeServiceTopDown.java - это интерфейс конечной точки сервиса

(SEI), который содержит определения методов ** ObjectFactory.java - содержит фабричные методы для создания экземпляров

Схема производных классов программно ** EmployeeServiceTopDown Service.java__ - это класс поставщика услуг

который может использоваться клиентом JAX-WS

5.2. Интерфейс конечной точки веб-службы

Инструмент wsimport создал интерфейс конечной точки веб-службы EmployeeServiceTopDown . Он объявляет методы веб-службы:

@WebService(
  name = "EmployeeServiceTopDown",
  targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class
})
public interface EmployeeServiceTopDown {
    @WebMethod(
      action = "http://topdown.server.jaxws.baeldung.com/"
      + "EmployeeServiceTopDown/countEmployees")
    @WebResult(
      name = "countEmployeesResponse",
      targetNamespace = "http://topdown.server.jaxws.baeldung.com/",
      partName = "parameters")
    public int countEmployees();
}

5.3. Реализация веб-сервиса

Инструмент wsimport создал структуру веб-сервиса. Мы должны создать реализацию веб-сервиса:

@WebService(
  name = "EmployeeServiceTopDown",
  endpointInterface = "com.baeldung.jaxws.server.topdown.EmployeeServiceTopDown",
  targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
public class EmployeeServiceTopDownImpl
  implements EmployeeServiceTopDown {

    @Inject
    private EmployeeRepository employeeRepositoryImpl;

    @WebMethod
    public int countEmployees() {
        return employeeRepositoryImpl.count();
    }
}

6. Подход снизу вверх (контракт-последний)

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

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

6.1. Модельный класс

Модель Employee :

public class Employee {
    private int id;
    private String firstName;

   //standard getters and setters
}

6.2. Интерфейс конечной точки веб-службы

Интерфейс конечной точки веб-службы, который объявляет методы веб-службы:

@WebService
public interface EmployeeService {
    @WebMethod
    Employee getEmployee(int id);

    @WebMethod
    Employee updateEmployee(int id, String name);

    @WebMethod
    boolean deleteEmployee(int id);

    @WebMethod
    Employee addEmployee(int id, String name);

   //...
}

Этот интерфейс определяет абстрактный контракт для веб-службы. Использованные аннотации:

**

**

  • @ WebResult используется для настройки имени элемента XML, который

представляет возвращаемое значение

6.3. Реализация веб-сервиса

Класс реализации интерфейса конечной точки веб-службы:

@WebService(endpointInterface = "com.baeldung.jaxws.EmployeeService")
public class EmployeeServiceImpl implements EmployeeService {

    @Inject
    private EmployeeRepository employeeRepositoryImpl;

    @WebMethod
    public Employee getEmployee(int id) {
        return employeeRepositoryImpl.getEmployee(id);
    }

    @WebMethod
    public Employee updateEmployee(int id, String name) {
        return employeeRepositoryImpl.updateEmployee(id, name);
    }

    @WebMethod
    public boolean deleteEmployee(int id) {
        return employeeRepositoryImpl.deleteEmployee(id);
    }

    @WebMethod
    public Employee addEmployee(int id, String name) {
        return employeeRepositoryImpl.addEmployee(id, name);
    }

   //...
}

7. Публикация конечных точек веб-службы

Чтобы опубликовать веб-сервисы (сверху вниз и снизу вверх), нам нужно передать адрес и экземпляр реализации веб-сервиса методу publish () класса javax.xml.ws.Endpoint :

public class EmployeeServicePublisher {
    public static void main(String[]args) {
        Endpoint.publish(
          "http://localhost:8080/employeeservicetopdown",
           new EmployeeServiceTopDownImpl());

        Endpoint.publish("http://localhost:8080/employeeservice",
          new EmployeeServiceImpl());
    }
}

Теперь мы можем запустить EmployeeServicePublisher , чтобы запустить веб-сервис. Чтобы использовать функции CDI, веб-службы могут быть развернуты в виде файла WAR на серверах приложений, таких как WildFly или GlassFish.

8. Клиент удаленного веб-сервиса

Теперь давайте создадим клиент JAX-WS для удаленного подключения к веб-службе EmployeeService .

8.1. Генерация клиентских артефактов

Чтобы сгенерировать клиентские артефакты JAX-WS, мы снова можем использовать инструмент wsimport :

wsimport -keep -p com.baeldung.jaxws.client http://localhost:8080/employeeservice?wsdl

Сгенерированный класс EmployeeService Service инкапсулирует логику для получения порта сервера, используя URL и QName__.

8.2. Подключение к веб-сервису

Клиент веб-службы использует сгенерированный EmployeeService Service__ для подключения к серверу и удаленного вызова веб-службы:

public class EmployeeServiceClient {
    public static void main(String[]args) throws Exception {
        URL url = new URL("http://localhost:8080/employeeservice?wsdl");

        EmployeeService__Service employeeService__Service
          = new EmployeeService__Service(url);
        EmployeeService employeeServiceProxy
          = employeeService__Service.getEmployeeServiceImplPort();

        List<Employee> allEmployees
          = employeeServiceProxy.getAllEmployees();
    }
}

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

Эта статья представляет собой краткое введение в веб-службы SOAP с использованием JAX-WS .

Мы использовали как восходящий, так и нисходящий подходы к созданию веб-сервисов SOAP с использованием API JAX-WS. Мы также написали клиент JAX-WS, который может удаленно подключаться к серверу и выполнять вызовы веб-службы.

Полный исходный код доступен на over на GitHub .