今天开发项目遇到一个问题,简单记录下,希望能帮到遇到同样问题的同学
我使用Axis1.4开发webservice客户端,客户端代码如下:
Service service = new Service();
Call call;
try {
call = (Call)service.createCall();
call.setTargetEndpointAddress(d2Url);
QName qn = new QName("", "CMSID");
call.addParameter(qn, XMLType.SOAP_STRING, ParameterMode.IN);
QName qn2 = new QName("", "CorrelateID");
call.addParameter(qn2, XMLType.SOAP_STRING, ParameterMode.IN);
QName qn3 = new QName("", "ContentMngXMLURL");
call.addParameter(qn3, XMLType.SOAP_STRING, ParameterMode.IN);
call.setReturnClass(ContentDeployReqResponse.class);
QName mapping = new QName("iptv", "ContentPreloadReqResponse");
call.registerTypeMapping(ContentDeployReqResponse.class, mapping,
new BeanSerializerFactory(ContentDeployReqResponse.class, mapping),
new BeanDeserializerFactory(ContentDeployReqResponse.class, mapping));
call.setOperationName(new QName("iptv", "ContentPreloadReq"));
return call;
} catch (ServiceException e) {
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
return null;
ContentDeployReqResponse类代码如下:
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@XmlAccessorType(XmlAccessType.FIELD)
public class ContentDeployReqResponse implements Serializable{
/**
*
*/
private static final long serialVersionUID = -6709028467973715698L;
@XmlElement(name = "ErrorDescription")
private String errorDescription;
@XmlElement(name = "ResultCode")
private int resultCode;
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public String getErrorDescription() {
return errorDescription;
}
public void setErrorDescription(String errorDescription) {
this.errorDescription = errorDescription;
}
}
调用服务端后返回的xml如下:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:ContentPreloadReqResponse xmlns:ns2="iptv">
<return>
<ResultCode>0</ResultCode>
<ErrorDescription>success</ErrorDescription>
</return>
</ns2:ContentPreloadReqResponse>
</S:Body>
</S:Envelope>
Axis在解析xml为ContentDeployReqResponse 时出现以下错误:
[2013-12-19 17:51:24,234 ERROR] Exception: org.apache.axis.client.Call.invoke(Call.java:2469)
org.xml.sax.SAXException: Invalid element in opt.fonsview.cmm.ws.ContentDeployReqResponse - ResultCode
at org.apache.axis.encoding.ser.BeanDeserializer.onStartChild(BeanDeserializer.java:258)
at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035)
at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:236)
at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
at org.apache.axis.client.Call.invoke(Call.java:2467)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)
首先想到的是将ContentDeployReqResponse 中的属性首字母大写,发现还是出现以上问题,查看源代码,Axis用到的是javax.bean相关类来生成ContentDeployReqResponse 类信息,我猜测应该是为了跟java规范保持一致,所以在保存属性名的时候是将首字母小写,而返回的xml中首字母是大写,导致出错。
采用第二种方法,改写Axis相关源码,替换jar包中文件,运行成功,改写的源文件为org.apache.axis.encoding.ser.BeanDeserializer 的onStartChild方法
改写之前:
if (propDesc == null) {
// look for a field by this name.
propDesc = (BeanPropertyDescriptor) propertyMap.get(localName);
}
改写之后:
if (propDesc == null) {
// look for a field by this name.
for(Iterator iter = propertyMap.keySet().iterator(); iter.hasNext();){
String key = (String)iter.next();
if(key.equalsIgnoreCase(localName)){
propDesc = (BeanPropertyDescriptor) propertyMap.get(key);
break;
}
}
}
开发过程中还遇到一个问题未解决:Axis在解析返回的XML时耗费的时间过长,达10分钟之久,发现问题出在InputStream的read方法上,什么原因?欢迎碰到相同的同学一起探讨
附件为修改后的axis jar包