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

来源:互联网 发布:fifa online mac 编辑:程序博客网 时间:2024/06/06 01:05

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

我的程序直接抛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;      }


当执行到发送请求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);    }


再看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);                }            }        }    }


进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;    }



这里就是发送请求并接收响应的地方
再看倒数第二行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);            }        }    }



这时,我们可以看到一个很有趣的方法, 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();        }    }


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

options.setExceptionToBeThrownOnSOAPFault(false);



就不抛异常了,能够正常获取并解析响应报文。
总结:一切的害怕源于对代码的神秘,未知,当你把它当成自己写的代码,去反编译,去阅读,那就不会再害怕!
0 0
原创粉丝点击