Java – soap WS – make @ webparam optional
I have a very simple method. I use jax-ws annotation in WS API:
@WebMethod public MyResponse sendSingle2( @WebParam(name="username") String username,@WebParam(name="password") String password,@WebParam(name="newParam") String newParam) { // the code }
Now I want newparam to be optional I mean, I want this method to still work, not just when passing an XML parameter that is empty:
<ws:sendSingle2> <username>user</username> <password>pass</password> <newParam></newParam> </ws:sendSingle2>
And when it doesn't exist:
<ws:sendSingle2> <username>user</username> <password>pass</password> </ws:sendSingle2>
I need it not to break the existing API without new parameters
Solution
In general, the selectability of parameters is set by the mode minoccurs = 0 In addition, you can define a request parameter in the schema instead of using multiple parameters. You define it as the parameter of webmethod Optionality is now encapsulated in parameters, and the same method is called for calls with or without optional parameters
I prefer to define the contract first rather than rely on automatically generated files Once you know how XSD, soap and WSDL play together, you don't have to use annotation / code based definitions because you have more flexibility
Code example:
<xs:schema targetNamespace="http://your.namespace.com" xmlns:tns="http://your.namespace.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFromDefault="qualified" attributeFromDefault="qualified"> ... <xs:element name="MyRequest" type="tns:MyRequestType" /> <xs:element name="MyResponse" type="tns:MyResponseType" /> <xs:complexType name"MyRequestType"> <xs:sequence> <xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1" /> <xs:element name="password" type="xs:string" minOccurs="1" maxOccurs="1" /> <xs:element name="newParam" type="xs:string" minOccurs="0" maxOccurs="1" /> </xs:sequence> </xs:complexType> ... </xs:schema>
In your WSDL file, you define the following message:
<wsdl:deFinitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:msg="http://your.namespace.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" targetNamespace="http://your.namespace.com"> <wsdl:types> <xs:schema> <!-- either import the externalized schema --> <xs:import namespace="http://your.namespace.com" schemaLocation="someDir/yourMessageSchema.xsd" /> </xs:schema> <!-- or define the schema within the WSDL - just copy the schema here --> <xs:schema targetNamespace="http://your.namespace.com" xmlns:tns="http://your.namespace.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFromDefault="qualified" attributeFromDefault="qualified"> ... </xs:schema> </wsdl:types> ... <wsdl:message name="sendSingle2Request"> <wsdl:part name="in" element="msg:MyRequest" /> </wsdl:message> <wsdl:message name="sendSingle2Response"> <wsdl:part name="out" element="msg:MyResponse" /> </wsdl:message> ... <wsdl:portType name="YourServiceEndpoint"> <wsdl:operation name="sendSingle2"> <wsdl:input message="tns:sendSingle2Request" /> <wsdl:output message="tns:sendSingle2Response" /> </wsdl:operation> ... </wsdl:portType> <wsdl:binding name="YourServiceBinding" type="YourServiceEndpoint"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name=""sendSingle2"> <soap:operation soapAction="http://your.namespace.com/SendSingle2" style="document" /> <wsdl:input> <soap:body parts="in" use="literal" /> </wsdl:input> <wsdl:output> <soap:body parts="out" use="literal" /> </wsdl:output> </wsdl:operation> ... </wsdl:binding> <wsdl:service name="YourService"> <wsdl:port name="YourServicePort binding="tns:YourServiceBinding"> <soap:address location="http://your.server:port/path/to/the/service" /> </wsdl:port> </wsdl:service> </wsdl:deFinitions>
The WSDL protocol here is defined as using style: document / literal, and with the help of the schema, the actual SOAP message will be wrapped in document / text. In addition, WS-I is compatible
Therefore, your method will be changed to public myresponse sendsinge2 (myrequest request), where the request now encapsulates username, passowrd, and newparam If newparam does not send a soap request, it will only return null, so check it before using it
If you insist on using code first methods, you need to first define your myrequest class and use it as a request parameter instead of a value of 2 or 3
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "MyRequest",namespace="http://your.namespace.com") public class MyRequest implements Serializable { @XmlElement(name = "username",required = true) protected String username; @XmlElement(name = "password",required = true) protected String password; @XmlElement(name = "newParam",required = false) protected String newParam; ... }
If not, myresult should do the same Web methods can now look like this:
@WebMethod(operationName = "sendSingle2") @WebResult(name = "sendSingle2Response",targetNamespace = "http://your.namespace.com") public MyResult sendSingle2(@WebParam(name = "sendSingle2Request") MyRequest request) { ... }
Again, request to encapsulate your first parameter. You can check whether the optional parameter is empty
HTH