如何根据服务调用在WSO2 ESB故障序列中生成客户错误?

时间:2015-11-09 17:24:06

标签: wso2 wso2esb esb

我正在尝试在WSO2 ESB中添加一些逻辑,它将尝试正常调用服务并返回响应,但如果由于某种原因服务有问题,我想检查另一个服务,看看是否由于维护而关闭,然后相应地显示错误消息。

我尝试使用添加到代理目标的故障序列。并且在这个序列中,我对servlet进行了一个send调用,但它错误地说响应不是JSON我知道它是因为它是硬编码的。

这是正确的做法吗? 实现此功能的正确方法是什么?

这是将返回错误代码或消息的servlet,目前它是硬编码的:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("hit the servlet.......");
    response.setContentType("application/json");
    response.getWriter().append("{\"result\": \"1234\"}");
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

这是代理:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="mjstest" transports="https http" startOnLoad="true" trace="disable">
<target faultSequence="json_fault_handler">
    <inSequence>
        <log level="full"/>
        <property name="messageType" value="application/json" scope="axis2" type="STRING"/>
        <log level="full" category="TRACE"/>
        <send>
            <endpoint>
                <address uri="http://10.180.63.195:9088/rest/badServiceThatWillFailForThisTest" format="rest">
                    <timeout>
                        <duration>30000</duration>
                        <responseAction>fault</responseAction>
                    </timeout>
                    <suspendOnFailure>
                        <errorCodes>-1</errorCodes>
                        <initialDuration>0</initialDuration>
                        <progressionFactor>1.0</progressionFactor>
                        <maximumDuration>0</maximumDuration>
                    </suspendOnFailure>
                    <markForSuspension>
                        <errorCodes>-1</errorCodes>
                    </markForSuspension>
                </address>
            </endpoint>
        </send>
    </inSequence>
    <outSequence>
        <log level="full" separator=","/>
        <send/>
    </outSequence>
</target>

以下是序列:

<sequence xmlns="http://ws.apache.org/ns/synapse" name="json_fault_handler">
 <log category="INFO" level="custom" separator=",">
     <property name="failS" value="=======False Sequence==========="/>
 </log>
 <send>
     <endpoint>
         <address uri="http://localhost:8080/UGC_Images/BACMaintananceWindow" ></address>
     </endpoint>
 </send>
 <property name="messageType" value="application/json" scope="axis2"></property>

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

所以这是我工作的解决方案。它可能不是最好的解决方案,但确实可以满足需要。解决方案流程如下:

  1. 尝试原始请求
  2. 如果失败,请转到fault_handler,其中
  3. 转到Java Class以读取xml文件以查看它是否在维护块中
  4. 返回值并显示回复
  5. 这是fault_handler:

    <sequence xmlns="http://ws.apache.org/ns/synapse" name="json_fault_handler">
    <log category="INFO" level="full" separator="," />
    <property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" action="set" expression="get-property('ERROR_CODE')" name="ErrorCode" scope="default" type="INTEGER" />
    <log category="INFO" level="custom" separator=",">
        <property name="failS" value="=======False Sequence===========" />
        <property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" expression="$ctx:ErrorCode" name="testCode" />
        <property xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" expression="get-property('Action')" name="Action" />
    </log>
    <class name="com.comp.synapse.mediator.ServiceMediatorClass"></class>
    <property action="set" name="HTTP_SC" scope="axis2" type="STRING" expression="$axis2:HTTP_SC" />
    <payloadFactory media-type="json">
        <format>{
            "code": "$1",
            "error": "$2",
            "error_description": "$3"
            }
        </format>
        <args>
            <arg expression="$axis2:SystemErrorCode" />
            <arg expression="$axis2:SystemErrorShort" />
            <arg expression="$axis2:SystemErrorDescription" />
        </args>
    </payloadFactory>
    <property action="set" name="messageType" scope="axis2" type="STRING" value="application/json" />
    <property action="remove" name="NO_ENTITY_BODY" scope="axis2" />
    <property action="set" name="RESPONSE" scope="default" type="STRING" value="true" />
    <header action="remove" name="To" />
    <send />
    

    这是中介类方法:

    public boolean mediate(MessageContext mc) {     
        org.apache.axis2.context.MessageContext msgContext = ((Axis2MessageContext) mc).getAxis2MessageContext();
        String httpStatusCode = ((Integer) msgContext.getProperty("HTTP_SC")).toString();
        String directory = "C:\\Temp\\maintenance.xml";
        File file = new File(directory);
        boolean inMaintenanceWindow = false;
        String errorDescription = "";
        Date now = new Date();
        try {           
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(file);
    
            NodeList nList = doc.getElementsByTagName("downTimePeriod");
    
            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
    
                Date fromDate = null;
                Date toDate = null;
                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) nNode;
                    System.out.println("downTimePeriod id : " + eElement.getAttribute("id"));
                    String fromDateString = eElement.getElementsByTagName("FromDate").item(0).getTextContent();
                    String fromTimeString = eElement.getElementsByTagName("FromTime").item(0).getTextContent();
                    String toDateString = eElement.getElementsByTagName("ToDate").item(0).getTextContent();
                    String toTimeString = eElement.getElementsByTagName("ToTime").item(0).getTextContent();
                    fromDate = sdf.parse(fromDateString + " " + fromTimeString);
                    toDate = sdf.parse(toDateString + " " + toTimeString);
    
                    if(now.after(fromDate) && now.before(toDate)){
                        inMaintenanceWindow = true;
                        errorDescription = "Service is under maintenance until - " + toDateString + " " + toTimeString;
                        break;
                    }
                }
            }
        } catch (Exception e) {         
            e.printStackTrace();
        }
        if(inMaintenanceWindow){
            msgContext.setProperty("HTTP_SC", "503");
            msgContext.setProperty("SystemErrorCode", "503");
            msgContext.setProperty("SystemErrorShort", "Service is under maintenance.");
            msgContext.setProperty("SystemErrorDescription", errorDescription);
        }else{
            msgContext.setProperty("HTTP_SC", httpStatusCode);
            msgContext.setProperty("SystemErrorCode", httpStatusCode);
            msgContext.setProperty("SystemErrorShort", "Error occurred.");
            msgContext.setProperty("SystemErrorDescription", errorDescription);         
        }
    
        return true;
    }
    

    希望这有助于某人。

答案 1 :(得分:0)

你走了。 根据您的解释,您要实现的是服务链。我的理解是你试图拨打服务1,如果失败,你将打电话给服务2。 根据此服务2仅在服务1失败时才被调用。如果是这种情况你应该做的是你的故障序列应该保持每个呼叫的状态,并最终将其提升给呼叫者。最佳选项是为每个调用保持单独的序列,您可以从每个故障序列中调用这些序列。 这又取决于用例。如果至少有1个服务失败,如果要将所有内容都视为失败,则可以直接从故障序列返回。如果没有,你可以按照我的建议。但这里的问题应该是状态代码。如果你设置为200意味着成功。如果一项服务失败,我们可以说成功吗?再次取决于你的用例。