我必须从我的java程序进行SOAP调用,为此我使用了apache轴。 我的计划如下:
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;
public class Project {
public static void main(String [] args) {
try {
String endpoint ="http://RequestUrl";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName(new QName(endpoint, "getFrsFileData"));
String value = (String) call.invoke(new Object[] { "24BB7","frs1001" } );
System.out.println(value);
}
catch (Exception e) {
System.err.println(e.toString());
}
}
}
执行时出现如下错误
- 例外: org.xml.sax.SAXException:反序列化参数'getFrsFileDataReturn':找不到类型{http:// Url} FrsFileSoapDO的反序列化器 在org.apache.axis.message.RPCHandler.onStartChild(RPCHandler.java:277) 在org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035) 在org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165) 在org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141) at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:345) 在org.apache.axis.message.RPCElement.getParams(RPCElement.java:384) 在org.apache.axis.client.Call.invoke(Call.java:2467) 在org.apache.axis.client.Call.invoke(Call.java:2366) 在org.apache.axis.client.Call.invoke(Call.java:1812) 在Project.main(Project.java:33) org.xml.sax.SAXException:反序列化参数'getFrsFileDataReturn':找不到类型{http:// Url} FrsFileSoapDO
的反序列化器
尝试使用SOAPUI进行相同的调用,但它无法帮我调试。
请帮我调试这个java代码,
谢谢
答案 0 :(得分:5)
我得到了朋友的帮助,能够得到答案。
问题是soap调用会给出一个肥皂响应,它是一个类型为“FrsFileSoapDO”的bean。因为我没有在代码中提供任何代码来说明我的程序将如何理解收到的bean,这给了我一个错误,说“找不到类型为{http://Url}FrsFileSoapDO
的反序列化器”。
现在清除问题的步骤是
1)创建一个“QName”来说明“FrsFileSoapDO”所指的命名空间是什么。
2)创建Bean序列化程序(知道如何序列化bean),
3)创建一个Bean反序列化器(知道如何反序列化bean),
4)执行映射说QName q映射到类FrsFileSoapDO.class(在此之前确保你有FrsFileSoapDO.class并且已导入它)
现在让我们在程序中实现它,(我在这里只重复try块)
try {
String endpoint ="http://RequestUrl";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
QName q = new QName ("http://Url", "FrsFileSoapDO"); // step 1
BeanSerializerFactory bsf = new BeanSerializerFactory(FrsFileSoapDO.class,q); // step 2
BeanDeserializerFactory bdf = new BeanDeserializerFactory(FrsFileSoapDO.class,q); // step 3
call.registerTypeMapping(FrsFileSoapDO.class,q, bsf, bdf); //step 4
call.setOperationName(new QName(endpoint, "getFrsFileData"));
FrsFileSoapDO s = (FrsFileSoapDO) call.invoke(new Object[] { "24BB7","frs1001" } );
System.out.println(s.getFilename());
}
这可以给我预期的输出。
函数Call,BeanSerializerFactory,BeanDeserializerFactory的文档位于BeanSerializerFactory和BeanDeserializerFactory
答案 1 :(得分:0)
我遇到了同样的问题。 我认为你代码中唯一的错误是在线下:
call.setOperationName(new QName(endpoint, "getFrsFileData"));
您不应将端点用于QName构造函数参数。如果你只是发送字符串参数,你可以把它留空,但是如果你应该从wsdl文件中提供一些复杂的数据。 检查wsdl文件中此Web服务方法的参数,并在此处给出相同的映射。 例如对我来说这是一个文件传输,所以wsdl中的条目是:
<wsdl:message name="sendFileRequest">
<wsdl:part name="in0" type="apachesoap:DataHandler"/>
<wsdl:part name="in1" type="soapenc:string"/>
</wsdl:message>
并在客户端代码中提供相同的类型,如:
call.setOperationName( new QName("apachesoap:MatrixService", "sendFile") );
QName fileAttachment = new QName("apachesoap:MatrixService", "DataHandler");
在此之后,您需要使用registerTypeMapping定义相同的地图。