Oslo based solution for deploying BizTalk applications – the runtime
This is a third post in a series describing my Oslo based solution for deploying BizTalk applications; I’ve used this exercise to play around with ’M’, but it was important for me to work on a real solution, with real benefits – something I could actually usein Part I I discussed the concept and presented both the “source code” of my app and the output I was working toward; Part II was all about the MGrammar part of the solution.
In this, third, part I will discuss the last missing piece -the runtime.
Before I start, though, I would say that I did find getting into ’M’ somewhat confusing at first; and while it’s more than just possible I’m still missing some things , I hope this series could help one or two people in their journey with Oslo – which is, without a doubt, an exciting one!
There are two things, I believe, that contributed to my confusion – the first is the fact the M is really many things, quite different things, actually; from what I hear Microsoft have identified the challenge some of us (me) are having getting a grasp on ’M’ and are hard at work to bring things [closer] together; hopefully it won’t be long before we know how the converged language looks like, in the mean time one simply has to remember that –
There’s MSchema – which you could use to define models, a bit like xml-schema, or declaring your classes in code or even tables in SQL; I haven’t really touched on MSchema in this series butI might come back to that later.
Then there’s MGraph, which is a way to define instances of things, possibly ones that have been modelled using MSchema, but, as is evident from my little project, not necessarily – MGraph can be very useful even if you don’t have a model- as long as you have your grammar – in comes MGrammar, the third spect of ’M’, which can be used to define a syntax for your very own [domain-sepcific-]languge for describing things;
A ’runtime’ could then be used to processes instances described as MGrammar as a result of inputs in your language.
And that is the second thing that really confused me – what is that ’runtime’? in all the ’M’ presentations I’ve seen, the ’runtime’ was merely mentioned and has never received enough “floor space” and yet – an MGrammar without a runtime, in the majority of cases, is, quite useless; you have to have a runtime that would act on your source code; in fact – the runtime would act on the MGraph resulting from your language, which is what makes it all so brilliant, because in a sense, this is where everything comes together – you runtime can work on instances described in your language, on MGraph instances stored in the repository created using MSchema and possibly even ones defined using Quadrant.
The point is that there must be a runtime that understand the model behind your language , can parse its graph and then do whatever you need it to do; and it is your job to build that runtime.
So what have I done for my runtime? here’s a quick overview (reminder: the full source code will find its way shortly onto codeplex) –
My runtime is a console application, one that takes a source code file path as an argument and outputs MSBuild files (and dependencies) that can be used to deploy the application described in the source code onto BizTalk Server.
The first part of my runtime – which I will not bore you with – is about validating the command line arguments; standard stuff.
The second part is about creating the parser for my language, where, thankfully, the Oslo SDK does all of the heavy lifting – it includes a class called DynamicParser which, once created, you can use to parse your source code.
To create the DynamicParser you must first compile your language, and that’s easy enough to do – you start by creating a compiler
MGrammarCompiler compiler = new MGrammarCompiler();
and continue by supplying your grammar
compiler.SourceItems = new SourceItem[] { new SourceItem { Name="BTSDeploy", ContentType = ContentType.Mg, TextReader = new StreamReader(GetLanguageDefinition()) } };
(GetLanguageDefinition() is a simple helper method I wrote to get the grammar file embedded as a resource in the exe)
Now you’re ready to compile your language, but to make things manageable you want to provide it with an error reported; the compiler would report any errors to the stream you would provide, I’ve naturally used the console
TextWriterReporter errorReporter = new TextWriterReporter(Console.Out); if (compiler.Compile(errorReporter) != 0 || errorReporter.HasErrors) { Log("Failed to compile language definition\nSee above for details"); return null; }
If the compilation succeeded you are ready to create your parser –
DynamicParser parser = new DynamicParser(); compiler.LoadDynamicParser(parser);
That’s part one of three done.
The next step is to use the dynamic parser to parse your source code, the output of which would be a graph representation of the source; luckily the SDK does virtually all the lifting here as well, and it comes down to one line –
object rootNode = parser.Parse<object>(sourceCodeFileName, null, errorReporter);
Note that the output type is object – which, as you will find out if you try this out, is quite painful- currently all the types used in the Graph are internal, which makes debugging quite difficult (you can’t quite look at any variables you hold in any meaningful way, you have to keep calling methods, as you’ll see next; hopefully this will change one of the next updates to the SDK.
In any case rootNode is now pointing at the root of a graph – a tree like structure you could ’walk’ to extract the pieces of information you care about in the source code; here you’re expected to use methods like GetLabel, GetSequenceElements and GetSuccessors to reach nodes and their values in the graph and, of course, to do that you need to know exactly how your graph looks like; my first instinct was to look at the PreviewMode pane in intellipad (usually the right most pane when working with MGrammar) as it shows you a representation of the MGraph created for the source code and language used; this worked quite well, but, as I found out, wasn’t the most trivial thing – the two didn’t align completely and I ended up having to resort to trail-and-error to get the parsing logic right.
The reason is that M has a few shortcuts one could take, but the graph you would be working on is the very basic, more verbose format; some information on this is mentioned here.
Then, on a recent visit to Redmond, Dana Kaufman passed on a great tip – if you ’compile’ your grammar using mg.exe to create the mgx file (basically a ZIP file containing XAML representation of language) and then use mgx.exe on your source file adding a reference to the mgx file you just created, you end up with an ’M’ file which is exactly the graph your runtime would be working on.end up with; so useful!
So – here are a few example of how I worked the graph – to start with I knew my root node should be a node with the label ’Application’, so I checked it this way –
string label = graph.GetLabel(rootNode).ToString(); if (label != "Application")
I then knew that the application name would be a child element of the root node, so I extracted it like this
// extract the application's data - this should contain two nodes - the application name and the list of items in the application List<object> appData = graph.GetSequenceElements(rootNode).ToList<object>(); //first line should be the application name, make sure it is not a node and extract the label if (!graph.IsNode(appData[0])) Contents.AppName = appData[0].ToString();
the second node in the appData collection is where the graph ’continues’, so to get the list of things that compose my application I needed to walk down that path –
//the second element should be the list of lines foreach (object section in graph.GetSuccessors(appData[i])) { //each successor would be a category (reference, importing binding, resource, etc), with a list of items processSection(graph,section); }
with processSection start with
string sectionName = graph.GetSequenceLabel(graph.GetSuccessors(section).First()).ToString(); List<object> items = graph.GetSuccessors(graph.GetSuccessors(section).First()).ToList<object>(); Log("Found section '{0}'", sectionName); switch (sectionName)
I hope that from these few examples you can see what it takes to work the graph – the graphBuilder (which is a somewhat confusing name, as I’m using it to walk the graph, not build it) has all the methods you need to access the various nodes ( but there’s no xpath-like- support), but as all the types are (currently) internal to the MS assembly you’re always working with objects, which is less then ideal.
Again – my full source code is on its way to codeplex, I just want to make sure it’s commented well enough to be well understood, and am struggling with time, but the bottom line is that once you figure out how the graph builder works, learnt how to see your graph visually (using mg.exe and mgx.exe) and got used to the fact that you’re dealing with objects for now, parsing the source code is very easy.
Obviously it is completely down to you what you then do with all the information you’ve extracted from the source code; in my case my runtime is using a plug-in model so the first part is all about using the Oslo SDK to get an instance of a BizTalkDeployment class populated based on the contents of the input file, this class looks like –
public class BizTalkDeployment { public string AppName { get; set; } public List<object> References { get; set; } public List<object> Build { get; set; } public List<BizTalkAssembly> BizTalkAssemblies { get; set; } public List<object> ImportBindings { get; set; } public List<Binding> AddBindings { get; set; } public List<Assembly> Resources { get; set; } }
I then use late binding and configuration to load a plug in that would take an instance of this class and do the work, be it generation of msbuild scripts, deploying to the local machine using BTSTask or anything else.
Extending Dublin’s tracking service by implementing a custom tracking participant
In a previous post we’ve explored how to extend Dublin’s forwarding service by implementing a custom message filter. This post continues the series by illustrating the extensibility model of Dublin’s tracking service. WCF message tracking and monitoring…(read more)
Demos from SDWest
Apparently I forgot to blog my demos from my WCF extensibility session at SDWest. You can find them here . Thanks again to all the people who attended my session….(read more)
Article on .NET Services in MSDN Magazine
My latest article on .NET Services is available in the April 2009 issue of MSDN Magazine. It’s called CLOUD COMPUTING: Building Distributed Applications with .NET Services. Enjoy.
DevWeek 2009 – it’s a wrap
We just wrapped up another great year at DevWeek 2009 in London. It’s one of my favorite shows to attend each year because of the central location, the attendees, the great conference organizers (thanks Nick!), and the chance to hang out with good friends in one of the best cities in the world. Numerous Pluralsight instructors speak here each year – it’s something of a yearly retreat for us). You can check out some of the #devweek action on Twitter.
I did the keynote this year on cloud computing, and then I gave several breakout sessions on WCF, REST, ADO.NET Data Services, .NET 4.0, and Dublin. Here’s the code from my demos.
And here’s the new Pluralsight On-Demand! shirt that we gave away this week:
Time to head home now, and time to get back to recording the next few Pluralsight On-Demand! titles I’m working on. Next up – the Azure Services Platform.
The File Receive Adapter doesn’t Process Empty Files
A quick observation for today – interesting to see that the FILE adapter won’t attempt to process empty files (my emphasis):
The FILE receive adapter deleted the empty file “C:\CBTMessage_2009-03-26_03-12-50_7c54477f-516c-48c1-9f8b-5450eeff1dd0.xml” without performing any processing.
Event IDs 7076, 6482, 6398 in Appplication Log
Symptom
Event Type: Error
Event Source: Windows SharePoint Services 3
Event Category: (964)
Event ID: 6398
Date: <DATE>
Time: <TIME>
PM User: N/A
Computer: <SERVERNAME>
Description:
The Execute method of job definition Microsoft.Office.Server.Administration.ApplicationServerAdministrationServiceJob
(ID GUID) threw an exception. More information is included below.
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
You may also get just a blank page when you try to manage IIS
Solution/Recommendation
Check for the hotfix at http://support.microsoft.com/?id=946517
Commentary
SP1 seems to help a bit, but the hotfix closes the loop
Recoverable interchange processing enhancements in BizTalk 2009
The text below is based on the beta release of BizTalk 2009. It might not (completely) apply to the RTM release.
BizTalk Server 2009 brings developers a lot of new functionality. In presentations and blog posts most of those new functions have already been described and shown.
One of the new things that is not or only […]
Visualizing SOA’s Return on Investment
[Source: http://geekswithblogs.net/EltonStoneman]
This is the rather grand title of a WebCast I’ve recorded recently which tries to illustrate where the return on investment comes after moving to a SOA strategy. The video is on Digital Forum: Visualizing SOA ROI , and the Open Source proof of concept it references is on CodePlex: ESBSimpleSamples.
In the WebCast I start with a blank Visual Studio solution and create a new Web app which consumes an existing service. All in it takes 3 lines of code and around 3 minutes of development (most of it spent correcting typos), and it doesn’t require me to have any understanding of the underlying SOA infrastructure – in this case, Microsoft’s ESB Guidance package sitting on BizTalk Server 2006 R2. Equally important, assuming the service we consume is in production, the testing and deployment effort needed for the new project is minimal.
This is a rework of a presentation I did with a client where I wanted to show how quick and easy it is to use their SOA implementation. I had reservations of showing a code demonstration to an audience which included IT heads (IT Director and Solution Architects) and project management, but it was surprisingly well received, so I’ve reproduced it using services and components which are publicly available.
Direct links to the references in the WebCast are here:
- ESB Guidance: http://www.codeplex.com/esb
- UK SOA/BPM User Group presentation: http://sbug.org.uk/media/p/129.aspx
- Blog posts on ESB Guidance: http://geekswithblogs.net/EltonStoneman/category/7947.aspx
