Azure Logic App – Lessons Learned – Part 1

At present the logic app workflows, API apps and the syntax for the template language expressions are, at best, a well-kept secret, with precious little documentation on their definition and even less on its usage.  Since I have not yet been able to discover the hidden treasure chest that contains these nuggets of golden information, and while I wait for someone to manifest a rainbow that will highlight the pot in which the chest can be found, I take up the challenge of Trial and Error.  As I unravel the mysteries of this new service I will endeavour to present them as a series of blog postings so that others may learn and hopefully contribute to this enigmatic treasure hunt!

Let the Treasure Hunting Begin!

Having had a strong BizTalk background, one of the first scenarios I wanted to try with Logic Apps was the receipt and validation of an XML document.  Using the “Create EAI Logic App using VETR” sample in the Azure documentation, I expected this to be a simple task.  I had a slightly simpler use case in mind, however, and just wanted to have the Logic App validate the XML document and then return either an HTTP status code of 200 or a 500 depending on the success or failure of the validation.  If the validation failed, I also wanted to return the reason for the failure.

Armed with these requirements, I set out to create a Logic App that could be used to achieve this.  The result was my Logic App that looked like this:image

My initial assumption was that the HTTP Listener would automatically return the result and error description, because the HTTP Listener had been created with the “Send response automatically” package setting set to “True”.image

So, when I sent a valid XML message to the Logic App, the returned message was the following:

<Response xmlns="https://httplistener…&quot;>
   <RequestId>734ae454a51e4aa3bf68fd8027a7f300</RequestId>
</Response>

And when sending a malformed XML message, the returned message was precisely the same (except of course the RequestId was a different value).  There was, however, no indication either in the message that was returned or in the Azure Portal that the validation had failed:
image

When drilling into the details of the run associated with the malformed message, the outputs of the XML Validator contained the Result property, which was false, and the ErrorDescription property which provided detail around WHY the validation failed.image

So, first lesson learnt: if the “Send response automatically” package setting is set to “True”, the HTTP Listener functions in an asynchronous manner, returning immediately with a request ID that can be used to later determine the status of the associated run.

In wanting to change this package setting, the second lesson learnt was that there is no interface that I could find where this setting can be changed after the HTTP Listener has been created!  Hopefully someone has found the hidden gem that enables one to change this property, without needing to re-create the listener? 

Third lesson learnt: You can delete the HTTP Listener API App even though it is still referenced in your Logic App.  While this allows you to create a new HTTP Listener API App and not have to delete it from the Logic App first, it should at least prompt you with a warning of the dependency before allowing you to delete it.

Fourth lesson learnt: With the HTTP Listener now re-created, with the “Send response automatically” package setting set to “False”, if you now send a message to the Logic App your client will time out because the Logic App does not return a response automatically.

So, we now need to add an action that will instruct the Logic App to return a response.  As per our requirements, however, we need to return an HTTP 200 status code if the validation was successful, and an HTTP 500 status code AND the error description if the validation failed.  So, we need two HTTP Listener Response actions.  The revised flow now looks like this:
finalFlow

When setting up the two HTTP Listener response actions, it took a lot of trial and error to figure out how the conditional expressions should be defined.  Initially, based on the details in the “Create EAI Logic App using VETR” article, I defined the condition as @equals(actions('messagevalidationxmlvalidator').status, 'Succeeded')

The problem with this condition was that the XML Validator always returned a status of “Succeeded”, even if the validation failed.  So, I set out to find another way of identifying if the validation had been successful or not.  After much trial and error, I determined that by using the “Result” property I could identify if the validation had succeeded or not.  So, the two conditions became:

@equals(body('messagevalidationxmlvalidator').Result,bool('True'))

and

@equals(body('messagevalidationxmlvalidator').Result,bool('False'))

The fifth lesson learnt, therefore, was that if your property (“Result”) is Boolean, you have to use the bool operator in your equals function to compare the left and right values.  In other words, if you try an expression like

@equals(body('messagevalidationxmlvalidator').Result,True)

you will get the following error:

{
     "code":"ActionConditionFailed",
     "message":"The execution of template action 'messagevalidationxmlvalidator' is skipped: the condition expression '@equals(body('messagevalidationxmlvalidator').Result,True)' is not satisfied: 'False'."
}

So, with the correct conditions in place, now when sending a valid XML message, what is returned is an HTTP Status of 200 and a body that looks like this:

<data contentType="text/plain; charset=utf-8" contentLength="30">
    <![CDATA[Message validated successfully]]>
</data>

When sending a malformed XML message, an HTTP Status code of 500 is returned containing the following in its body:

<data contentType="text/plain; charset=utf-8" contentLength="370">
    <![CDATA[Message validation failed: XML Input matched schema TestSchema but validation failed with error The '
http://schemas.datacontract.org/2004/07/TestSchema:TestContent&#039; element is invalid – The value '27cc6.87' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:decimal&#039;
– The string '27cc6.87' is not a valid Decimal value..]]>
</data>

Conclusion

In summary, there is a lot that we still need to learn about Azure Logic Apps and hopefully there is a lot of documentation still to come on its use, but in the meantime these are the lessons I have learnt in my first attempt to use the Logic Apps:

  • Setting the “Send response automatically” property in the Package Settings of an HTTP Listener API App makes the logic app flow asynchronous.  In other words, a RequestId will be returned to the caller as soon as the HTTP Listener API App has successfully received the request, regardless of what happens to the request thereafter.
  • Changing the “Send response automatically” property after the HTTP Listener API App has been created is not possible.
  • Deleting an HTTP Listener API App from the list of API Apps does not raise any warnings that the API App is in use within a Logic App, so be careful.  Assumedly this is true for any API App, but I have not yet tested that.
  • When the HTTP Listener API App is re-created, and provided it has the same name that was used when creating the Logic App, the Logic App will use this new API App without any changes needing to be made.  It should be noted, however, that if you are sending your message to the HTTP Listener from a client, re-creating the HTTP Listener will change the URL that your client has to use.
  • When setting a condition in an action, and you want to compare a Boolean property with a Boolean string, you need to use the bool function to convert either “True” or “False” to a Boolean value.

Hopefully this helps others who are also learning this wonderful new Azure App service, and if I have made any errors or if you have any other gems you would like to share, please let me know.  Together, we can find the treasure chest! Smile

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.