Для данного 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);
}
Этот пост показывает, что существуют разные способы достижения одинакового результата.