ESB Guidance…part 3

Itinerary Processing

So what does ESB Guidance offer beyond the management and monitoring aspect?

The notion of itinerary processing was all new to me, and as I said in previous posts, I didn't really understand the concept at first. However, now that I do, I think of this as, by far, the coolest thing about the ESB Guidance.

Although BizTalk is flexible and configurable, when you've deployed your schemas, maps orchestrations etc, it all takes on a more static state. Furthermore, all those artifacts are compiled into assemblies, and you'll have binary references all over the place. These assembly references are of course internal, and doesn't necessary make your BizTalk solution less loosely coupled, but it will however have an effect on your overall productivity.

Normally, a system consuming a service hosted in BizTalk, would have no knowledge of how that call would be executed on the other side of that end-point. The mechanism behind the itinerary processing lets the consumer of the service describe the process, and pass that description to the service. A pipeline will then resolve the itinerary and proceed with the instructions.  

The itinerary describes a composition of services to be executed, such as transformation, routing and dynamic end-point resolution. Each of which works with a set of resolvers, that will provide the necessary input for that service.

It's important to understand the relationship between the services and the resolvers. Each resolver returns resolver facts as a property/value Dictionary defined in the Resolution class. This class contains properties such as TransportType and TransportLocation used by any of the adapter providers, and TransformType used for the Transform service.

A Uddi resolver, will return a preset property/value dictionary which only suits the adapter provider for dynamic end-point resolution. The BizTalk Rule Engine resolver howerver, is more dynamic and can be used with any adapter provider or service. This is since the user (developer) sets all the Resolver facts within the BRE, such as the name of a mapping file, which can then be used with the transformation service.

The help describes in great detail how’d you go about building your own Services, Resolvers and Adapter providers.

ESB Guidance part 4

Sharepoint DataFormWebPart overriding the SetDataSourceProperties method

Well firstly – I’ve got to say this comes off the back of a great Sharepoint MVP and
collegue of mine Ishai Sagi. Big THANKS
Ishai!!!

Typically my experience with the DataFormWebPart has been through the eyes of Sharepoint
Designer – open pages with webparts on them and looking at the XML configuration of
these parts. It look pretty ugly AND very site/web specific – IDs all over the place
etc etc.

Ishai the wealth of knowledge came up with this solution – by overriding the SetDataSourceProperties method,
you can effectively create a datasource from anywhere!!!! Forgetting the IDs etc that
cause all the pain.

I’ve marked the 2 important lines with (**) in the code.

Big Thanks Ishai!!! Folks he’s always one to watch – lock his blog
in and learn!! 🙂

Ishai mentioned that his code below is purely for educational purposes

using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Data;
using System.Xml;

namespace AdvancedQueryWebPart
{
[Guid(“46a8853d-415c-458e-990c-419c12fa04f5”)]
public class AdvancedQueryWebPart
: DataFormWebPart, IWebPart
{
public AdvancedQueryWebPart()
{
this.ExportMode = WebPartExportMode.All;
}

protected override void SetDataSourceProperties()
{
   try

   {
      //
Call a custom function that returns the data you want to show as a data table


      DataTable results = GetCustomData();
      if (results.Rows.Count
> 0)
      {
         //
generate xml for selected items


         XmlDocument doc = new XmlDocument();
         XmlNode root = doc.AppendChild(doc.CreateElement(“Rows”));
         foreach (DataRow
row in results.Rows)
         {
            XmlElement
rowNode = doc.CreateElement(“row”);
            foreach (DataColumn
col in row.Table.Columns)
            {
               string val = row[col].ToString();
               XmlAttribute
att = doc.CreateAttribute(col.ColumnName);
               att.Value = val;
               rowNode.Attributes.Append(att);
            }
            root.AppendChild(rowNode);
         }
         //
create an XmlDatasource with the new data, and set it to cache for one second


         XmlDataSource ds = new XmlDataSource();
         ds.CacheDuration = 1;
         ds.Data = doc.InnerXml;
         //
bind the web part to the xml


(**)     this.DataSource = ds;
(**)     this.DataBind(true);
       }
       else

       {
         Label noResults = new Label();
         noResults.Text = “No
results were found”
;
         this.Controls.Add(noResults);
       }
   }
   catch (Exception
ex)
   {
      Label lblError = new Label();
      lblError.Text = ex.ToString();
      this.Controls.Add(lblError);
   }
   base.SetDataSourceProperties();
}

private DataTable
GetCustomData()
{
   try

   {
      SPWeb webSite = SPContext.Current.Web;
      SPSiteDataQuery query = new SPSiteDataQuery();
      //look
only in document libraries


      query.Lists = “<Lists
ServerTemplate=\”101\” />”
;
      //search
for documents that have “Test” in the title


      query.Query = @”<Where><Contains><FieldRef
Name=””Title”” /><Value Type=”Text””>Test</Value></Contains></Where>”
;
      //bring
back the title field of the documents


      query.ViewFields = @”<FieldRef
Name=””Title”” Nullable=””TRUE”” /><FieldRef Name=””FileLeafRef”” Nullable=””FALSE””
/>”
;
      DataTable items = webSite.GetSiteData(query);
      return items;
   }
   catch (Exception
ex)
   {
      throw new Exception(“There
was a problem querying the site with the query”
, ex);
   }
}

}

}

System.Exception vs. General Exception

So…

People sometimes ask, what is the difference between catching System.Exception and
the General Exception in a Catch Exception shape in the orchestration designer in
BizTalk.

Off course, an obvious difference is, that with the General Exception, you don’t get
an object with properties to investigate. But then it seems that the General Exception
is useless… surely there is a point to it?

Well, I was curious about this myself, so I investigated a bit, and found this
post. So basically, I think the catch of the general exception in BizTalk 2006
is a left over from BizTalk 2004. In BizTalk 2004 it made sense, since you actually
have exceptions thrown at you that didn’t derive from System.Exception. That is no
longer possible in .NET 2.0 – they just haven’t removed it from the designer – probably
just to be backwards compatible.

That’s it…



eliasen

Quicklearn BizTalk 2006 R2 Deep Dive course

Hi everyone

Right now I am attending the Quicklearn
BizTalk 2006 R2 Deep Dive course
. I have taken their BizTalk 2004 deep dive and
2006 deep dive earlier, and now the time has come to the R2 one.

The last two times I was taught by John Callaway, and this time it is Alan Smith.

Basically, if you feel like taking a BizTalk course, that goes deeper than the normal
courses, I highly recommend the quicklean course.



eliasen

Finding the latest written document in a directory

I am working on a BizTalk test system within TFS for a client.  They are sending the output messages to a file location and using a GUID as the file name.  They have a requirement to take the output message and compare it to a known good output to determine if they are the same or not. 


 


Since we don’t know the name of the file we needed something to use to find the file.  Unfortunately, we did have anything in the file itself to correlate on nor could we add anything.  So, we decided that we would take the last written file in the output directory.  I thought there must be some code snippet that someone has already created to do this and to my surprise I couldn’t find one.  Now there is.


 


I grab the files in the directory and add them to a SortedList with the DateTime as the key and the full path and file name as the value.  I then take the one at the top of the list and use that.  The code is below:


 


XmlDocument outputDocument = new XmlDocument();


string outputDocumentFilePath;           


DirectoryInfo dir = new DirectoryInfo(outputLocation);


            SortedList sl = new SortedList();


                foreach (FileInfo fi in dir.GetFiles())


                {


                    String fname = fi.Name;


                    DateTime dt = fi.LastWriteTime;


                    sl.Add(dt,fi.DirectoryName + @”\” + fname);


                }


               


            //Read the output document from the Orchestration found in the output directory


            outputDocumentFilePath = sl.GetByIndex(sl.Count -1).ToString();


                   


            outputDocument.Load(outputDocumentFilePath);


 


There are a couple of potential issues.  What happens if more than one person is testing and multiple people are looking for their output file? What happens if BizTalk takes longer to process the message and you read the latest file before BizTalk writes out the file?


 


These are outside the scope of this entry – remember, this was just going to be how to grab the last written file in a directory of output files.