如何使用 Java 中的 Web 服务(例如 Axis2)发送复杂对象的数组或集合?
我对 SOAP/Web 服务还比较陌生;虽然我完成了一些较小的 Web 服务项目,但我偶然从来不需要返回(或用作参数)“复杂”对象的数组或集合。当我尝试这样做时,根据我的 SOAP 绑定风格,我会得到不同的奇怪行为。
当我使用RPC/literal时,我可以发送和接收内置类型的数组(例如 String[]),但是当我尝试“复杂”对象时,我会收到编组错误(例如 xyz 或尽管已将相关类添加到 @XmlSeeAlso 注释,但其任何超类在此上下文中都是已知的。
或者,尝试 Document/literal/wrapped (这似乎是最佳实践?)允许我发送或接收复杂的对象,但当我尝试传递任何类型的数组时会导致一些奇怪的情况。例如,String[] t = { "A", "B", "C", "D" };
以空字符串形式到达 Web 服务(不是String[])。
有谁知道这里发生了什么或者如何让事情以任何合理的方式进行?我目前正在本地部署到 Apache Geronimo。
服务器代码片段:
接口:
@WebService
@SOAPBinding(style=Style.DOCUMENT, use=Use.LITERAL, parameterStyle=ParameterStyle.WRAPPED)
@XmlSeeAlso({Feedback.class,Feedback[].class})
public interface CerberusRequest {
...
@WebMethod
public Feedback[] test(String[] facts) throws Exception;
}
实现:
@WebService(serviceName = "CerberusRequestService", portName
= "CerberusRequestPort", targetNamespace = "http://web.cerberus.xyz.gov/",
endpointInterface = "gov.xyz.cerberus.web.CerberusRequest")
public class CerberusRequestImpl implements CerberusRequest {
...
public Feedback[] test(String[] facts) throws Exception {
//Just some debug crap (prints: "in test...1 [Ljava.lang.String;")
System.out.println("in test..." + facts.length + " " + facts.getClass().getName());
for(String f : facts) {
System.out.println("test:" + f);
}
//return feedback;
Feedback[] f = { new Feedback() };
return f;
}
}
客户端代码片段:
URL url = new URL(destination+"?wsdl");
QName qname = new QName(namespace, service);
Service service = Service.create(url, qname);
CerberusRequest sr = service.getPort(CerberusRequest.class);
String[] t = { "A", "B", "C", "D" };
Feedback[] feedback = sr.test(t);
for(Feedback f : feedback) {
System.out.println(f);
}
WSDL:
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://web.cerberus.xyz.gov/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="CerberusRequestService" targetNamespace="http://web.cerberus.xyz.gov/">
<types>
<xsd:schema>
<xsd:import namespace="http://web.cerberus.xyz.gov/" schemaLocation="http://localhost:8080/CerberusService/CerberusRequest?xsd=xsd1"/>
</xsd:schema>
<xsd:schema>
<xsd:import namespace="http://jaxb.dev.java.net/array" schemaLocation="http://localhost:8080/CerberusService/CerberusRequest?xsd=xsd2"/>
</xsd:schema>
</types>
<message name="Exception">
<part element="tns:Exception" name="fault">
</part>
</message>
<message name="test">
<part element="tns:test" name="parameters">
</part>
</message>
<message name="testResponse">
<part element="tns:testResponse" name="parameters">
</part>
</message>
<portType name="CerberusRequest">
<operation name="test">
<input message="tns:test">
</input>
<output message="tns:testResponse">
</output>
<fault message="tns:Exception" name="Exception">
</fault>
</operation>
</portType>
<binding name="CerberusRequestPortBinding" type="tns:CerberusRequest">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="test">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
<fault name="Exception">
<soap:fault name="Exception" use="literal"/>
</fault>
</operation>
</binding>
<service name="CerberusRequestService">
<port binding="tns:CerberusRequestPortBinding" name="CerberusRequestPort">
<soap:address location="http://localhost:8080/CerberusService/CerberusRequest"/>
</port>
</service>
</definitions>
非常感谢您提前提供的任何信息以及您能提供的一切帮助!
I'm relatively new to SOAP/web services; while I've done a few smaller web services projects I've incidentally never needed to return (or use as a parameter) an array or collection of 'complex' objects. When I attempt to do so, I get varying odd behaviour depending on my SOAP binding style.
When I use RPC/literal, I can send and receive arrays of built-in types (e.g. String[]), but when I try a 'complex' object, I get marshaling errors (e.g. xyz nor any of its super class is known to this context), despite having added the relevant classes to the @XmlSeeAlso annotation.
Alternatively, trying Document/literal/wrapped (which seems to be best practice?) allows me to send or receive complex objects, but results in some oddities when I try to pass around arrays of any type. For example, String[] t = { "A", "B", "C", "D" };
reaches the web service as a an empty String (not String[]).
Does anyone have any idea what's going on here or how to get things working in any sensible way? I'm deploying locally to Apache Geronimo at the moment.
Server code snippet:
Interface:
@WebService
@SOAPBinding(style=Style.DOCUMENT, use=Use.LITERAL, parameterStyle=ParameterStyle.WRAPPED)
@XmlSeeAlso({Feedback.class,Feedback[].class})
public interface CerberusRequest {
...
@WebMethod
public Feedback[] test(String[] facts) throws Exception;
}
Implementation:
@WebService(serviceName = "CerberusRequestService", portName
= "CerberusRequestPort", targetNamespace = "http://web.cerberus.xyz.gov/",
endpointInterface = "gov.xyz.cerberus.web.CerberusRequest")
public class CerberusRequestImpl implements CerberusRequest {
...
public Feedback[] test(String[] facts) throws Exception {
//Just some debug crap (prints: "in test...1 [Ljava.lang.String;")
System.out.println("in test..." + facts.length + " " + facts.getClass().getName());
for(String f : facts) {
System.out.println("test:" + f);
}
//return feedback;
Feedback[] f = { new Feedback() };
return f;
}
}
Client code snippet:
URL url = new URL(destination+"?wsdl");
QName qname = new QName(namespace, service);
Service service = Service.create(url, qname);
CerberusRequest sr = service.getPort(CerberusRequest.class);
String[] t = { "A", "B", "C", "D" };
Feedback[] feedback = sr.test(t);
for(Feedback f : feedback) {
System.out.println(f);
}
WSDL:
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://web.cerberus.xyz.gov/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="CerberusRequestService" targetNamespace="http://web.cerberus.xyz.gov/">
<types>
<xsd:schema>
<xsd:import namespace="http://web.cerberus.xyz.gov/" schemaLocation="http://localhost:8080/CerberusService/CerberusRequest?xsd=xsd1"/>
</xsd:schema>
<xsd:schema>
<xsd:import namespace="http://jaxb.dev.java.net/array" schemaLocation="http://localhost:8080/CerberusService/CerberusRequest?xsd=xsd2"/>
</xsd:schema>
</types>
<message name="Exception">
<part element="tns:Exception" name="fault">
</part>
</message>
<message name="test">
<part element="tns:test" name="parameters">
</part>
</message>
<message name="testResponse">
<part element="tns:testResponse" name="parameters">
</part>
</message>
<portType name="CerberusRequest">
<operation name="test">
<input message="tns:test">
</input>
<output message="tns:testResponse">
</output>
<fault message="tns:Exception" name="Exception">
</fault>
</operation>
</portType>
<binding name="CerberusRequestPortBinding" type="tns:CerberusRequest">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="test">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
<fault name="Exception">
<soap:fault name="Exception" use="literal"/>
</fault>
</operation>
</binding>
<service name="CerberusRequestService">
<port binding="tns:CerberusRequestPortBinding" name="CerberusRequestPort">
<soap:address location="http://localhost:8080/CerberusService/CerberusRequest"/>
</port>
</service>
</definitions>
Thank you very much in advance for any and all help you can provide!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我有类似的问题,我想传递 VO ,它内部有一个复杂的对象(地图),并且该地图可以包含地图的地图作为值或地图列表。
即使您支持当前的要求,以后也可能会遇到其他问题。更好的是,您可以使用第三方序列化器,例如 Castor/Dozer/GSon 等工具。并将数据更改为可以轻松通过线路传递的简单 java 类型。
Well I had similar kind of issues I wanted to pass the VO , which had a complex object (map) inside and this map could contain map of maps as values or List of Map.
Even if you support the current requirement you may end up in other issues later. Better you can use third party serializers like Castor/Dozer/GSon kind of tools. And change the data a simple java type which can be easily passed over the wire.