Skip to main content

Copy local that BizTalk 2009 reference

I’m sure by now everyone has met the evil ‘copy local’ problem in BizTalk.  It’s blogged by Jan here and by Ryan as well. Often, you want to add your schema project as a reference to the map or orchestration project. Things might look allright at first, but then after some changes, you get build errors. Once you know what it is, it’s easy to solve, just put that ‘copy local’ setting on your reference to false, then directly back to true. Magically (?) it all works again.

It’s one of the issues that gets attributed to BizTalk 2009, but I just reproduced this in a C# project trying to reference a BizTalk project. What exactly happens? It did all work in 2005!

In fact, Visual Studio is fooling us all. The csproj and btproj files don’t actually have that copy local at all! For a copy local referenc, The project file should contain something like this:

   {00000000-0000-0000-0000-000000000000}
   Mysolution.Schemas
   True

However the part <Private>True</Private> is missing. So the compiler does not copy the dll locally.

Why this strange behaviour? I found an explanation in the MSDN: http://msdn.microsoft.com/en-us/library/ez524kew.aspx

If you deploy an application that contains a reference to a custom component that is registered in the GAC, the component will not be deployed with the application, regardless of the CopyLocal setting. In earlier versions of Visual Studio, you could set the CopyLocal property on a reference to ensure that the assembly was deployed. Now, you must manually add the assembly to the Bin folder. This puts all custom code under scrutiny, reducing the risk of publishing custom code with which you are not familiar.

By default, the CopyLocal property is set to False if the assembly or component is in the global assembly cache or is a framework component. Otherwise, the value is set to True. Project-to-project references are always set to True.

At run time, components must be either in the output path of the project or in the Global Assembly Cache (GAC). If the project contains a reference to an object that is not in one of these locations, you must copy the reference to the output path of the project when you build the project. The CopyLocal property indicates whether this copy has to be made. If the value is True, the reference is copied to the project directory when you build the project. If the value is False, the reference is not copied.

Since BizTalk assemblies are always deployed to the GAC, in fact if your copy local contains the right private setting depends on if your project was deployed before you added the reference. Even though you still seem to have copy local set right!

An unhappy side effect of this is that the orchestration / mapping is compiled against the schema that is in the GAC and not the one that is in your project. Leaving you to guess why that change you made did not compute at build time.

I also remember having some other problems with assemblies in the GAC referred in Visual Studio. Perhaps this is all related. I hope this issue is gets addressed in the next release!

ALWAYS export your itinerary in strict mode

I lost quite some time last week trying to figure out why my itinerary services were processed out of order. I created a simple solution based on the A-B-C scenario I wrote about last week. Difference was there that I am using a common data model in the middle, so I need to transform my incoming message to a common model, and my outgoing messages as well, just like the return messages.

So I created an itinerary with the following sequence:

  1. On-Ramp (file)
  2. Message Transform service (to common request)
  3. Message Route service
  4. Off-Ramp extender
  5. Message Transform (to outgoing request)
  6. Off-Ramp (using the itinerary forwarder pipeline)
  7. Message Transform (to common response)
  8. Message Route back
  9. Off-Ramp extender
  10. Message Transform (to imcoming response)
  11. Off-Ramp (file)

If you export this using the default setting, each ESB pipeline will process as much as it can, until it finds an off-ramp service. Depending on some other configurations (two-way,  request response, putting the route on send or receive side, changing the pipelines on the ports) this resulted in different orders or processing, none of which were what I wanted. Mostly, the send pipeline in the first off-ramp would try to do both the send and receive transform in the send. Looking at the exported XML indeed I could not see how the pipeline would ‘guess’ the order that I indicated so carefully in my DSL.

Turns out you need to set the “Export Model” option to strict. The default setting was intenede for compatibility with V1 of the guidance. On the ESB forum, this is what Brian Birdoes says about the export model:

The strict mode supports new features such as stage and the broker.  As mentioned in the docs the stage attribute is output and utilized by the ESB Dispatcher in On-Ramps and Off-Ramps.  Without it, the engine basically processes as many steps as it can until it ends or hits an orchestration or off-ramp step.  With the stage attribute the engine can skip a step and not execute it until the correct pipeline direction.  For example, if you want a transform to run on a request-response (service pass-through) scenario on the Off-Ramp’s receive pipeline, the only way to do this is to have the stage attribute.  This could be a common scenario since the original requestor may not expect the message in the format returned by the service.  In default mode the transform would always execute on the Off-Ramp’s send pipeline.

The broker capability utilizes the id and next id to work correctly.  In V1 the steps are processed sequentially.  For more advanced routing like the broker the engine needed a way to jump to steps.  The pattern was basically to use a linked list within the itinerary.  The outcome of these filters really is to determine the correct id to jump to for the next step.

Simply put, Default mode is for backward compatibility with V1 itineraries.  Strict mode is required for many of the new V2 features.  For itineraries that I build I generally use Strict mode.

So hope I can prevent you from making the same mistake. Make ‘strict’ your new default.

Create BizTalk Project … Project Creation Failed

Friday I uploaded a new update in microsoft update. It was a 365 MB Update called the “Security Update for Microsoft Visual Studio 2008 Service Pack 1 (KB971092)”. Turns out this is an update of another update that was released a week earlier (see this blog also)

If you are using BizTalk 2009 you will probably experience the same issue as me. After installing it, you cannot create BizTalk projects anymore. You will get the very discriptive text “Project Creation Failed” in your status bar. In the eventlog you will find that the template is not installed.

The solution? Just load the BizTalk CD or ISO to your PC and choose ‘Repair’. After that you can create the projects again.

Update:

Not really a patch, but an easier way to solve this was published on the biztalk customer response team blog. Apparently you only need to change a little thing in the registry. Get the full text at this link

We could get the project system to work by repair installing Biztalk but that doesn’t seem like a solution.  Further debugging revealed that the following registry setting was modified by a VS update.

 [HKEY_LOCAL_MACHINESOFTWAREMicrosoftVisualStudio9.0Projects{FAE04EC0-301F-11d3-BF4B-00C04F79EFBC}]

“PossibleProjectExtensions”=”csproj”   – Original VS install reg value. “PossibleProjectExtensions”=”csproj;btproj” – Post Biztalk installation reg value

The following is the entry for the 64 bit version of VS:

HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftVisualStudio9.0Projects{FAE04EC0-301F-11d3-BF4B-00C04F79EFBC}

xpath to the Max() – still no support

Today I wanted to use a simple XPATH function in my orchestrationto find the maximum value of a sequence number in a set of nodes. So I booted up XMLSpy and loaded the xml schema. Simple problem, simple solution:

max(//sequence_nr)

Wrong.. biztalk does not support xpath 2.0. Even worse, I cannot even program a helper function since .NET 3.5 does not support XPATH 2.0. This was kind of hard to verify since msdn states something different.

Since my records are ordered, luckily I could also pick the last record. Which resulted in the uglier xpath statement:

string(//record[count(//record)]/sequence_nr)

That the actual statement was a lot longer since it had namespaces and some subnodes. And I really don’t see how I could do this in xpath when the records were not sorted.

This post in microsoft connect I found acknowledges that xpath 2.0 is still not supported in .Net framework 3.5

I hope they will manage to fit support in framework version 4.0

A – B – C itinerary using the ESB Toolkit

Now that I had my SQL Adapter insert covered as show in the last post, I wanted to create an itinerary that gets a message from a one way port, then sends it to the SQL Adapter to do that insert (request / response), and then with the result of that insert, trigger another one way send port. So from A (one way) to B (two way) to C (One way) This is a scenario that you can configure in BizTalk as message routing using pub/sub, but how would you do this in an itinerary?

What I did not find right away is how to forward the response message to another port. In fact, it wasn’t easy to find any sample that had more then one (send port) at all. Would this mean creating two off-ramps? and how to configure the off-ramp ports? And would the itinerary be a one way itinerary or a two way?

Brian Birdoes sent me on the right track: in the multiple web services sample, there is a one way scenario. However this one is only provided as an XML and the itinerary DSL file is not provided and on top of that, it has a bug. The key issue was that when you want to send on a response message from a solicit response port, you need the ItineraryForwarderSendReceive pipeline in the response port. And the sample used the normal DynamicResolutionSolicitResp port instead of the DynamicResolutionSolicitRespForwarder

Using Hernan de lahitte’s Itinerary Designer Model Importer did some work, but left me still with a broken itinerary. Using some trial and error I recreated a model that produced exactly the same XML. After that I put some nice names on it and posted it here so we can all profit from it.

Get the updated sample itinerary

WCF SQL Adapter through an itinerary

I just started using the ESB Toolkit, and I wanted to create an itinerary that sends messages to the SQL Adapter to do an insert action.

I found the sample on configuring the SQL WCF port with some help with of the ESB Toolkit forum, so no problems there. But the documentation for the sample is non-existent. So I thought I should give you the head-start I did not get. It’s really not that difficult.

First things first, I am assuming you already know how to do a two-way two-way itinerary. Without mapping this would be a request response itinerary with four sequential shapes, the fourth connecting back to the first:

  1. On ramp (two way)
  2. Routing Service Messaging Extender (itinerary service, select messaging as extender, Routing as service)
  3. Off ramp extender (itinerary service)
  4. Off ramp (two way)

You add a resolver to the messaging extender to enter the parameters for the dynamic send port.

WCF SQL Adapter through an Itinerary

The ‘magic’ for calling the SQL adapter is all in that resolver. To keep things easy, we use a static resolver with the following properties

  • Resolver implementation: static
  • Transport name: WCF-Custom
  • Transport location: mssql://myserver//mydatabase?
  • Endpoint configuration: BindingType=sqlBinding
  • Action: {TableOp/Insert/dbo/myTable}

Basically you can copy those attributes from the binding file that was generated when you used the generate schema option for the WCF SQL Adapter. I did not test if it is possible to use the BTSActionMapping construct but it would make more sense to decide the operation in a business rule resolver when you are doing ESB Toolkit anyway. In any case don’t forget the curly brackets around the action.

The actional sample, the SqlAdapter-TwoWay-MessageRouting-MessageTransform-MessageTwoWaySendPort.itinerary file contains an additional mapping, but is basically the same.

Don’t forget, before you install this sample you have to install the dependent samples: Dynamic Resolution Sample, Resolver Service Sample and the Itinerary On ramp sample.

This sample you can try out yourself by executing setup.bin in the installscripts folder, then execute Esb.Itinerary.Test.exe from the itinerary sample. Select Two Way Service in web service options and deselect Use WCF Service,  Load the itinerary xml provided in the itineraries folder of the sample, load up the request message from the testdata folder and press request. If all is well, you should get the response back.

 
%d bloggers like this: