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