Java SOAP WS - 使 @WebParam 可选
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21179098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SOAP WS - make @WebParam optional
提问by amorfis
I have quite a simple method, which I use in WS API by JAX-WS annotations:
我有一个非常简单的方法,我通过 JAX-WS 注释在 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 the method still to work not only when parameter is empty in passed xml:
现在我希望 newParam 是可选的。我的意思是我希望该方法不仅在传递的 xml 中的参数为空时仍然有效:
<ws:sendSingle2>
<username>user</username>
<password>pass</password>
<newParam></newParam>
</ws:sendSingle2>
but also when it is absent:
但当它不存在时:
<ws:sendSingle2>
<username>user</username>
<password>pass</password>
</ws:sendSingle2>
I need it not to break existing API, which works without the new param.
我需要它不要破坏现有的 API,它可以在没有新参数的情况下工作。
采纳答案by Roman Vottner
@WebParam maps a message part to a parameter, and parts can't be optional. See Optional Message Parts in WSDL. Therefore the short answer is that precisely what you're asking can't be done. But if you can refactor this method, you can use one of the approaches described below.
@WebParam 将消息部分映射到参数,部分不能是可选的。请参阅WSDL 中的可选消息部分。因此,简短的回答是,您所要求的正是无法完成的。但是,如果您可以重构此方法,则可以使用下面描述的方法之一。
Usually the optionality of a parameter is set via the schema minOccurs=0
. Furthermore, instead of using multiple parameters you could define one Request parameter in your schema which you define as parameter for your WebMethod
. The optionality is now encapsulated within the parameter and the same method is invoked for a call with or without the optional parameter(s).
通常参数的可选性是通过 schema 设置的minOccurs=0
。此外,您可以在架构中定义一个请求参数,而不是使用多个参数,您将其定义为WebMethod
. 可选性现在封装在参数中,并且为带有或不带有可选参数的调用调用相同的方法。
I prefer defining the contract first instead of relying on automatically generated files. Once you figured out how XSD, SOAP and WSDL play in-together, you hardly want to use annotation/code-first based definitions any longer as you are more flexible the other way around.
我更喜欢先定义合同,而不是依赖自动生成的文件。一旦您弄清楚 XSD、SOAP 和 WSDL 如何结合在一起,您就几乎不想再使用基于注释/代码优先的定义,因为反过来您会更加灵活。
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 message like that:
在您的 WSDL 文件中,您可以这样定义消息:
<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 contract here defines to use style: document/literal
and with the help of the schema the actual SOAP message will be document/literal wrapped
which is furthermore WS-I compliant.
此处的 WSDL 契约定义使用样式:document/literal
并且在模式的帮助下,实际的 SOAP 消息将document/literal wrapped
进一步符合 WS-I。
Your method will therefore change to public MyResponse sendSinge2(MyRequest request)
where request
now encapsulates username
, passowrd
and newParam
. In case newParam
was not send with the SOAP request it simply will return null
, so better check if first before you use it.
因此,您的方法将更改为 public MyResponse sendSinge2(MyRequest request)
,request
现在封装了username
,passowrd
和newParam
。如果newParam
没有随 SOAP 请求一起发送,它只会返回null
,因此在使用它之前最好先检查一下。
If you stick to the code-first approach, you will need to define your MyRequest
class first which you use as request parameter instead of those 2 or 3 values.
如果您坚持代码优先的方法,您将需要首先定义您的MyRequest
类,您将其用作请求参数而不是那 2 或 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;
...
}
The same should be done for MyResult
if you haven't done it yet. The web method may now look something like that:
MyResult
如果您还没有这样做,也应该这样做。Web 方法现在可能看起来像这样:
@WebMethod(operationName = "sendSingle2")
@WebResult(name = "sendSingle2Response", targetNamespace = "http://your.namespace.com")
public MyResult sendSingle2(@WebParam(name = "sendSingle2Request") MyRequest request)
{
...
}
Again, request
encapsulates the 3 parameters where you fist should check if the optional parameters are null.
同样,request
封装了 3 个参数,您应该检查可选参数是否为空。
HTH
HTH
回答by kingAm
It all depends on your implementation class, where you are using these parameters. At endpoint interface simply add this parameter as webparam.
这完全取决于您在何处使用这些参数的实现类。在端点接口只需将此参数添加为 webparam。
Make sure in your implementation class If you are using this parameter anywhere, add alternative code (Else part) to perform your operation or execution without this parameter also.
确保在您的实现类中如果您在任何地方使用此参数,请添加替代代码(Else 部分)以在没有此参数的情况下执行您的操作或执行。
I think all parameters treat as optional until unless you validate them or use them in your implementation class as recommended.
我认为所有参数都视为可选的,除非您验证它们或按照建议在您的实现类中使用它们。