zoukankan      html  css  js  c++  java
  • 关于使用Axis2 webservice 处理Fault响应时抛org.apache.axis2.AxisFault的分析

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

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

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

    1. try {  
    2.          ServiceClient serviceClient = new ServiceClient();  
    3.          Options options = new Options();  
    4.          //设置超时时间,单位毫秒  
    5.          options.setTimeOutInMilliSeconds(this.wsTimeOut);  
    6.            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);  
    7.            options.setTo(new EndpointReference(this.wsEndpointAddress));  
    8.            options.setSoapVersionURI(org.apache.axiom.soap.SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);  
    9.            options.setAction(this.wsMethod);  
    10.            MessageContext requetMessageContext = new MessageContext();  
    11.            SOAPEnvelope env = this.getRequestEnvelope();  
    12.            log.info("version : "+ env.getVersion().getEnvelopeURI());  
    13.             requetMessageContext.setEnvelope(env);  
    14.               
    15.             OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);  
    16.             opClient.addMessageContext(requetMessageContext);  
    17.             opClient.setOptions(options);  
    18.             opClient.execute(true);  
    19.             MessageContext rspMC = opClient.getMessageContext("In");  
    20.             response = rspMC.getEnvelope().getBody().getFirstElement();  
    21.          log.info("应答报文: "+ rspMC.getEnvelope());  
    22.       } catch (AxisFault e) {  
    23.          this.errRspDesc = "xxxxx";  
    24.          log.error("soapDispatch AxisFault!");  
    25.          throw e;  
    26.       } catch (Exception e) {  
    27.          this.errRspDesc = "xxxxxxxxxxxxx!";  
    28.          log.error("soapDispatch Exception!");  
    29.          throw e;  
    30.       }  
    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); 入手,可以看到

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

    再看this.executeImpl(block);

    1. public void executeImpl(boolean block) throws AxisFault {  
    2.        if(log.isDebugEnabled()) {  
    3.            log.debug("Entry: OutInAxisOperationClient::execute, " + block);  
    4.        }  
    5.   
    6.        if(this.completed) {  
    7.            throw new AxisFault(Messages.getMessage("mepiscomplted"));  
    8.        } else {  
    9.            ConfigurationContext cc = this.sc.getConfigurationContext();  
    10.            MessageContext mc = this.oc.getMessageContext("Out");  
    11.            if(mc == null) {  
    12.                throw new AxisFault(Messages.getMessage("outmsgctxnull"));  
    13.            } else {  
    14.                this.prepareMessageContext(cc, mc);  
    15.                if(this.options.getTransportIn() == null && mc.getTransportIn() == null) {  
    16.                    mc.setTransportIn(ClientUtils.inferInTransport(cc.getAxisConfiguration(), this.options, mc));  
    17.                } else if(mc.getTransportIn() == null) {  
    18.                    mc.setTransportIn(this.options.getTransportIn());  
    19.                }  
    20.   
    21.                boolean useAsync = false;  
    22.                if(!mc.getOptions().isUseSeparateListener()) {  
    23.                    Boolean replyTo = (Boolean)mc.getProperty("UseAsyncOperations");  
    24.                    if(log.isDebugEnabled()) {  
    25.                        log.debug("OutInAxisOperationClient: useAsyncOption " + replyTo);  
    26.                    }  
    27.   
    28.                    if(replyTo != null) {  
    29.                        useAsync = replyTo.booleanValue();  
    30.                    }  
    31.                }  
    32.   
    33.                EndpointReference replyTo1 = mc.getReplyTo();  
    34.                if(replyTo1 != null) {  
    35.                    if(replyTo1.hasNoneAddress()) {  
    36.                        throw new AxisFault(replyTo1.getAddress() + "" + " can not be used with OutInAxisOperationClient , user either " + "fireAndForget or sendRobust)");  
    37.                    }  
    38.   
    39.                    if(replyTo1.isWSAddressingAnonymous() && replyTo1.getAllReferenceParameters() != null) {  
    40.                        mc.setProperty("includeOptionalHeaders", Boolean.TRUE);  
    41.                    }  
    42.   
    43.                    String customReplyTo = (String)this.options.getProperty(Options.CUSTOM_REPLYTO_ADDRESS);  
    44.                    if(!Options.CUSTOM_REPLYTO_ADDRESS_TRUE.equals(customReplyTo) && !replyTo1.hasAnonymousAddress()) {  
    45.                        useAsync = true;  
    46.                    }  
    47.                }  
    48.   
    49.                if(!useAsync && !mc.getOptions().isUseSeparateListener()) {  
    50.                    if(block) {  
    51.                        this.send(mc);  
    52.                        this.completed = true;  
    53.                    } else {  
    54.                        this.sc.getConfigurationContext().getThreadPool().execute(new OutInAxisOperationClient.NonBlockingInvocationWorker(this.callback, mc, this.axisCallback));  
    55.                    }  
    56.                } else {  
    57.                    this.sendAsync(useAsync, mc);  
    58.                }  
    59.   
    60.            }  
    61.        }  
    62.    }  
     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)方法

    1. protected MessageContext send(MessageContext msgContext) throws AxisFault {  
    2.        MessageContext responseMessageContext = msgContext.getConfigurationContext().createMessageContext();  
    3.        responseMessageContext.setServerSide(false);  
    4.        responseMessageContext.setOperationContext(msgContext.getOperationContext());  
    5.        responseMessageContext.setOptions(new Options(this.options));  
    6.        responseMessageContext.setMessageID(msgContext.getMessageID());  
    7.        this.addMessageContext(responseMessageContext);  
    8.        responseMessageContext.setServiceContext(msgContext.getServiceContext());  
    9.        responseMessageContext.setAxisMessage(this.axisOp.getMessage("In"));  
    10.        AxisEngine.send(msgContext);  
    11.        responseMessageContext.setDoingREST(msgContext.isDoingREST());  
    12.        responseMessageContext.setProperty("TRANSPORT_HEADERS", msgContext.getProperty("TRANSPORT_HEADERS"));  
    13.        responseMessageContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE));  
    14.        responseMessageContext.setProperty("TRANSPORT_IN", msgContext.getProperty("TRANSPORT_IN"));  
    15.        responseMessageContext.setTransportIn(msgContext.getTransportIn());  
    16.        responseMessageContext.setTransportOut(msgContext.getTransportOut());  
    17.        this.handleResponse(responseMessageContext);  
    18.        return responseMessageContext;  
    19.    }  
     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);

    1. protected void handleResponse(MessageContext responseMessageContext) throws AxisFault {  
    2.      responseMessageContext.setSoapAction((String)null);  
    3.      SOAPEnvelope resenvelope;  
    4.      if(responseMessageContext.getEnvelope() == null) {  
    5.          resenvelope = TransportUtils.createSOAPMessage(responseMessageContext);  
    6.          if(resenvelope == null) {  
    7.              throw new AxisFault(Messages.getMessage("blockingInvocationExpectsResponse"));  
    8.          }  
    9.   
    10.          responseMessageContext.setEnvelope(resenvelope);  
    11.      }  
    12.   
    13.      resenvelope = responseMessageContext.getEnvelope();  
    14.      if(resenvelope != null) {  
    15.          AxisEngine.receive(responseMessageContext);  
    16.          if(responseMessageContext.getReplyTo() != null) {  
    17.              this.sc.setTargetEPR(responseMessageContext.getReplyTo());  
    18.          }  
    19.   
    20.          resenvelope = responseMessageContext.getEnvelope();  
    21.          if((resenvelope.hasFault() || responseMessageContext.isProcessingFault()) && this.options.isExceptionToBeThrownOnSOAPFault()) {  
    22.              throw Utils.getInboundFaultFromMessageContext(responseMessageContext);  
    23.          }  
    24.      }  
    25.   
    26.  }  
       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()) 总算是跟我们的异常报文有关了。跟进去看一下

    1. public boolean hasFault() {  
    2.       QName payloadQName = this.getPayloadQName_Optimized();  
    3.       if(payloadQName != null && "Fault".equals(payloadQName.getLocalPart())) {  
    4.           String body1 = payloadQName.getNamespaceURI();  
    5.           return "http://schemas.xmlsoap.org/soap/envelope/".equals(body1) || "http://www.w3.org/2003/05/soap-envelope".equals(body1);  
    6.       } else {  
    7.           SOAPBody body = this.getBody();  
    8.           return body == null?false:body.hasFault();  
    9.       }  
    10.   }  
      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的一个参数,可配置,所以给我们的代码加上

    1. options.setExceptionToBeThrownOnSOAPFault(false);  
    options.setExceptionToBeThrownOnSOAPFault(false);
    

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

  • 相关阅读:
    Spring声明式事务配置
    spring注解注入:<context:component-scan>详解
    MySQL添加用户、删除用户与授权
    Mysql 分页语句Limit用法
    Java内存泄露的理解与解决
    eclipse的设置和优化
    从svn删除文件夹和文件
    权限管理设计
    Linux Tomcat 6.0安装配置实践总结
    Java 继承
  • 原文地址:https://www.cnblogs.com/firstdream/p/7779712.html
Copyright © 2011-2022 走看看