Author: Richard Seroter

  • RSS, RSS Readers and Finding Information

    Last week my long-suffering blog reader, Bloglines, pulled the plug.  I’ve since moved over to Google Reader and like it more than the last time I tried it.  Coinciding with Bloglines’ death, a few blog posts cropped up talking about the state of RSS (readers) and the evolved information gathering habits of the consumer.  I can’t say I totally get this new perspective that information should come to me, and active subscriptions are a thing of the past.

    I read Don Dodge’s post last week where he first repeated Robert Scoble’s statement that “if the information is important, it will find me” and then goes on to say that he doesn’t really use RSS readers anymore and relies on real-time channels and content aggregators.  I don’t see how I’d be satisfied consuming my information only through the recommendations of others.  Unless I was (a) on Twitter 25 hours a day or (b) expected every thoughtful technical article would get snapped up by an aggregator, I don’t see how I could replace my own RSS reader.  In an RSS reader, I subscribe to the people who write things that interest me.  Why would I want to rely on others telling me that so-and-so just wrote something profound?

    Today Dave Winer wrote an overall good piece on rebooting RSS where he mentions:

    I keep saying the same thing over and over, the Google Reader approach is wrong, it isn’t giving you what’s new — and that’s all that matters in news.

    Again, I just don’t see it.  Assuming that my RSS reader doesn’t ONLY subscribes to traditional news sources,  I do want “unread counts” and the backlog of things to peruse.  Sure, I don’t want or need a 12-day backlog of sports news from ESPN when I return from vacation, but when I have an RSS subscription to some of my favorite bloggers (e.g. Lori MacVittie of F5), I expect to queue up the interesting articles that aren’t time sensitive “news”, but rather smart opinion pieces.  I don’t use an RSS reader for traditional “news” as much as I use it to actively listen in on the long-form thoughts of insightful people.  I might be strange in that my RSS readers isn’t for news as much as following individual bloggers where this increasing obsession with information speed is less relevant.

    So, maybe I’m clinging to old information consumption models, but I like RSS readers and not relying on browser bookmarks or the whims of my Twitter “friends” to identify smart content.  I notice that my blog gets a high level of traffic from syndicated readers (not site visits), so many of you all seem to be using RSS readers as well.

    What say you?  Is traditional RSS consumption dead?  Do you instead use a mix of bookmarks, aggregators and social-sharing to find new information?

    [Update: Great post from GigaOm that came in after mine and makes the same points, and a few new ones.  Recommended reading.]

  • And … The New Book is Released

    Nearly 16 months after a book idea was born, the journey is now complete.  Today, you can find our book, Applied Architecture Patterns on the Microsoft Platform, in stock at Amazon.com and for purchase and download at the Packt Publishing site.

    I am currently in Stockholm along with co-authors Stephen Thomas and Ewan Fairweather delivering a 2 day workshop for the BizTalk User Group Sweden.  We’re providing overviews of the core Microsoft application platform technologies and then excerpting the book to show how we analyzed a particular use case, chose a technology and then implemented it.  It’s our first chance to see if this book was a crazy idea, or actually useful.  So far, the reaction has been positive.  Of course, the Swedes are such a nice bunch that they may just be humoring me.

    I have absolutely no idea how this book will be received by you all.  I hope you find it to be a unique tool for evaluating architecture and building solutions on Microsoft technology.  If you DON’T like it, then I’ll blame this book idea on Ewan.

  • Interview Series: Four Questions With … Mark Simms

    Happy September and welcome to the 23rd interview with a thought leader in the “connected technology” space.  This month I grabbed Mark Simms who is member of Microsoft’s AppFabric Customer Advisory team, blogger, author and willing recipient of my random emails.

    Mark is an expert on Microsoft StreamInsight and has a lot of practical customer experience with the product.  Let’s see what he has to say.

    Q: While event-driven architecture (EDA) and complex event processing (CEP) are hardly new concepts, there does seem to be momentum in these areas.  While typically a model for financial services, EDA and CEP have gained a following in other arenas as well.  To what might you attribute this increased attention in event processing and which other industries do you see taking advantage of this paradigm?

    A: I tend to think about technology in terms of tipping points, driven by need.  The financial sector, driven by the flood of market data, risks and trades was the first to hit the challenge of needing timely analytics (and by need, we mean worth the money to get), spawning the development of a number of complex event processing engines.  As with all specialized engines, they do an amazing job within their design sphere, but run into limitations when you try to take them outside of their comfort zone.  At the same time, technology drivers such as (truly) distributed computing, scale-out architectures and “managed by somebody” elastic computing fabrics (ok, ok, I’ll call it the “Cloud”) have led to an environment wherein the volume of data being created is staggering – but the volume of information that can be processed (and stored, etc) hasn’t.

    Whereas I spend most of my time lately working on two sectors (process control – oil & gas, smart grids, utilities and web analytics), the incoming freight train of cloud computing is going to land the challenge of dealing with correlating nuggets of information spread across both space and time into some semblance of coherence.  In essence, finding the proverbial needle in the stack of needles tumbling down an escalator is coming soon to a project near you.

    Q: It’s one thing to bake the publication and consumption of events directly into a new system.  But what are some strategies and patterns for event-enabling existing packaged or custom applications?

    A: This depends both on the type of events that are of interest, and the overall architecture of the system.  Message based architectures leveraging a rich subscription infrastructure are an ideal candidate for ease of event-enabling.  CEP engines can attach to key endpoints and observe messages and metadata, inferring events, patterns, etc.  For more monolithic systems there are still a range of options.  Since very little of interest happens on a single machine (other than StarCraft 2’s single player campaign), there’s almost always a network interface that can be tapped into.  As an example on our platform, one might leverage WCF interceptors to extract events from the metadata of a given service call and transfer the event to a centralized StreamInsight instance for processing.  Another approach that can be leveraged with most applications on the Microsoft platform is to extract messages from ETW logs and infer events for processing – between StreamInsight’s ability to handle real-time and historical data, this opens up some very compelling approaches to optimization, performance tuning, etc, for Windows applications.

    Ultimately, it comes down to finding some observable feed of data from the existing system and converting that feed into some usual stream of events.  If the data simply doesn’t exist in an accessible form, alas, StreamInsight does not ship with magic event pixie dust.

    Q: Microsoft StreamInsight leverages a few foundational Microsoft technologies like .NET and LINQ.  What are other parts of the Microsoft stack (applications or platforms) that you see complimenting StreamInsight, and how?

    A: StreamInsight is about taking in a stream of data, and extracting relevant information from that data by way of pattern matching, temporal windows, exception detection and the like.  This implies two things – data comes from somewhere, and information goes somewhere else.  This opens up a world wherein pretty much every technology under the fluorescent lamps is a candidate for complimenting StreamInsight.  Rather than get into a meandering and potentially dreadfully boring bulleted list of doom, here’s some of (but not the only :)) top of mind technologies I think about:

    • SQL Server.  I’ve been a SQL Server guy for the better part of a decade now (after a somewhat interminable sojourn in the land of Oracle and mysql), and for pretty much every project I’m involved with that’s where some portion of the data lives.  Either as the repository for reference data, destination for filtered and aggregate results, or the warehouse of historical data to mine for temporal patterns (think ETL into StreamInsight) the rest of SQL Server suite of technology is never far away.  In a somewhat ironic sense, as I write up my answers, I’m working on a SQL output adapter in the background leveraging SQL Service Broker for handling rate conversion and bursty data.
    • App Fabric Cache. Filling a similar complementary role in terms of a data repository as SQL Server (in a less transactional & durable sense), I look to AppFabric Cache to provide a distributed store for reference data, and a “holding pond” of sorts to handle architectural patterns such as holding on to 30 minutes worth of aggregated results to “feed” newly connecting clients.
    • SharePoint and Silverlight.  Ultimately, every bit of the technology is at some point trying to improve the lot of its users – the fingers and eyeballs factor.  Great alignment SharePoint, combined with Silverlight for delivering rich client experiences (a necessity for visualizing fast-moving data – the vast majority of all visualization tools and frameworks assume that the data is relatively stationary) will be a crucial element in putting a face on the value that StreamInsight delivers.

    Q [stupid question]: They say you can’t teach old dogs new tricks.  I think that in some cases that’s a good thing.  I recently saw a television commercial for shaving cream and noticed that the face-actor shaved slightly differently than I do.  I wondered if I’ve been doing it wrong for 20 years and tried out the new way.  After stopping the bleeding and regaining consciousness, I decided there was absolutely no reason to change my shaving strategy.  Give us an example or two of things that you’re too old or too indifferent to change.

    A: One of the interesting things about being stuck in a rut is that it’s often a very comfortable rut.  If I wasn’t on the road, I’d ask my wife who would no doubt have a (completely accurate) laundry list of these sorts of habits. 

    One of the best aspects of my job on the AFCAT team is our relentless inquisitive drive to charge out into unknown technical territory.  I’m never happier than when I’m learning something new, whether it be figuring out how to apply a new technology or trying to master a new recipe or style of cuisine.  Coupled with a recent international relocation that broke a few of my more self-obvious long standing habits (Tom Horton’s coffee, ketchup chips, a 10-year D&D campaign), this is probably the hardest question to answer.

    With the aforementioned lack of a neutral opinion to fall back on, I’m going to have to pull a +1 on your shaving example – I’ve been using the same shaving cream for almost two decades now, and the last time I tried switching up, I reconfirmed that I am indeed rather violently allergic to every single other shaving balm on the planet 😉

    Thanks Mark.  Keep an eye on his blog and the AppFabric CAT team blog for more in-depth details on the Microsoft platform technologies.

    Share

  • Do you know the Microsoft Customer Advisory Teams? You should.

    For those who live and work with Microsoft application platform technologies, the Microsoft Customer Advisory Teams (CAT) are a great source of real-world info about products and technology.  These are the small, expert-level teams whose sole job is to make sure customers are successful with Microsoft technology.  Last month I had the pleasure of presenting to both the SQL CAT and Server AppFabric CAT teams about blogging and best practices and thought I’d throw a quick plug out for these groups here.

    First off, the SQL CAT team (dedicated website here) has a regular blog of best practices, and link to the best whitepapers for SQL admins, architects, and developers.  I’m not remotely a great SQL Server guy, but I love following this team’s work and picking up tidbits that make me slightly more dangerous at work.  If you actually need to engage these guys on a project, contact your Microsoft rep.

    As for the Windows Server AppFabric CAT team, they also have a team blog with great expert content.  This team, which contains the artists-formerly-known-as-BizTalk-Rangers, provides deep expertise on BizTalk Server, Windows Server AppFabric, WCF, WF, AppFabric Caching and StreamInsight.  You’ll find a great bunch of architects on this team including Tim Wieman, Mark Simms, Rama Ramani, Paolo Salvatori and more, all led by Suren Machiraju and the delightfully frantic Curt Peterson. They’ve recently produced posts about using BizTalk with the AppFabric Service Bus, material on the Entity Framework,  and a ridiculously big and meaty post from Mark Simms about building StreamInsight apps.

    I highly recommend subscribing to both these team blogs and following SQL CAT on twitter (@sqlcat).

    Share

  • How Intelligent is BizTalk 2010’s Intelligent Mapper?

    One of the interesting new features of the BizTalk Server 2010 Mapper (and corresponding Windows Workflow shape) is the “suggestive matching” which helps the XSLT map author figure out which source (or destination) nodes are most likely related.  The MSDN page for suggestive matching has some background material on the feature.  I thought I’d run a couple quick tests to see just how smart this new mapper is.

    Before the suggestive match feature was introduced, we could do bulk mapping through the “link by” feature.  With that feature, you could connect two parent nodes and choose to map the children nodes based on the structure (order), exact names or through the mass copy function.  However, this is a fairly coarse way to map that doesn’t take into account the real semantic differences in a map.  It also doesn’t help you find any better destination candidates that may be in a different section of the schema.

    2010.08.15mapper01

    Through Suggestive Matching, I should have an easier time finding matching nodes with similar, but non-exact naming.  However, per the point of this post, I wasn’t sure if the Mapper just did a simple comparison or anything further.

    Simple Name Matching

    In this scenario, we are simply checking to see if the Mapper looks for the same textual value from the source in the destination.  In my source schema I have a field called “ID.”  In my destination schema I have a field called “ItemID.”  As you’d expect, the suggestive match points this relationship out.

    2010.08.15mapper02

    In that case, the name of the source node is a substring of the destination.  What if the destination node is a substring of the source?  To demonstrate that, I have a source field named “PhoneNumber” and the destination node is named “Phone.”  Sure enough, a match is still made.

    2010.08.15mapper03

    Also, it doesn’t matter where in the node name that a matching value is found.  If I have a “Code” field in the source tree and both a “ZipCode” and “OrderCodeIdentifier” in the destination, both nodes are considered possible matches.  The word “code” in the latter field, although between other text, is still identified as a match.  Not revolutionary of course, but nice.

    2010.08.15mapper04

    Complex Name Matching

    In this scenario, I was looking to see if the Mapper detected any differences based on more than just the substrings.  That is, could it figure out that “FirstName” and “FName” are the same?  Unfortunately, the “FirstName” field below resulted in a match to all name fields in the destination.

    2010.08.15mapper05

    The highlighted link is considered the best match, and I noticed that as I added more characters to the “FName” node, I got a different “best match.”

    2010.08.15mapper06

    You see that “FirName” is considered a close match to “FirstName.”  Has anyone else found any cases where similar but inexact worded is still marked as a match?

    Node Positioning

    I was hoping that via intelligent mapping that an address with a similar structure could be matched across.  That is, if in one map I had certain identically named nodes before an after one, that it might guess that the middle ones matched.  For instance, what if I have “City” between “Street” and “State” in the source and “Town” between “Street” and “State” in the destination, that maybe it would detect a pattern.  But alas, that is apparently a dream.

    2010.08.15mapper07

    Summary

    It looks like our new intelligent mapper, with the help of Suggestive Match, does a decent job of textual matching between a source and destination schema.  I have yet to see any examples of advanced conditions outside of that.  Still, if all we get is textual matching, that still provides developers a bit of help when traversing monstrous schemas with multiple destination candidates for a source node.

    If you have any additional experiences with this, I’d love to hear it.

    Share

  • My Book is Available for Pre-order on Amazon.com

    Just a quick FYI that my new book, Applied Architecture Patterns on the Microsoft Platform, can now be pre-ordered on Amazon.com.  I’m reviewing final prints now, so hopefully we’ll have this out the door and in your hands shortly.

  • Cloud Provider Request: Notification of Exceeded Cost Threshold

    I wonder if one of the things that keeps some developers from constantly playing with shiny cloud technologies is a nagging concern that they’ll accidentally ring up a life-altering usage bill.  We’ve probably all heard horror stories of someone who accidentally left an Azure web application running for a long time or kept an Amazon AWS EC2 image online for a month and were shocked by the eventual charges.  What do I want? I want a way to define a cost threshold for my cloud usage and have the provider email me as soon as I reach that value.

    Ideally, I’d love a way to set up a complex condition based on various sub-services or types of charges.  For instance, If bandwidth exceeds X, or Azure AppFabric exceeds Y, then send me an SMS message.  But I’m easy, I’d be thrilled if Microsoft emailed me the minute I spent more than $20 on anything related to Azure.  Can this be that hard?  I would think that cloud providers are constantly accruing my usage (bandwidth, compute cycles, storage) and could use an event driven architecture to send off events for computation at regular intervals. 

    If I’m being greedy, I want this for ANY variable-usage bill in my life.  If you got an email during the summer from your electric company that said “Hey Frosty, you might want to turn off the air conditioner since it’s ten days into the billing cycle and you’ve already rung up a bill equal to last month’s total”, wouldn’t you alter your behavior? Why are most providers stuck in a classic BI model (find out things whenever reports are run) vs. a more event-driven model? Surprise bills should be a thing of the past.

    Are you familiar with any providers who let you set charge limits or proactively send notifications?  Let’s make this happen, please.

    Share

  • Using “Houston” to Manage SQL Azure Databases

    Up until now, your only option for managing SQL Azure cloud databases was using an on-premise SQL Server Management Console and pointing to your cloud database.  The SQL Azure team has released a CTP of “Houston” which is a web-based, Silverlight environment for doing all sorts of stuff with your SQL Azure database.  Instead of just telling you about it, I figured I’d show it.

    First, you need to create a SQL Azure database (assuming that you don’t already have one).  Mine is named SeroterSample.  I’m feeling very inspired this evening.

    2010.07.22SqlAzure01

    Next up, we make sure to have a firewall rule allowing Microsoft services to access the database.

    2010.07.22SqlAzure02

    After this, we want to grab our database connection details via the button at the bottom of the Databases view.

    2010.07.22SqlAzure03

    Now go to the SQL Azure labs site and select the Project Houston CTP 1 tab.

    2010.07.22SqlAzure04

    We then see a futuristic console which either logs me into project Houston or launches a missile.

    2010.07.22SqlAzure05

    If the login is successful, we get the management dashboard.  It contains basic management operations at the top (“new table”, “new stored procedure”, “open query”, etc), a summary of database schema objects on the left, and an unnecessary but interesting “cube of info” in the middle.

    2010.07.22SqlAzure06

    The section in the middle (aka “cube of info”) rotates as you click the arrows and shows various data points.  Hopefully a future feature includes a jack-in-the-box that pops out of the top.

    I chose to create a new table in my database.  We are shown an interface where we build up our table structure by choosing columns, data types, default values, data types and more.

    2010.07.22SqlAzure07

    After creating a few columns and renaming my table, I clicked the Save button on the top left of the screen to commit my changes.  I can now see my table in the list of artifacts belonging to my database.

    2010.07.22SqlAzure08

    It’s great to have a table, but let’s put some data into that bad boy.  Clicking the table name re-opens the design view by default.  We can select the Data view at the top to actually add rows to our table.

    2010.07.22SqlAzure10

    I’m not exactly sure how to delete artifacts except through manual queries.  For kicks and giggles I clicked the New View option, and when I canceled out of it, I still ended up with a view in the artifact list.  Right-clicking is not something that is available anywhere in the application, and there was no visible way to delete the view short of create a new Query and deleting it from there.  That said, when I logged out and logged back in, the view was no longer there.  So, because I didn’t explicitly save it, the view was removed when I disconnected.

    All in all, this is a fine, light-weight management interface for our cloud database.  It wasn’t until I was halfway through my demonstration that I realized that I did all my interactions on the portal through a Chrome browser.  Cross-browser stuff is much more standard now, but, still nice to see.

    Because I have no confidence that my Azure account is accurately tied to my MSDN Subscription, I predict that this demonstration has cost me roughly $14,000 in Azure data fees.  You all are worth it though.

    Share

  • Sending StreamInsight Events to BizTalk Through New Web (SOAP/REST) Adapter

    One StreamInsight usage scenario frequently discussed by the product team involves sending a subset of events (or aggregated complex events) to the Enterprise Service Bus for additional processing and distribution.  As I’ve mentioned before, StreamInsight doesn’t come with any out-of-the-box adapters.  So if you want to make this usage scenario a reality, it’s up to you to figure out how to do it.  In this post, I hope to give you a head start (and code) to making this happen.  I’ve built a StreamInsight web adapter which lets StreamInsight send either SOAP or REST-style messages to an endpoint. We can use this adapter to send messages to BizTalk, or any web endpoint.  Buckle up, this is a long one.

    Designing the Adapter

    In the StreamInsight SDK  you’ll find some solid examples of StreamInsight adapters that you can use as a template to build your own.  I’ve built a few so far myself and demonstrate how to build an MSMQ publication adapter in my new book.  But I hadn’t built a consumer adapter yet, so I had to think about the right design strategy.

    The first design choice was whether to build a typed or untyped adapter.  While typed adapters are easier to craft since you are building to a known data payload, you don’t get any reuse out of the adapter.  So, the first (easy) decision was to build an untyped adapter that could send any payload to a web endpoint.

    The second consideration was how to call the downstream web endpoint.  I decided to use the System.Net.HttpWebRequest object to publish the payload and not try to do an IOC pattern with proxy classes.  By using this mechanism, I can apply the same code to call a SOAP endpoint or invoke various HTTP verbs on a RESTful endpoint.

    Finally, I had to decide how to actually convert the StreamInsight events to the expected XML payload of my web endpoints.  I figured that leveraging XSLT was a solid plan.  I can take the inbound event, and via a runtime configuration property, apply an XML transformation stylesheet to the event and produce output that my web endpoint requires.

    Ok, with all of these considerations in place, let’s build the adapter.  Note that you are completely allowed to disagree with any of the choices above and modify my adapter to fit your needs.

    Building the Adapter

    First off, I built the adapter’s configuration object.  These are the settings that we apply at runtime when we bind a StreamInsight query to an adapter.  Consider this to be reference data that we don’t want to hardcode into our adapter.

    public struct WebOutputConfig
        {
            public string XslPath { get; set; }
            public string ServiceAddress { get; set; }
            public string HttpMethod { get; set; }
            public string SoapAction { get; set; }
            public bool IsSoap { get; set; }
        }
    

    Note that my configuration accepts the path to an XSLT file, the URL of the target service, the HTTP method to apply, and if we are calling a SOAP endpoint, what the SOAP Action value is.

    Next I create my actual adapter class.  It inherits from the untyped PointOutputAdapter class.

    public class WebPointOutput: PointOutputAdapter
        {
            //store reference to CEP event
            private CepEventType bindTimeEventType;
            private string serviceAddress;
            private string httpMethod;
            private string soapAction;
            private bool isSoap;
            private XslCompiledTransform consumerXform;
    
            public WebPointOutput(WebOutputConfig configInfo, CepEventType eventType)
            {
                this.bindTimeEventType = eventType;
                this.serviceAddress = configInfo.ServiceAddress;
                this.httpMethod = configInfo.HttpMethod;
                this.soapAction = configInfo.SoapAction;
                this.isSoap = configInfo.IsSoap;
    
                //load up transform
                consumerXform = new XslCompiledTransform(false);
                consumerXform.Load(configInfo.XslPath);
            }
      }
    

    The adapter stores internal references to the configuration values it received and the constructor instantiates the XSL transformation object using the XSL path passed into the adapter.

    Before writing the primary operation which calls the service, we need a helper function which takes the key/value pairs from the CEP event and creates a dictionary out of them.  We will later convert this dictionary into a generic XML structure that we’ll apply our XSLT against.

    private Dictionary<string, string> GetCepEventFields(PointEvent currentEvent)
            {
                Dictionary<string, string> cepFields = new Dictionary<string, string>();
    
                for (int ordinal = 0; ordinal < bindTimeEventType.FieldsByOrdinal.Count; ordinal++)
                {
                    CepEventTypeField evtField = bindTimeEventType.FieldsByOrdinal[ordinal];
                    cepFields.Add(evtField.Name, currentEvent.GetField(ordinal).ToString());
                }
                return cepFields;
            }
    

    See above that I loop through all the fields in the event and add each one (name and value) to a dictionary object.

    Now we can build our primary function which takes the StreamInsight event and calls the web endpoint.  After the code snippet, I’ll comment on a few key points.

    private void ConsumeEvents()
      {
          //create new point event
          PointEvent currentEvent = default(PointEvent);
          try
          {
              while (true)
              {
                  if (AdapterState.Stopping == AdapterState)
                  {
                     Stopped();
                     return;
                  }
    
                  if (DequeueOperationResult.Empty == Dequeue(out currentEvent))
                 {
                     Ready();
                     return;
                  }
    
                 //only publish insert events and ignore CTIs
                 if (currentEvent.EventKind == EventKind.Insert)
                 {
                    // ** begin service call
                    //convert CEP message to XML for transformation
                    XDocument intermediaryDoc = new XDocument(
                    new XElement("Root",
                    GetCepEventFields(currentEvent).Select(field => new XElement("Property",
                        new XElement("Name", field.Key),
                        new XElement("Value", field.Value)
                        ))));
    
                    //transform CEP event fields to output format
                    XDocument returnDoc = new XDocument();
                    using (XmlWriter writer = returnDoc.CreateWriter())
                    {
                      consumerXform.Transform(intermediaryDoc.CreateReader(), (XsltArgumentList)null, writer);
                    }
    
                    //call service
                    HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(serviceAddress);
                    req.Method = httpMethod;
                    req.ContentType = "text/xml";
                    if (isSoap)
                        req.Headers.Add("SOAPAction", soapAction);
    
                    using (Stream reqStream = req.GetRequestStream())
                    {
                        var bytes = Encoding.UTF8.GetBytes(returnDoc.ToString());
                        reqStream.Write(bytes, 0, bytes.Length);
                        reqStream.Close();
                    }
    
                    var resp = (HttpWebResponse)req.GetResponse();
                   }
    
                 // Every received event needs to be released.
                 ReleaseEvent(ref currentEvent);
             }
          }
          catch (AdapterException e)
          {
             System.IO.File.WriteAllText(
                @"C:\temp\" + System.Guid.NewGuid().ToString() + "_eventerror.txt", "Error: " + e.ToString());
           }
       }
    

    First, notice that I do NOT emit CTI events.  Next see that I use a bit of LINQ to take the results of the event-to-dictionary conversion and create an XML document (XDocument) consisting of name/value pairs.  I then take this “intermediary XML” and pass it through an XslCompiledTransform using whichever XSLT was provided during adapter configuration.  The resulting XML is then streamed to the web endpoint via the HttpWebRequest object.  There are probably performance improvements that can be done here, but hey, it’s a proof-of-concept!

    The final piece of this adapter is to fill in the required “start” and “resume” operations.

    public override void Resume()
            {
                new Thread(this.ConsumeEvents).Start();
            }
    
            public override void Start()
            {
                new Thread(this.ConsumeEvents).Start();
            }
    
            protected override void Dispose(bool disposing)
            {
                base.Dispose(disposing);
            }
    

    Finally, I have to create an adapter factory which spins up my adapter when the StreamInsight query gets started up.  Since we are using an untyped adapter, there isn’t any logic needed to pick the “right” output adapter.

    public class WebOutputFactory : IOutputAdapterFactory<WebOutputConfig>
     {
         public OutputAdapterBase Create(WebOutputConfig configInfo, EventShape eventShape, CepEventType cepEventType)
         {
             OutputAdapterBase adapter = default(OutputAdapterBase);
             adapter = new WebPointOutput(configInfo, cepEventType);
    
             return adapter;
         }
     }
    

    With that, we have a complete StreamInsight consumer adapter.

    Using the Adapter

    How can we use this fancy, new adapter?  In one scenario, we can use StreamInsight to process a high volume of events, filter out the “noise”, and amplify events of specific interest.  Or, we can empower StreamInsight to look for trends within the stream over a particular time duration and share these complex events whenever one is encountered.

    2010.07.08StreaminsightBts03

    For this post, I’ll show the latter example.  I have a StreamInsight application which generates call center events every half second and sends them to an embedded StreamInsight server.   I do some aggregation over a window of time and if a complex event is detected, the web adapter is called and BizTalk receives the message for further processing.  Note that nothing prevents me from substituting WCF Services or Azure-based services for BizTalk in this case.  Well, except for security which I have NOT added to my adapter.  Didn’t figure out a clean way to store and send credentials yet.

    BizTalk Setup

    Let’s set up the BizTalk application that StreamInsight will publish to.  First I created a simple schema that represents the event data I want BizTalk to receive.

    2010.07.08StreaminsightBts02

    In real life I’d add an orchestration or two to process the event data, but this post is already ginormous and you all get the point.  So, let’s jump right to exposing this schema as part of a BizTalk service contract.  I walked through the BizTalk WCF Publishing Wizard and produced a one-way service that takes in my CallThresholdEvent message.

    2010.07.08StreaminsightBts01

    Once the service is created, I built the requisite receive port/location and a send port which subscribes on the CallThresholdEvent message.

    All we need now is the right XSLT to transform the CEP event message to the WCF service contract message format.  How do we get that? The easiest way to get the correct XML is to invoke the service in the WCF Test Client and steal the SOAP payload it builds to call the service.  I pointed the WCF Test Client to my endpoint and invoked the service.

    2010.07.08StreaminsightBts04

    Once I confirmed that the service worked (and emitted a file from the send port), I switched the view from “formatted” to “xml” and could view the XML that was sent across the wire.

    2010.07.08StreaminsightBts05

    I took the “request” XML and created a new XSLT file with this request structure created in the root template.

    <xsl:template match="*">
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
          <s:Header>
            <!--<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">PublishThresholdEvent</Action>-->
          </s:Header>
          <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <CallThresholdEvent xmlns="http://BizTalkEventProcessor">
              <ProductName xmlns="">
                <xsl:value-of select="Property[Name = 'EvtProd']/Value"/>
              </ProductName>
              <CallCategory xmlns="">
                <xsl:value-of select="Property[Name = 'EvtType']/Value"/>
              </CallCategory>
              <OccuranceCount xmlns="">
                <xsl:value-of select="Property[Name = 'EvtCount']/Value"/>
              </OccuranceCount>
              <TimeReceived xmlns=""></TimeReceived>
            </CallThresholdEvent>
          </s:Body>
        </s:Envelope>
      </xsl:template>
    

    Note that you should NOT send the Action header as WCF takes care of that and the service endpoint barfs with an HTTP 500 if you send it.  It also takes roughly 96 hours to figure out that this is the problem.  Consider yourself warned.

    At this point, I have all I need in BizTalk to call the service successfully.

    StreamInsight Setup

    The first query in my StreamInsight application performs an aggregation of events over a “tumbling” window.

    var inputStream = CepStream<CallCenterRequestEventType>.Create("input", typeof(CallCenterAdapterFactory), config, EventShape.Point);
    
     var callTypeCount =
              from w in inputStream
              group w by new { w.RequestType, w.Product } into appGroup
              from x in appGroup.TumblingWindow(
                      TimeSpan.FromSeconds(15),
                      HoppingWindowOutputPolicy.ClipToWindowEnd)
               select new EventTypeSummary
               {
                   EvtType = appGroup.Key.RequestType,
                   EvtProd = appGroup.Key.Product,
                   EvtCount = x.Count()
                };
    

    In the query above, I take the call center event input stream and put the incoming events into groups based on the event type (e.g. “Info Request”, “Product Complaint”, “Account Change”) and product the customer is calling about.  I base these groups on a tumbling window that lasts 15 seconds.  This means that the window is flushed every 15 seconds and started fresh.  I then take the output of the window grouping and put it into a new, known type named EventTypeSummary.  If I use an anonymous type here instead, I get a “System.IndexOutOfRangeException: Index was outside the bounds of the array” error.

    I next take the result of the first query and make it the input into a second query.  This one looks at any groups emitted by the first query and filters them based on a criteria my ESB is interested in.

    var callTypeThreshold =
                from summary in callTypeCount
                where summary.EvtCount > 3 && summary.EvtType == "Product Complaint"
                select summary;
    

    Above, I am looking for any “summary events” where the call type is a product complaint and there have been more than 3 of them for a specific product (during a given window).

    Before I register my query, I need to define the StreamInsight adapter configuration for my web endpoint.  Recall above that we defined a structure to hold parameters that we will pass into the adapter at runtime.

    var webAdapterBizTalkConfig = new WebOutputConfig()
     {
        HttpMethod = "POST",
        IsSoap = true,
        ServiceAddress = "http://localhost/BizTalkEventProcessingService/BizTalkEventProcessingService.svc",
        SoapAction = "PublishThresholdEvent",
        XslPath = @"[path]\CallCenterEvent_To_BizTalkSoapService.xslt"
      };
    

    Above, you’ll see the service address pointing to my BizTalk-generated WCF endpoint, the SOAP action for my service, and a pointer to the XSLT that I created to transform the CEP event to a SOAP payload.

    Finally, I registered the query and start it.

    var allQuery = callTypeThreshold.ToQuery(
                             myApp,
                             "Threshold Events",
                             string.Empty,
                             typeof(WebOutputFactory),
                             webAdapterBizTalkConfig,
                             EventShape.Point,
                             StreamEventOrder.FullyOrdered);
    

    You can see that I pass in my web adapter factory type and the adapter configuration properties defined earlier.

    The Result

    When all this is in place, I start up my StreamInsight application, begin generating events, and can observe BizTalk messages getting written to disk.

    2010.07.08StreaminsightBts06

    In this post we saw how I can link StreamInsight with BizTalk Server through a WCF channel.  You can grab the source code for the StreamInsight Web Adapter here. I’ve done some basic testing of the adapter against both RESTful and SOAP services, but there are great odds that you’ll find something I missed.  However, it hopefully gives you a great head start when building a StreamInsight solution that emits events to web endpoints.

    Share

  • Updated Ways to Store Data in BizTalk SSO Store

    One of my more popular tools has been the BizTalk SSO Configuration Data Storage Tool.  At the time I built that, there was no easy way to store and manage Single Sign On (SSO) applications that were used purely for secure key/value pair persistence.

    Since that time, a few folks (that I know of) have taken my tool and made it better.  You’ll find improvements from Paul Petrov here (with update mentioned here), and most recently by Mark Burch at BizTorque.net.  Mark mentioned in his post that Microsoft had stealthily released a tool that also served the purpose of managing SSO key/values, so I thought I’d give the Microsoft tool a quick whirl.

    First off, I downloaded my own SSO tool, which I admittedly haven’t had a need to use for quite some time.  I was thrilled that it worked fine on my new BizTalk 2010 machine.

    2010.07.05sso01

    I created (see above) a new SSO application named SeroterToolApp which holds two values.  I then installed the fancy new Microsoft tool which shows up in the Start Menu under SSO Application Configuration.

    2010.07.05sso02

    When you open the tool, you’ll find a very simple MMC view that has Private SSO Application Configuration as the root in the tree.  Somewhat surprisingly, this tool does NOT show the SSO application I just created above in my own tool.  Microsoft elitists, think my application isn’t good enough for them.

    2010.07.05sso03

    So let’s create an application here and see if my tool sees it.  I right-click that root node in the tree and choose to add an application.  You see that I also get an option to import an application and choosing this prompts me for a “*.sso” file saved on disk.

    2010.07.05sso04

    After adding a new application, I right-clicked the application and chose to rename it.

    2010.07.05sso05

    After renaming it MicrosoftToolApp, I once again right-clicked the application and added a key value pair.  It’s nice that I can create the key and set its value at the same time.

    2010.07.05sso06

    I added one more key/value pair to the application.  Then, when you click the application name in the MMC console, you see all the key/value pairs contained in the application.

    2010.07.05sso07

    Now we saw earlier that the application created within my tool does NOT show up in this Microsoft tool, but what about the other way around?  If I try and retrieve the application created in the Microsoft tool, sure enough, it appears.

    2010.07.05sso08

    For bonus points, I tried to change the value of one of the keys from my tool, and that change is indeed reflected in the Microsoft tool.

    2010.07.05sso09

    2010.07.05sso10

    So this clearly shows that I am a much better developer than anyone at Microsoft.  Or more likely, it shows that somehow the applications that my tool creates are simply invisible to Microsoft products.  If anyone gets curious and wants to dig around, I’d be somewhat interested in knowing why this is the case.

    It’s probably a safe bet moving forward to use the Microsoft tool to securely store key/value pairs in Enterprise Single Sign On.  That said, if using my tool continues to bring joy into your life, than by all means, keep using it!

    Share