2025年关于使用Axis2 webservice 处理Fault响应时抛org.apache.axis2.AxisFault的分析

关于使用Axis2 webservice 处理Fault响应时抛org.apache.axis2.AxisFault的分析使用 Axis2 这个框架进行 webservice 协议通讯 期间出了个问题 我 CLIENT 请求后 当服务端返回符合协议的 SOAP 异常报文 例如 我的程序直接抛 org apache axis2 AxisFault 异常 导致连服务端给我们的报文都没有接收成功 请注意 是我连报文都没有接收成功 而不是接收成功后我解析失败了 try ServiceClien

使用Axis2这个框架进行webservice协议通讯,期间出了个问题,我(CLIENT)请求后,当服务端返回符合协议的SOAP异常报文,例如

我的程序直接抛org.apache.axis2.AxisFault异常,导致连服务端给我们的报文都没有接收成功。

–请注意,是我连报文都没有接收成功,而不是接收成功后我解析失败了。

try {

ServiceClient serviceClient = new ServiceClient();

Options options = new Options();

//设置超时时间,单位毫秒

options.setTimeOutInMilliSeconds(this.wsTimeOut);

options.setTransportInProtocol(Constants.TRANSPORT_HTTP);

options.setTo(new EndpointReference(this.wsEndpointAddress));

options.setSoapVersionURI(org.apache.axiom.soap.SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);

options.setAction(this.wsMethod);

MessageContext requetMessageContext = new MessageContext();

SOAPEnvelope env = this.getRequestEnvelope();

log.info(“version : “+ env.getVersion().getEnvelopeURI());

requetMessageContext.setEnvelope(env);

OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);

opClient.addMessageContext(requetMessageContext);

opClient.setOptions(options);

opClient.execute(true);

MessageContext rspMC = opClient.getMessageContext(“In”);

response = rspMC.getEnvelope().getBody().getFirstElement();

log.info(“应答报文: “+ rspMC.getEnvelope());

} catch (AxisFault e) {

this.errRspDesc = “xxxxx”;

log.error(“soapDispatch AxisFault!”);

throw e;

} catch (Exception e) {

this.errRspDesc = “xxxxxxxxxxxxx!”;

log.error(“soapDispatch Exception!”);

throw e;

}

try {
ServiceClient serviceClient = new ServiceClient();
Options options = new Options();
//设置超时时间,单位毫秒
options.setTimeOutInMilliSeconds(this.wsTimeOut);
options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
options.setTo(new EndpointReference(this.wsEndpointAddress));
options.setSoapVersionURI(org.apache.axiom.soap.SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
options.setAction(this.wsMethod);
MessageContext requetMessageContext = new MessageContext();
SOAPEnvelope env = this.getRequestEnvelope();
log.info("version : "+ env.getVersion().getEnvelopeURI());
requetMessageContext.setEnvelope(env);

OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);
opClient.addMessageContext(requetMessageContext);
opClient.setOptions(options);
opClient.execute(true);
MessageContext rspMC = opClient.getMessageContext("In");
response = rspMC.getEnvelope().getBody().getFirstElement();
log.info("应答报文: "+ rspMC.getEnvelope());
} catch (AxisFault e) {
this.errRspDesc = "xxxxx";
log.error("soapDispatch AxisFault!");
throw e;
} catch (Exception e) {
this.errRspDesc = "xxxxxxxxxxxxx!";
log.error("soapDispatch Exception!");
throw e;
}

当执行到发送请求opClient.execute(true);

服务端成功返回格式正常的SOAP异常报文,此时程序直接抛异常,走不到下面rspMC的获取,也就拿不到响应报文。

经过一段时间的查看Axis2源码,终于找到原因。

从opClient.execute(true); 入手,可以看到

public final void execute(boolean block) throws AxisFault {

this.sc.setLastOperationContext(this.oc);

this.executeImpl(block);

}

 public final void execute(boolean block) throws AxisFault {
this.sc.setLastOperationContext(this.oc);
this.executeImpl(block);
}

再看this.executeImpl(block);

public void executeImpl(boolean block) throws AxisFault {

if(log.isDebugEnabled()) {

log.debug(“Entry: OutInAxisOperationClient::execute, ” + block);

}

if(this.completed) {

throw new AxisFault(Messages.getMessage(“mepiscomplted”));

} else {

ConfigurationContext cc = this.sc.getConfigurationContext();

MessageContext mc = this.oc.getMessageContext(“Out”);

if(mc == null) {

throw new AxisFault(Messages.getMessage(“outmsgctxnull”));

} else {

this.prepareMessageContext(cc, mc);

if(this.options.getTransportIn() == null && mc.getTransportIn() == null) {

mc.setTransportIn(ClientUtils.inferInTransport(cc.getAxisConfiguration(), this.options, mc));

} else if(mc.getTransportIn() == null) {

mc.setTransportIn(this.options.getTransportIn());

}

boolean useAsync = false;

if(!mc.getOptions().isUseSeparateListener()) {

Boolean replyTo = (Boolean)mc.getProperty(“UseAsyncOperations”);

if(log.isDebugEnabled()) {

log.debug(“OutInAxisOperationClient: useAsyncOption ” + replyTo);

}

if(replyTo != null) {

useAsync = replyTo.booleanValue();

}

}

EndpointReference replyTo1 = mc.getReplyTo();

if(replyTo1 != null) {

if(replyTo1.hasNoneAddress()) {

throw new AxisFault(replyTo1.getAddress() + “” + ” can not be used with OutInAxisOperationClient , user either ” + “fireAndForget or sendRobust)”);

}

if(replyTo1.isWSAddressingAnonymous() && replyTo1.getAllReferenceParameters() != null) {

mc.setProperty(“includeOptionalHeaders”, Boolean.TRUE);

}

String customReplyTo = (String)this.options.getProperty(Options.CUSTOM_REPLYTO_ADDRESS);

if(!Options.CUSTOM_REPLYTO_ADDRESS_TRUE.equals(customReplyTo) && !replyTo1.hasAnonymousAddress()) {

useAsync = true;

}

}

if(!useAsync && !mc.getOptions().isUseSeparateListener()) {

if(block) {

this.send(mc);

this.completed = true;

} else {

this.sc.getConfigurationContext().getThreadPool().execute(new OutInAxisOperationClient.NonBlockingInvocationWorker(this.callback, mc, this.axisCallback));

}

} else {

this.sendAsync(useAsync, mc);

}

}

}

}

 public void executeImpl(boolean block) throws AxisFault {
if(log.isDebugEnabled()) {
log.debug("Entry: OutInAxisOperationClient::execute, " + block);
}

if(this.completed) {
throw new AxisFault(Messages.getMessage("mepiscomplted"));
} else {
ConfigurationContext cc = this.sc.getConfigurationContext();
MessageContext mc = this.oc.getMessageContext("Out");
if(mc == null) {
throw new AxisFault(Messages.getMessage("outmsgctxnull"));
} else {
this.prepareMessageContext(cc, mc);
if(this.options.getTransportIn() == null && mc.getTransportIn() == null) {
mc.setTransportIn(ClientUtils.inferInTransport(cc.getAxisConfiguration(), this.options, mc));
} else if(mc.getTransportIn() == null) {
mc.setTransportIn(this.options.getTransportIn());
}

boolean useAsync = false;
if(!mc.getOptions().isUseSeparateListener()) {
Boolean replyTo = (Boolean)mc.getProperty("UseAsyncOperations");
if(log.isDebugEnabled()) {
log.debug("OutInAxisOperationClient: useAsyncOption " + replyTo);
}

if(replyTo != null) {
useAsync = replyTo.booleanValue();
}
}

EndpointReference replyTo1 = mc.getReplyTo();
if(replyTo1 != null) {
if(replyTo1.hasNoneAddress()) {
throw new AxisFault(replyTo1.getAddress() + "" + " can not be used with OutInAxisOperationClient , user either " + "fireAndForget or sendRobust)");
}

if(replyTo1.isWSAddressingAnonymous() && replyTo1.getAllReferenceParameters() != null) {
mc.setProperty("includeOptionalHeaders", Boolean.TRUE);
}

String customReplyTo = (String)this.options.getProperty(Options.CUSTOM_REPLYTO_ADDRESS);
if(!Options.CUSTOM_REPLYTO_ADDRESS_TRUE.equals(customReplyTo) && !replyTo1.hasAnonymousAddress()) {
useAsync = true;
}
}

if(!useAsync && !mc.getOptions().isUseSeparateListener()) {
if(block) {
this.send(mc);
this.completed = true;
} else {
this.sc.getConfigurationContext().getThreadPool().execute(new OutInAxisOperationClient.NonBlockingInvocationWorker(this.callback, mc, this.axisCallback));
}
} else {
this.sendAsync(useAsync, mc);
}

}
}
}

进send(mc)方法

protected MessageContext send(MessageContext msgContext) throws AxisFault {

MessageContext responseMessageContext = msgContext.getConfigurationContext().createMessageContext();

responseMessageContext.setServerSide(false);

responseMessageContext.setOperationContext(msgContext.getOperationContext());

responseMessageContext.setOptions(new Options(this.options));

responseMessageContext.setMessageID(msgContext.getMessageID());

this.addMessageContext(responseMessageContext);

responseMessageContext.setServiceContext(msgContext.getServiceContext());

responseMessageContext.setAxisMessage(this.axisOp.getMessage(“In”));

AxisEngine.send(msgContext);

responseMessageContext.setDoingREST(msgContext.isDoingREST());

responseMessageContext.setProperty(“TRANSPORT_HEADERS”, msgContext.getProperty(“TRANSPORT_HEADERS”));

responseMessageContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE));

responseMessageContext.setProperty(“TRANSPORT_IN”, msgContext.getProperty(“TRANSPORT_IN”));

responseMessageContext.setTransportIn(msgContext.getTransportIn());

responseMessageContext.setTransportOut(msgContext.getTransportOut());

this.handleResponse(responseMessageContext);

return responseMessageContext;

}

 protected MessageContext send(MessageContext msgContext) throws AxisFault {
MessageContext responseMessageContext = msgContext.getConfigurationContext().createMessageContext();
responseMessageContext.setServerSide(false);
responseMessageContext.setOperationContext(msgContext.getOperationContext());
responseMessageContext.setOptions(new Options(this.options));
responseMessageContext.setMessageID(msgContext.getMessageID());
this.addMessageContext(responseMessageContext);
responseMessageContext.setServiceContext(msgContext.getServiceContext());
responseMessageContext.setAxisMessage(this.axisOp.getMessage("In"));
AxisEngine.send(msgContext);
responseMessageContext.setDoingREST(msgContext.isDoingREST());
responseMessageContext.setProperty("TRANSPORT_HEADERS", msgContext.getProperty("TRANSPORT_HEADERS"));
responseMessageContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE));
responseMessageContext.setProperty("TRANSPORT_IN", msgContext.getProperty("TRANSPORT_IN"));
responseMessageContext.setTransportIn(msgContext.getTransportIn());
responseMessageContext.setTransportOut(msgContext.getTransportOut());
this.handleResponse(responseMessageContext);
return responseMessageContext;
}

这里就是发送请求并接收响应的地方 再看倒数第二行this.handleResponse(responseMessageContext);

protected void handleResponse(MessageContext responseMessageContext) throws AxisFault {

responseMessageContext.setSoapAction((String)null);

SOAPEnvelope resenvelope;

if(responseMessageContext.getEnvelope() == null) {

resenvelope = TransportUtils.createSOAPMessage(responseMessageContext);

if(resenvelope == null) {

throw new AxisFault(Messages.getMessage(“blockingInvocationExpectsResponse”));

}

responseMessageContext.setEnvelope(resenvelope);

}

resenvelope = responseMessageContext.getEnvelope();

if(resenvelope != null) {

AxisEngine.receive(responseMessageContext);

if(responseMessageContext.getReplyTo() != null) {

this.sc.setTargetEPR(responseMessageContext.getReplyTo());

}

resenvelope = responseMessageContext.getEnvelope();

if((resenvelope.hasFault() || responseMessageContext.isProcessingFault()) && this.options.isExceptionToBeThrownOnSOAPFault()) {

throw Utils.getInboundFaultFromMessageContext(responseMessageContext);

}

}

}

   protected void handleResponse(MessageContext responseMessageContext) throws AxisFault {
responseMessageContext.setSoapAction((String)null);
SOAPEnvelope resenvelope;
if(responseMessageContext.getEnvelope() == null) {
resenvelope = TransportUtils.createSOAPMessage(responseMessageContext);
if(resenvelope == null) {
throw new AxisFault(Messages.getMessage("blockingInvocationExpectsResponse"));
}

responseMessageContext.setEnvelope(resenvelope);
}

resenvelope = responseMessageContext.getEnvelope();
if(resenvelope != null) {
AxisEngine.receive(responseMessageContext);
if(responseMessageContext.getReplyTo() != null) {
this.sc.setTargetEPR(responseMessageContext.getReplyTo());
}

resenvelope = responseMessageContext.getEnvelope();
if((resenvelope.hasFault() || responseMessageContext.isProcessingFault()) && this.options.isExceptionToBeThrownOnSOAPFault()) {
throw Utils.getInboundFaultFromMessageContext(responseMessageContext);
}
}

}

这时,我们可以看到一个很有趣的方法, if((resenvelope.hasFault() || responseMessageContext.isProcessingFault()) 总算是跟我们的异常报文有关了。跟进去看一下

public boolean hasFault() {

QName payloadQName = this.getPayloadQName_Optimized();

if(payloadQName != null && “Fault”.equals(payloadQName.getLocalPart())) {

String body1 = payloadQName.getNamespaceURI();

return “http://schemas.xmlsoap.org/soap/envelope/”.equals(body1) || “http://www.w3.org/2003/05/soap-envelope”.equals(body1);

} else {

SOAPBody body = this.getBody();

return body == null?false:body.hasFault();

}

}

  public boolean hasFault() {
QName payloadQName = this.getPayloadQName_Optimized();
if(payloadQName != null && "Fault".equals(payloadQName.getLocalPart())) {
String body1 = payloadQName.getNamespaceURI();
return "http://schemas.xmlsoap.org/soap/envelope/".equals(body1) || "http://www.w3.org/2003/05/soap-envelope".equals(body1);
} else {
SOAPBody body = this.getBody();
return body == null?false:body.hasFault();
}
}

可以看到Axis2的内部处理机制,就是一但发现响应报文有Fault节点,它就要抛异常。总算找到源头了 那要如何解决这个问题 我们可以看到 if((resenvelope.hasFault() || responseMessageContext.isProcessingFault()) && this.options.isExceptionToBeThrownOnSOAPFault()) { throw Utils.getInboundFaultFromMessageContext(responseMessageContext); } 这里还有一个判断条件, this.options.isExceptionToBeThrownOnSOAPFault() 当它为TRUE时才抛异常。 这就是options的一个参数,可配置,所以给我们的代码加上

options.setExceptionToBeThrownOnSOAPFault(false);

options.setExceptionToBeThrownOnSOAPFault(false);

就不抛异常了,能够正常获取并解析响应报文。

总结:一切的害怕源于对代码的神秘,未知,当你把它当成自己写的代码,去反编译,去阅读,那就不会再害怕!

编程小号
上一篇 2025-06-03 08:33
下一篇 2025-09-06 07:57

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/hz/124318.html