2

We have an Azure API Management endpoint that receives requests in the following format:

{
    "messageType": "EVENT",
    "eventData": {
        "installedApp": {
            "installedAppId": "xxx",
            "locationId": "yyy"
        },
        "events": [
            {
                "eventTime": "2020-11-13T13:14:50.8011105+00:00",
                "eventType": "DEVICE_EVENT",
                "deviceEvent": {
                    "eventId": "3a08b3f3-25b1-11eb-962f-975d499d1166",
                    "locationId": "yyy",
                    "ownerId": "a975533a-a1ae-49f7-88f1-94368bd4d605",
                    "ownerType": "LOCATION",
                    "deviceId": "c3fdc7c6-08f2-4ba3-92b3-0cdfa2b141f5",
                    "componentId": "main",
                    "capability": "motionSensor",
                    "attribute": "motion",
                    "value": "inactive",
                    "valueType": "string",
                    "stateChange": true,
                    "data": {},
                    "subscriptionName": "all_motion_sub"
                }
            }
        ]
    }
}

It passes them through a Liquid template:

<set-body template="liquid">{
    "id": "{{context.Variables["RequestId"]}}",
    "API": "SmartThings",
    "InstalledAppId": "{{body.eventData.installedApp.installedAppId}}",
    "LocationId": "{{body.eventData.installedApp.locationId}}",
    "DeviceEvents":[
        {% assign device_events = body.eventData.events | Where: "eventType", "DEVICE_EVENT" %}
        {% JSONArrayFor event in device_events %}
        {
            "EventId": "{{event.deviceEvent.eventId}}",
            "LocationId": "{{event.deviceEvent.locationId}}",
            "DeviceId": "{{event.deviceEvent.deviceId}}",
            "ComponentId": "{{event.deviceEvent.componentId}}",
            "Capability": "{{event.deviceEvent.capability}}",
            "Attribute": "{{event.deviceEvent.attribute}}",
            "Value": "{{event.deviceEvent.value}}",
            "StateChange": {{event.deviceEvent.stateChange}},
            "EventTime": "{{event.eventTime | Date: "yyyy-MM-ddTHH:mm:sszzz" | Default: context.Variables["RequestDateTime"] }}"
        }
        {% endJSONArrayFor  %}
    ],
    "EventTime": "{{context.Variables["RequestDateTime"]}}"
}</set-body>

And generates an output which is sent to a Logic App for further processing:

{
    "id": "d5e2a032-14b3-40ca-9c6b-4e13f8d2285c",
    "API": "SmartThings",
    "InstalledAppId": "xxx",
    "LocationId": "yyy",
    "DeviceEvents": [
        {
            "EventId": "3a08b3f3-25b1-11eb-962f-975d499d1166",
            "LocationId": "yyy",
            "DeviceId": "c3fdc7c6-08f2-4ba3-92b3-0cdfa2b141f5",
            "ComponentId": "main",
            "Capability": "motionSensor",
            "Attribute": "motion",
            "Value": "inactive",
            "StateChange": true,
            "EventTime": "2020-11-13T13:14:50.8011105+00:00"
        }
    ],
    "EventTime": "2020-11-13T13:14:50.8011105+00:00"
}

Until around 23:00Z on 11/11/2020, this worked as expected, and had been working in production for several months. Commencing at that time, the Liquid mapping began to fail, producing instead:

{
    "id": "2c93647c-f9ef-4747-adfb-985805a71f0c",
    "API": "SmartThings",
    "InstalledAppId": "xxx",
    "LocationId": "yyy",
    "DeviceEvents": [
        {
            "EventId": "",
            "LocationId": "",
            "DeviceId": "",
            "ComponentId": "",
            "Capability": "",
            "Attribute": "",
            "Value": "",
            "StateChange": ,
            "EventTime": "2020-11-13T13:14:50.8011105+00:00"
        }
    ],
    "EventTime": "2020-11-13T13:14:50.8011105+00:00"
}

We have a scheduled maintenance event in the logs to 'Upgrade API Management' from midnight Thursday, so it looks like there was some kind of breaking change.

What changed to cause this, and how do we go about fixing it?

Jude Fisher
  • 11,138
  • 7
  • 48
  • 91

1 Answers1

3

For this problem, I test it in my side and also reproduce your situation. It seems there is bug of liquid template in APIM. After reproduce your problem, I test in another APIM but it doesn't show same problem, the liquid template works fine in that APIM. Then I test in multiple APIM(with same set-body policy and request body) and summarize the result as below:

enter image description here

According to many test and the test result above, I guess it may be some bug after upgrade APIM. And the bug may be related to location or pricing tier(I'm not sure) because I can't find any differences between these APIM except location and pricing tier. So I suggest you to do same job in another APIM(with different location and pricing tier), it will solve the problem temporarily.

===============================Update=============================

I did some further test and found a workaround for this problem. I found the problem was caused by the line {% assign device_events = body.eventData.events | Where: "eventType", "DEVICE_EVENT" %}. If we don't assign body.eventData.events to device_events, instead use body.eventData.events directly in for loop like {% JSONArrayFor event in body.eventData.events %}. Then the liquid template works fine.

So we can just remove the line of "assign" and do "where" condition in for loop. Please refer to my liquid template below: enter image description here

Hury Shen
  • 14,948
  • 1
  • 9
  • 18
  • Thanks - this is useful. I'm given to understand the problem is being actively investigated so will hang fire to see if they come up with a fix or a workaround. – Jude Fisher Nov 16 '20 at 13:15
  • Hi @JudeFisher I did some more test and update my answer. Please refer to my "Update". – Hury Shen Nov 17 '20 at 03:28
  • Hi @JudeFisher May I know if the update workaround works in your side ? – Hury Shen Nov 17 '20 at 09:38
  • 1
    Yes the workaround is good. Many thanks. I'll leave the question open for a bit, as I'm still interested to know how this got broken, and what any permanent fix should be - but I'll accept your answer in a few days if nothing else comes in. – Jude Fisher Nov 18 '20 at 12:18
  • Hi @JudeFisher Since there aren't any other answer, could you please accept my answer, thanks~ – Hury Shen Nov 25 '20 at 08:50