Статьи

Использование Maven для генерации привязанных или неупакованных привязок SOAP


Для данного WSDL существует несколько различных способов генерации кода веб-службы Java (CXF, Axis2 и т. Д.).
И в зависимости от определенных настроек в файле WSDL и настроек, используемых соответствующим инструментом сборки, существуют разные способы предоставления этих сервисов, описанных в WSDL.

В этом посте будет кратко описана генерация кода Java для WSDL с использованием Maven и
плагина jaxws wsimport . Это также покажет разницу в службах, предоставляемых при использовании обернутых и неупакованных привязок.

Ниже приводится выдержка из файла pom.xml для генерации кода Java:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>1.10</version>
    <executions>
        <execution>
            <goals>
                <goal>wsimport</goal>
            </goals>
            <configuration>
                <wsdlFiles>
                    <wsdlFile>City81SOAPService.wsdl</wsdlFile>
                </wsdlFiles>
                <bindingDirectory>${basedir}/src/wsdl</bindingDirectory>
            </configuration>
            <id>generate-sources</id>
            <phase>generate-sources</phase>
        </execution>
    </executions>
    <dependencies>
         .........           
    </dependencies>
    <configuration>
        <sourceDestDir>
            ${project.build.directory}/generated-sources/jaxws-wsimport
        </sourceDestDir>
        <xnocompile>true</xnocompile>
        <verbose>true</verbose>
        <extension>true</extension>
        <catalog>${basedir}/src/jax-ws-catalog.xml</catalog>                 
    </configuration>
</plugin>

Для приведенного ниже WSDL-файла плагин wsimport сгенерирует следующие классы:

com \ city81 \ soap \ Balance.java
com \ city81 \ soap \ City81SOAP.java
com \ city81 \ soap \ City81SOAPImplService.java
com \ city81 \ soap \ CreateCustomer. java
com \ city81 \ soap \ CreateCustomerResponse.java
com \ city81 \ soap \ CreateCustomerResponseType.java
com \ city81 \ soap \ CreateStatus.java
com \ city81 \ soap \ ObjectFactory.java
com \ city81 \ soap \ package-info.java

<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="City81SOAPService" targetNamespace=http://soap.city81.com/ xmlns:ns1=http://schemas.xmlsoap.org/wsdl/soap/http
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://soap.city81.com/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
    <wsdl:types>
        <xsd:schema>
            <xsd:import namespace="http://soap.city81.com/" schemaLocation="City81SOAPService.xsd" />
        </xsd:schema>
    </wsdl:types>
 
    <wsdl:message name="createCustomer">
        <wsdl:part name="params" element="tns:createCustomer"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="createCustomerResponse">
        <wsdl:part name="params" element="tns:createCustomerResponse"></wsdl:part>
    </wsdl:message>
 
    <wsdl:portType name="City81SOAP">
        <wsdl:operation name="createCustomer">
            <wsdl:input message="tns:createCustomer"></wsdl:input>
            <wsdl:output message="tns:createCustomerResponse"></wsdl:output>
        </wsdl:operation>
    </wsdl:portType>
 
    <wsdl:binding name="City81SOAPImplServiceSoapBinding" type="tns:City81SOAP">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="createCustomer">
            <soap:operation soapAction="http://soap.city81.com/createCustomer" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
 
    <wsdl:service name="City81SOAPImplService">
        <wsdl:port binding="tns:City81SOAPImplServiceSoapBinding" name="City81SOAPImplPort">
            <soap:address location=http://localhost:8080/city81-soap/soap />
        </wsdl:port>
    </wsdl:service>
 
</wsdl:definitions>

Для указанных выше настроек сгенерированный
класс
City81SOAP будет выглядеть следующим образом:

@WebService(name = "City81SOAP", targetNamespace = "http://soap.city81.com/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class
})
public interface City81SOAP {
 
    @WebMethod(action = "http://soap.city81.com/createCustomer")
    @WebResult(name = "createCustomerResponse", targetNamespace = "http://soap.city81.com/", partName = "params")
    public CreateCustomerResponse createCustomer(@WebParam(name = "createCustomer", targetNamespace = "http://soap.city81.com/", partName = "params") CreateCustomer params);
 
}

Стиль привязки, как видно из  аннотации @SOAPBinding в
начале класса, — BARE, то есть не обернутый. Аргументы метода и возвращаемые параметры в каждом случае представлены как один объект Java.
CreateCustomer и
CreateCustomerResponse .

Это произошло потому , что в файле pom.xml, есть
bindingDirectory тег , который указывает на папку , содержащую
binding.xml файл. Этот файл, показанный ниже, имеет
тег
enableWrapperStyle и логическое значение false.

<bindings
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    wsdlLocation="City81SOAPService.wsdl"
    xmlns="http://java.sun.com/xml/ns/jaxws">
        <!-- Disable default wrapper style -->
        <enableWrapperStyle>false</enableWrapperStyle>       
</bindings>

Если логическое значение равно true, или если в файле pom.xml нет
тега bindingDirectory, то будет использоваться стиль привязки SOAP по умолчанию, т.е.
WRAPPED . Это приведет к созданию сгенерированного ниже
класса City81SOAP :

@WebService(name = "City81SOAP", targetNamespace = "http://soap.city81.com/")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface City81SOAP {
 
    @WebMethod(action = "http://soap.city81.com/createCustomer")
    @RequestWrapper(localName = "createCustomer", targetNamespace = "http://soap.city81.com/", className = "com.city81.soap.CreateCustomer")
    @ResponseWrapper(localName = "createCustomerResponse", targetNamespace = "http://soap.city81.com/", className = "com.city81.soap.CreateCustomerResponse")
    public void createCustomer(
 
        @WebParam(name = "surname", targetNamespace = "")
        String surname,
        @WebParam(name = "firstName", targetNamespace = "")
        String firstName,
        @WebParam(name = "balance", targetNamespace = "")
        Balance balance,
        @WebParam(name = "customerId", targetNamespace = "", mode = WebParam.Mode.OUT)
        Holder<String> customerId,
        @WebParam(name = "status", targetNamespace = "", mode = WebParam.Mode.OUT)
        Holder<CreateStatus> status);
 
}

Аргументы метода теперь являются отдельными объектами Java, и каждый из возвращаемых параметров представляется в виде
объектов
Holder со
значением
WebParam.Mode.OUT, обозначающим, что они являются возвращаемыми объектами. Это означает, что возвращаемые объекты устанавливаются, а не возвращаются в сигнатуре метода.

Другой способ указать другие привязок , чем при использовании
binding.xml файла является встраивать
enableWrapperStyle как дочерний
PortType но если WSDL от третьей стороны, то необходимости менять его каждый раз , когда новая версия WSDL будет отпущена открыты для ошибок.

<wsdl:portType name="City81SOAPImplService">
    <jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
        <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
    </jaxws:bindings>
    ...
</wsdl:portType>

Вернемся к сгенерированным интерфейсам, и они, конечно, должны быть реализованы. Для интерфейса с типом привязки
BARE реализованный класс будет выглядеть следующим образом:

@WebService(targetNamespace = "http://soap.city81.com/", name = "City81SOAP", portName = "City81SOAPImplPort", serviceName = "City81SOAPImplService")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class City81SOAPImpl implements City81SOAP {   
 
    @Override  
    public CreateCustomerResponse createCustomer(CreateCustomer createCustomer) {     
        CreateCustomerResponse createCustomerResponse =
            new CreateCustomerResponse();    
         .....
        return createCustomerResponse; 
    }
}

В случае
завернутые связывания стиля,
SOAPBinding аннотации будет включать
parameterStyle = SOAPBinding.ParameterStyle.WRAPPED и
createCustomer метод будет , как показано ниже:

public void createCustomer(
    String surname,
    String firstName,
    Balance balance,
    Holder<String> customerId,
    Holder<CreateStatus> status) {
 
    customerId= new Holder<String>("1");
    status = new Holder<CreateStatus>(CreateStatus.CREATE_PENDING);
} 

Этот пост показывает, что существуют разные способы достижения одинакового результата.