Accessing XML Fields Within a Logic App

By Nick Hauenstein

Earlier this week, I was revisiting a design for a Logic App that interacted with an event about a business entity that was represented as an XML message. It used data from this XML message to invoke actions later in the process, and relied on the XPath Extractor API App to provide access to the data contained within the XML. It looked something like this:

design1

At the time, the choice to use XPath Extractor API Apps was an alright choice, given that there weren’t really any alternative API Apps in the marketplace that allowed one to cross the XML / JSON divide – JSON being the native tongue of Logic Apps. That has since changed, and upon revisiting the design, it became apparent that using the XPath Extractor was a poor choice.

I wasn’t doing anything complex (e.g., selecting the text inside an element only when that element had an attribute with a specific value and appeared nested inside an element beginning with a certain set of characters), I was just trying to retrieve the values stored within scalar elements within the same location in the XML document each time – elements that I would have simply treated as distinguished fields in BizTalk Server and happily dotted into while editing an expression.

Despite not doing something complex, the original design was using 3 separate API App executions just to read 3 separate values. That seems a little bit wasteful for something that the Logic App runtime would give me for free with JSON data.

Using the Right Tool to Bridge the XML / JSON Divide

So what API App was added into the mix since the original plan for this Logic App? The BizTalk JSON Encoder API App – which provides translation from/to XML/JSON.

design2

It accomplishes this in a similar way to BizTalk Server’s own JSON Encoder / JSON Decoder pipeline components, and like those components also requires an XML schema in order to perform the conversion from JSON to XML. The schema can be written by hand, generated from JSON in the Azure Portal, generated from a Flat-file in the Azure Portal, or created using Visual Studio 2012 with the MABS SDK.

Once you have your schema, you can use the Components tile of the JSONEncoder API App within the Azure Portal to access an interface to upload and provide a name for the schema.

image

In the case of XML to JSON, the conversion can occur with or without a schema (i.e., a schema isn’t going to be used, but it won’t hurt anything if you upload one either).

Doing Simple Things with Simple Data

So how do we do something simple (e.g., access a few fields) with simple data? Thankfully, the answer is quite easily. First off, you will need to create an instance of the BizTalk JSON Encoder API App. This instance can be re-used for any XML to JSON conversions that you will require. Converting back to XML from JSON assumes that you have created the requisite schemas and uploaded them for the instance. One downside here is that you cannot share schemas between instances (as they are stored in local storage for the API App on the Gateway).

Once you have the API App, you can feed it any arbitrary XML payload and it will provide a nice JSON representation that you can dot into for any later actions in a Logic App. Unfortunately, its flexibility comes at the cost of rich metadata describing the shape of the output (i.e., the designer won’t be able to help you know which nodes will actually exist in the output, regardless of potentially having a schema available).

image

So let’s make it happen. I have an event about a business entity (product) that looks something like this as XML:

image

Let’s say that I want to retrieve the ProductName out of this message. In that case, the expression within a Logic App to retrieve the value would look something like this:

@body(‘jsonencoder’).OutputJSON.ProductEvent.ProductName

If the Remove Outer Envelope property on the BizTalk JSON Encoder API App was set to true, then it would look like this instead:

@body(‘jsonencoder’).OutputJSON.ProductName

As shown in the screenshot above, neither of these expressions are going to show up within my nice little drop-down list of values to select. Instead, I must dot into it in trust that it will be there. But how can we be a little bit more sure? We could couple it with an XML Validator, or add a condition on the action based on the logical existence of the node.

Does the simple case work though? Well, after updating the expression:

image

And then submitting the sample message to the source queue, this was the input/output set of the BizTalk JSON Encoder:

image

image

And this was the data that showed up in the request bin:

image

What If I Have More Complex Data?

What if the data that I have isn’t just a bunch of text in elements, but I have a complex structure with repeating nodes and attribute values? To find out, I loaded up the sample message with some sample data to see.

image

Running that through the JSON Encoder, I saw this output:

image

Attributes are represented as properties prefixed with @ and the text included in a node is represented as the value of a property named #text. Repeating nodes are collapsed into an array sharing the name of the node name – perfect for repeating an action against.Smile

Then, When Is the XPath Extractor the Right Answer?

Simple data or complex data might not be the determining factor in the choice between using the XPath Extractor or JSON Encoder API Apps to access data locked up in an XML message. Instead, it looks like the determining factor is how hard it is to describe where that data lives (or doesn’t live) within the content. In all the cases we’ve seen thus far, we referenced by name / location in the document. XPath will shine when we don’t have that information, or when we want information about the content in the document, and as such still deserves a place in the toolbox.

However, just because you’re trying to get data out of XML, and all previous knowledge points to XPath as the answer, it might not be – instead, the answer might be to translate that message into the native tongue of the runtime that’s interacting with it.

What’s Next?

I currently owe all of you readers out there a post about push triggers. I have most of it written, but I’m not yet fully pleased with it. I’ll try to get that out as soon as possible. Additionally, there’s another post that I’m even more excited about, one that I’ve been thinking about for the last 3 years. I’m likely going to be posting that one shortly after WPC.

Stay tuned. There’s heaps that I want to share, but, alas, the constraints of the solar day and the capacity of my human flesh prevent it from happening all at once.

How to Build A Polling Trigger API App

By Nick Hauenstein

In my first article recapping the BizTalk Summit 2015, I said I would revisit the topic of triggers for those of you wanting to build out custom API Apps that implemented either of those patterns.

After working through the official docs, and reviewing the code presented at the BizTalk Summit 2015 in anticipation of our upcoming Cloud-Based Integration Using Azure App Service class, I decided to take a little bit of a different direction.

Rather than do a write-up both here, and in hands-on-lab form within the class of writing a bunch of custom Swashbuckle operation filters for generating the appropriate metadata for a Logic App to properly consume an API App that’s trying to be a trigger, I decided to write up a library that just made it a little bit easier to create custom API Apps that are consumable from the Logic App designer.

How did I go about doing that? Well Sameer Chabungbam had mentioned in his presentation that a more elegant solution might be to use attributes for friendly names and the like. So I went in that direction, and made attributes for all of the stuff that the Logic App designer needs to have in a certain way (really anything that involved vendor extensions in the generated swagger). What do we do with all of those attributes? Well, we uh, read them in custom operation / schema filters of course! So yes, I did have to write some custom filters after all, but now you don’t have to!

Announcing QuickLearn’s T-Rex Metadata Library

PackageIconI rolled all of the code into a library that I’ve named the T-Rex Metadata Library1. The library is available as a NuGet package as well that you can add directly to your API App projects within Visual Studio 2013.

So how can we use that to make custom triggers? I’m glad you asked. Let’s get right into it.

Creating Custom Polling Triggers

The easiest kind of trigger to implement is a polling trigger. A polling trigger is polled by a Logic App at a set polling interval, and is asked for data. When the trigger has data available, it is supposed to return a 200 OK status with the data contained in the response body. When there is not data available, a 202 Accepted status should be returned with an empty response body.

You can find an example of a polling trigger over here. This polling trigger takes in a single configuration parameter named “divisor” and when polled will return data if and only if the current minute is evenly divisible by the divisor specified (kind of silly, I know).

So, how do I separate sample from reality and actually build one?

Steps for Creating a Polling Trigger

  1. Create a new project in Visual Studio using the Web Application template
  2. Choose API App (Preview) as the type of Web Application you are creating
  3. Add the TRex NuGet package to your project
  4. In the SwaggerConfig.cs file, add a using directive for TRex.Metadata
  5. In the SwaggerConfig.cs file, just after the line showing how to use the  c.SingleApiVersion add a line that reads c.ReleaseTheTRex();
  6. Add using directives for the Microsoft.Azure.AppService.ApiApps.Service, and TRex.Metadata namespaces.
    • Microsoft.Azure.AppService.ApiApps.Service provides the EventWaitPoll andEventTriggered extension methods
    • TRex.Metadata provides the T-Rex Metadata attribute, and the Trigger attribute
  7. Create an action that returns an HttpResponseMessage
  8. Decorate the action with the HttpGet attribute
  9. Decorate the action with the Metadata attribute and provide a friendly name, and description, for your polling action
  10. Decorate the action with the Trigger attribute passing the argument TriggerType.Poll to the constructor, as well as the type of model that will be sent when data is available (e.g.,typeof(MyModelClassHere))
  11. Make sure the action has a string parameter named triggerState
    • This is a value that you can populate and pass back whenever polling data is returned to the Logic App, and the Logic App will send it back to you on the next poll (e.g., to let you know that it is finished with the last item sent)
    • You do not need to decorate this parameter with any attributes. T-Rex looks for this property by name and automatically applies the correct metadata (friendly name, description, visibility, and default value)
  12. Optionally, add any other parameters that controls how it should poll (e.g., file name mask, warning temperature, target heart rate, etc…)
    • Decorate these parameters with the Metadata attribute to control their friendly names, descriptions, and visibility settings
  13. Make sure that the action returns the value generated by calling Request.EventWaitPoll when no data is available
    • You can also provide a hint to the Logic App as to a proper polling interval for the next request (if you anticipate data available at a certain time)
    • You can also provide a triggerState value that you want the Logic App to send to you on the next poll
  14. Make sure that the action returns the value generated by calling Request.EventTriggered when data is available
    • The first argument should be the data to be returned to the Logic App, followed by the newtriggerState value that you want to receive on the next poll, and optionally a new polling interval for the next request (if you anticipate data available at a certain time, or more likely that you know more data is immediately available and there isn’t a need to wait).

After you publish your API App, you should be able to use it as a trigger in a Logic App. Here’s what the sample looks like after being deployed:

Polling Trigger Sample

Next Up

In my next post, I’ll turn my focus to custom push triggers. For now though, I need to rest a little bit to get ready for 2 days of teaching followed immediately by Build 2015! It’s going to a long, yet quite fun week this week!

Until next week, take care!

1It was named this so that it would comply with the latest trends of fanciful library names, and so that I could justify naming a method ReleaseTheTRex. If you believe the name too unprofessional, let me know and I may add a TRex.Enterprise.Extensions namespace that includes a more professional sounding method name which simply calls into the former.