Как я могу правильно управлять случаем ошибки WSO2 ESB?Могу ли я централизовать все ошибки ситуации в faultSequence? - PullRequest
0 голосов
/ 13 июня 2018

Я работаю над проектом WSO2 ESB , и у меня есть некоторые сомнения относительно того, как правильно обрабатывать ситуацию с ошибками.

Так, например, у меня есть этот API:

<?xml version="1.0" encoding="UTF-8"?>
<api context="/weather/crop_calendar" name="crop_calendar" xmlns="http://ws.apache.org/ns/synapse">
    <resource methods="GET" uri-template="/country/{countryId}/crops?lang={lang_id}">
        <inSequence>
            <log level="full"/>
            <property expression="get-property('uri.var.countryId')" name="countryId" scope="default" type="STRING"/>
            <property expression="$url:lang" name="langId" scope="default" type="STRING"/>
            <log level="custom">
                <property expression="$ctx:countryId" name="countryId"/>
                <property expression="$ctx:langId" name="langId"/>
            </log>
            <property name="messageType" scope="axis2" type="STRING" value="application/xml"/>
            <payloadFactory media-type="xml">
                <format>
                    <ds:GetCropCalendarCommoditiesList xmlns:ds="http://ws.wso2.org/dataservice">
                        <country_id>$1</country_id>
                        <ds:language_id>$2</ds:language_id>
                    </ds:GetCropCalendarCommoditiesList>
                </format>
                <args>
                    <arg evaluator="xml" expression="$ctx:countryId"/>
                    <arg evaluator="xml" expression="$ctx:langId"/>
                </args>
            </payloadFactory>
            <header name="Action" scope="default" value="urn:SelectCropCalendarCommoditiesList"/>
            <call>
                <endpoint key="cropCalendarEndpoint"/>
            </call>
            <property name="messageType" scope="axis2" type="STRING" value="application/json"/>
            <property expression="json-eval($.)" name="JSONPayload" scope="default" type="STRING"/>
            <script language="js"><![CDATA[var log = mc.getServiceLog();

                function scan(obj) {
                    var k;
                    if (obj instanceof Object) {
                        for (k in obj){
                            if (obj.hasOwnProperty(k)){

                                obj[k] = checkForNull(obj[k]);
                                //recursive call to scan property
                                scan(obj[k]);  
                            }                
                        }
                    } else {
                        //not an Object so obj[k] here is a value
                    }

                }

                function checkForNull(value) {
                    if (value instanceof Object && "@nil" in value) {
                        return null;
                    }

                    return value;
                }

                log.info("----------------------------- CROP CALENDARD COMMODITIS LISTING SCRIPT START ------------------------------------------------");

                var lang_id = mc.getProperty('langId'); 

                // stange workaround for getting JSON Payload. getPayloadJSON returned null. 
                var pl_string = mc.getProperty("JSONPayload"); 
                log.info("PAYLOAD STRING: " + pl_string);
                var payload = JSON.parse(pl_string);

                // Create new response:          
                var response = payload;

                log.info("RESPONSE: " + JSON.stringify(response));

                scan(response);

                // Fix the single element problem:
                if (!(response.CropCalendarCommodities.CommoditiesList instanceof Array)) {
                    log.info("It is not an array, convert it into an array");

                    singleCommodity = response.CropCalendarCommodities.CommoditiesList;

                    response.CropCalendarCommodities.CommoditiesList = [];
                    response.CropCalendarCommodities.CommoditiesList.push(singleCommodity);
                }

                // Convert array of crops into required HATEOS format
                var cropsList = new Array();

                for (i = 0; i < response.CropCalendarCommodities.CommoditiesList.length; i++) {
                    log.info("Crop: " + i + " CROP NAME: " + response.CropCalendarCommodities.CommoditiesList[i].commodity_name);

                    commodityCropCalendarDetailsLinks = [];

                    commodityCropCalendarDetailsRefObj = {};

                    commodityCropCalendarDetailsRefObj.rel = "commodity_enutrifood_details";
                    commodityCropCalendarDetailsRefObj.href = "http://5.249.148.180:8280/weather/crop_calendar/commodity/" + checkForNull(response.CropCalendarCommodities.CommoditiesList[i].commodity_id) +  "?lang=" + lang_id; 
                    commodityCropCalendarDetailsRefObj.type = "GET";

                    commodityCropCalendarDetailsLinks.push(commodityCropCalendarDetailsRefObj);

                    response.CropCalendarCommodities.CommoditiesList[i].links = commodityCropCalendarDetailsLinks;

                }


                log.info("----------------------------- CROP CALENDARD COMMODITIS LISTING SCRIPT END ------------------------------------------------");
                // put payload back
                mc.setPayloadJSON(response);]]></script>
            <property name="RESPONSE" scope="default" type="STRING" value="true"/>
            <header action="remove" name="To" scope="default"/>
            <send/>
        </inSequence>
        <outSequence/>
        <faultSequence>
            // HERE HANDLE THE ERROR CASES
        </faultSequence>
    </resource>
</api>

Этот API принимает 2 входных параметра в URL:

  • countryId
  • lang_id

и использует оба для выполнения запроса DSS, затем выходные данные запроса преобразуются в документ JSON , а затем посредник сценария обрабатывает этот документ JSON.

Ошибка можетпроисходит в этой цепочке посредников.

Например, передача countryId , относящегося к стране, поэтому в базе данных нет данных, запрос DSS возвращает что-то вроде этого (после преобразования JSON thge):

{"CropCalendarCommodities":null}

Проблема в том, что когда этот документ обрабатывается посредником Script , WSO2 приводит к ошибке, поскольку не может получить доступ к этому элементу в предыдущем JSON:

CropCalendarCommodities.CommoditiesList

и я получаю ошибку, подобную этой:

TID: [-1234] [] [2018-06-13 10:26:58,527] ERROR {org.apache.synapse.mediators.bsf.ScriptMediator} -  The script engine returned an error executing the inlined js script function mediate {org.apache.synapse.mediators.bsf.ScriptMediator}
com.sun.phobos.script.util.ExtendedScriptException: org.mozilla.javascript.EcmaError: TypeError: Cannot read property "CommoditiesList" from null (<Unknown Source>#45) in <Unknown Source> at line number 45
        at com.sun.phobos.script.javascript.RhinoCompiledScript.eval(RhinoCompiledScript.java:68)
        at javax.script.CompiledScript.eval(CompiledScript.java:92)
        at org.apache.synapse.mediators.bsf.ScriptMediator.mediateForInlineScript(ScriptMediator.java:345)
        at org.apache.synapse.mediators.bsf.ScriptMediator.invokeScript(ScriptMediator.java:265)
        at org.apache.synapse.mediators.bsf.ScriptMediator.mediate(ScriptMediator.java:233)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:260)
        at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.mediateFromContinuationStateStack(Axis2SynapseEnvironment.java:775)
        at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:282)
        at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:554)
        at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:188)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:262)
        at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.mozilla.javascript.EcmaError: TypeError: Cannot read property "CommoditiesList" from null (<Unknown Source>#45)

Я сомневаюсь:

Как лучше всего справиться с подобной ситуацией?

Я знаю, что могу справиться с ситуацией внутри посредника сценариев (и это довольно просто:Я проверяю, равен ли CropCalendarCommodities.CommoditiesList null .Если оно пустое, я создаю опосредованный ответ JSON, который будет возвращен этому пользователю (что-то, содержащее сообщение о состоянии 404 ).

Но я сомневаюсь: могу ли я централизовать управление всемислучай возможной ошибки в последовательности ... .

Если да, то в этом случае мне нужен способ получить тип ошибки, произошедшей в моем .

В этом случае, если ошибка в посреднике сценария , я могу создать сообщение о состоянии 404 , которое будет возвращено пользователю.Но если произошла другая ошибка (например, DSS не может получить доступ к БД), я создам другое сообщение об ошибке, которое будет возвращено пользователю.

Я пытаюсь централизоватьУправление ошибками и обработка ситуации с ошибками способом, более похожим на классическую концепцию исключения.

Могу ли я сделать это каким-то образом?

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Последовательность ошибок будет вызываться при возникновении ошибки. Хорошая идея поместить что-то туда, иначе клиент продолжит ждать ответа.См. документацию по обработке ошибок для получения дополнительной информации.

Следует помнить, что в DSS, если база данных возвращает ошибку, это не приведет к вызову последовательности ошибок.Вам необходимо установить свойство FORCE_ERROR_ON_SOAP_FAULT .

Если у вас есть группа посредников, для которых вы хотите по-разному обрабатывать ошибки, рассмотрите возможность их перемещения на Sequence (давайте назовем это CodeSeq).Затем вы создаете другую последовательность, содержащую обработку ошибок (назовем ее ErrorSeq).Затем в CodeSeq вы можете указать атрибут on on onError="ErrorSeq".

0 голосов
/ 13 июня 2018

Да последовательность ошибок - это место для обработки ошибок.Вы можете использовать

  • get-property ('ERROR_CODE')
  • get-property ('ERROR_MESSAGE')

Вы можете создать пользовательскую ошибкуполезные данные с соответствующим HTTP_SC и ответ клиенту.

https://docs.wso2.com/display/ESB481/Error+Handling

...