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

How to generate a custome error in WSO2 ESB fault sequence based on service call?

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

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

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

这是将 return 错误代码或消息的 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>

非常感谢任何帮助。

给你。 根据您的解释,您要实现的是服务链。我的理解是您正在尝试调用服务 1,如果失败,您将调用服务 2。 根据此服务 2,只有在服务 1 失败时才会被调用。如果是这种情况,您应该做的是您的故障序列应该保持每个呼叫的状态,并最终将其提交给呼叫者。最好的选择是为每个调用保留单独的序列,您可以从每个故障序列中调用这些序列。 这又取决于用例。如果当至少有 1 个服务失败时,如果你想把一切都失败,你可以直接从故障序列 return。如果没有,您可以按照我的建议进行操作。但这里的问题应该是什么状态代码。如果您设置为 200,则表示成功。如果一项服务失败,我们能说成功吗?这又取决于您的用例。

这就是我正在使用的解决方案。它可能不是最好的解决方案,但它确实可以满足需要。解决流程如下:

  1. 尝试最初的请求
  2. 如果失败,转到fault_handler,其中
  3. 转到Java Class读取xml文件以查看它是否在维护块中
  4. return 值并显示响应

这里是 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": "",
        "error": "",
        "error_description": ""
        }
    </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 />

调解器class方法如下:

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

希望这对某人有所帮助。