Geeks With Blogs

News This is the *old* blog. The new one is at blog.sixeyed.com
Elton Stoneman
This is the *old* blog. The new one is at blog.sixeyed.com

BizTalk 2013 makes communication with the modern world of RESTful cloud services nice and simple, while sticking to the established BizTalk components and workflows. Richard Seroter has blogged about consuming REST services in BizTalk 2013, and Saravana Kumar about consuming JSON in BizTalk 2010 R2 – this post will tie the two together, and provide a generic pipeline component to convert from JSON to XML (complete with a root element name and namespace in the output message). I’ll use the document database MongoDB as the provider of my REST service.

Setting up MongoDB on Azure

Through the Windows Azure MongoLab add-in, you can create your own MongoDB instance hosted on Azure (free, with a 500Gb size limit) in a handful of clicks:

 

image003

When it’s provisioned, click on Manage in the Azure admin console to take you to the the MongoLab admin console:

image001

Click Open API view and you’ll get the REST URL for your database, with a query string which contains the API key you’ll need for every request:

image002

Creating and Fetching Documents with REST

With the URL and API key, you can switch to the Firefox RESTClient add-on and start accessing your MongoDB database with pure HTTP. Mongo has a simple structure – collections live inside the database, and documents live inside collections. To insert a new document, issue a POST to the collection – if the collection doesn’t exist, Mongo will create it for you. In my case, the base URL for the database is:

I’ll be using it to store information about vehicles. To add a document describing a vehicle to the vehicles collection, the POST request will use this URL and body:

  • {"makeCode":"volvo","modelCode":"amazon","imageUrl":"xyz"}

A successful response returns the stored document in the body, which now has an unique _id value, computed by Mongo:

image008

[ { "_id" : { "$oid" : "51651209e4b0242e80243468"} , "makeCode" : "volvo" , "modelCode" : "amazon" , "imageUrl" : "xyz"} ]

Note that your POST could have contained multiple documents, so you get an array back (JSON array notation: [ ]). In this case, the array has a single document. To read that document, the URL is /collections/{collection}/{documentId}:

Consuming the MongoDB REST API with BizTalk 2013

If we want to get that document into BizTalk, we can set up a static solicit-response send port, using the WCF-WebHttp adapter. At the simplest level, you can put the full URL into the Address,  specify GET as the HTTP Method, and in the Messages tab specify to suppress the message body on GETs (with the release version of BizTalk 2013, you no longer need a custom component to strip the body for outgoing REST calls – although it doesn’t default the entry for GETs):

image004 image005

That will bring the document into the message box in JSON format, so BizTalk can’t do much with it. Saravana provides a simple pipeline component which uses JSON.NET (the JSON parser which even Microsoft prefers to the .NET DataContractJsonSerializer – it’s the parser used in Web API). That component converts JSON to XML, but it needs a bit more work to produce a working XML document that will match a BizTalk schema with a namespace and a root node.

I’ve extended that component to have TargetNamespace and RootElementNode properties, and in the conversion it sets up the XML output correctly (this only works for documents which have a single namespace used throughout). You can get the code on github here: Parsing JSON to XML in BizTalk, which contains a sample project with this MongoDB REST walkthrough. The basis is the same, but JSON.NET doesn’t give you much control over namespaces without actually changing the JSON, which isn’t generic, so instead we parse it using JSON.NET and then update the namespaces manually:

//convert to XML: 
var document = JsonConvert.DeserializeXNode(json, "root"); 
var output = new XElement(XName.Get(RootElementName, TargetNamespace)); 
output.Add(document.Root.Descendants());

//fix up the namespaces: 
XNamespace ns = TargetNamespace; 
foreach (var element in output.Descendants()) 
{ 
    element.Name = ns.GetName(element.Name.LocalName); 
    var attributes = element.Attributes().ToList(); 
    element.Attributes().Remove(); 
    foreach (XAttribute attribute in attributes) 
    { 
        if (!attribute.IsNamespaceDeclaration) 
        { 
            element.Add(new XAttribute(attribute.Name.LocalName, attribute.Value)); 
        } 
    } 
}

By wrapping the component in a receive pipeline, specifying the root element name and namespace of your XML document schema and using the pipeline in your send port, your JSON response from Mongo enters the message box as a well-formed and valid XML document, complete with a promoted message type property. The pipeline component is generic, in that it will work for any JSON and output it to and XML schema, with the limitation that the schema has to have a single namespace.

Parameterizing the REST URL in the Send Port

BizTalk lets you parameterize the URL for the WCF-WebHttp adapter, so you can pull values from the message properties into the URL for the request. In the sample solution I have an incoming message which contains the ID of the vehicle to get details for. An orchestration picks up the message, calls into Mongo and then maps the response (to prove that the transformed JSON is a valid XML message which BizTalk can operate on). In the send port definition, you need to change the address to the base URL for the service:

- and in the HTTP Method and URL Mapping section, specify the relative path and record parameters in braces: /vehicles/{vehicleId}?apiKey=etc

image009

<BtsHttpUrlMapping>
 <Operation Name="GetVehicle" Method="GET" Url="/vehicles/{vehicleId}?apiKey=5162d1f18e87e1850a000071" />
</BtsHttpUrlMapping>

Then you can map the parameter values in the Variable Mapping window – there will be an entry for every variable you specify in the URL:

image010

For each variable, enter the source property from the message. The property needs to be promoted in a property schema (not just a distinguished property in the entity schema), and that grid in the “Variable Mapping” window does not have dropdowns. Everywhere else in the Admin Console you have to pick a property schema and then the property name from lists, but in this window you just type the text directly – so you need to get it exactly right from the property schema.

Running the Sample

  • set up your MongoDB instance (mine will be used for something else by the time you read this)
  • download the solution and deploy the BizTalk project from VS 2012
  • run Setup.cmd to create file drop locations
  • import the bindings XML file into the Sixeyed.BizTalk.JsonParser.Sample BizTalk app
  • update the base URL and apiKey in the Mongo send port sndGetVehicle.REST
  • start the BizTalk app
  • add your object ID into a text file and copy to c:\Drops\VehicleSnapshotRequests
  • if everything works, you’ll get a new file in c:\Drops\VehicleSnapshots

When you drop the file it goes through a flat-file schema, and is picked up by the orchestration. The orchestration calls into the REST port, which has the JSON-to-XML pipeline in the receive, so it gets an XML message back. The orchestration maps the response from Mongo to a summary schema, and sends it to the output file port.

BizTalk has called a REST service in the cloud, got JSON back and treated it as it would any other incoming message.

Posted on Thursday, April 11, 2013 7:05 PM The Cloud , Azure , BizTalk 2013 , NoSQL | Back to top


Comments on this post: Connecting BizTalk 2013 to MongoDB with REST+JSON

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Elton Stoneman | Powered by: GeeksWithBlogs.net