Sunday, October 21, 2007

Hi

I just thought I would share my experiences from the first BizTalk 2006 R2 I have installed and configured.

It was on two different boxes - one for SQL Server and one for BizTalk. Domain groups were created beforehand, as well as a service account for the services. So everything should be in place.

Installation went fine, naturally, but the configuration wouldn't let me configure Group and Runtime. I checked the logs, off course, and the first error was this one:

[09:14:15 Info ConfigHelper]  is not a local entity.
[09:14:15 Error ConfigHelper] d:\depot2300\mercury\private\common\configwizard\confighelper\service.cpp(729): FAILED hr = 80070421

[09:14:15 Warning ConfigHelper] The account name is invalid or does not exist, or the password is invalid for the account name specified.
[09:14:15 Warning ConfigHelper]  Failed to validate service credentials for account: %1

So it had to be something about the credentials I have specified. So I unconfigured, reconfigured, being very carefully to enter the correct credentials - same error. I tried again, with extra extra focus on not mistyping anything. Same error.

Then I searched some more in the log file, and found this:

2007-09-25 09:16:49:0441 [INFO] WMI Deploying 'C:\Program Files\Microsoft BizTalk Server 2006\Microsoft.BizTalk.GlobalPropertySchemas.dll'
2007-09-25 09:16:49:0723 [WARN] AdminLib GetBTSMessage: hrErr=80070002; Msg=The system cannot find the file specified.;
2007-09-25 09:16:49:0723 [WARN] AdminLib GetBTSMessage: hrErr=c0c02560; Msg=Failed to read "KeepDbDebugKey" from the registry.
The system cannot find the file specified.;

But the file actually existed. Then I searched the log file some more, and found this:

2007-09-25 09:16:49:0863 [INFO] WMI Error occurred during database creation; attempt to rollback and delete the partially created database'hcpr-hd-axa-01\BizTalkMgmtDb'
2007-09-25 09:16:49:0863 [INFO] WMI Calling CDataSource.Open() against hcpr-hd-axa-01\master
2007-09-25 09:16:49:0879 [INFO] WMI CDataSource.Open() returned
2007-09-25 09:17:09:0942 [WARN] WMI Rollback failed.  Could not delete database.
2007-09-25 09:17:09:0942 [ERR] WMI Failed in pAdmInst->Create() in CWMIInstProv::PutInstance(). HR=c0c025b3
2007-09-25 09:17:09:0942 [ERR] WMI WMI error description is generated: Exception of type 'System.EnterpriseServices.TransactionProxyException' was thrown.
2007-09-25 09:17:09:0942 [INFO] WMI CWMIInstProv::PutInstance() finished. HR=c0c025b3
[09:17:09 Error BtsCfg] d:\depot2300\mercury\private\mozart\source\setup\btscfg\btswmi.cpp(358): FAILED hr = c0c025b3

[09:17:09 Error BtsCfg] Exception of type 'System.EnterpriseServices.TransactionProxyException' was thrown.
[09:17:09 Error BtsCfg] d:\depot2300\mercury\private\mozart\source\setup\btscfg\btscfg.cpp(1769): FAILED hr = c0c025b3

This error pointed to some transaction error, so I downloaded and ran dtctester and it turned out my MSDTC settigns were not good enough. I spend the better part of a day looking for this. What really had me confused was that the SSODB was created fine - the BRE-DB was created fine... and the BizTalkMgmtDb database was sometimes created just fine. I mean... sometimes it would create the BizTalkMgmtDB database and fail during creation of the MessageBox. Other times it would fail on the Management database. So seing as two databases were created just fine, I really didn't think there were any issues with DTC.

BUT, this just goes to show; Before starting a multibox installation of BizTalk, ALWAYS run dtc tester first - just to be sure :-)

--
eliasen

Sunday, October 21, 2007 8:02:05 PM (Romance Daylight Time, UTC+02:00)  #    Comments [5]  | 
Thursday, October 18, 2007

Hi all

This isn't about BizTalk, .NET or anything else technical. This is about ME!

The other day I mended a fuse in our car.

Really? you might say.. so what? Well, to me this is a big deal :-) I don't like getting dirty hands - I generally never do anything practical around the house... I am lousy at it, I hate it, and I would rather pay someone else to do it.

But then, the back light on the car stopped working. I changed the light bulbe, which in itself took me about 2 hours, including driving to the gas station to buy a new bulbe... and then it turned out the original bulbe wasn't broken. That sucked! Then I decided I had to take the car to the mechanic... but a friend asked me if I had checked the fuses. Well, duh... off course not - how would I do that? So with the manual in one hand and a screwdriver (YES, a screwdriver... me... a screwdriver...) in the other hand, I found the fuse that wasn't working anymore. I drove, once again, to the gas station, bought a new one (approximately one dollar) and put it into place. And now the back lights are working again.

WOW! What en experience, eh? :-)

So after reading this, you might still think: "Is this guy crazy? All this fuzz about mending a fuse (Thanks to Mads Orbesen Troest for telling me how to say this in English)? YES! It's a bg deal! :-)

--
eliasen

Thursday, October 18, 2007 10:07:20 PM (Romance Daylight Time, UTC+02:00)  #    Comments [2]  | 
Sunday, October 14, 2007

Hi

The other day I published an orchestration of mine as a web service. Not a big deal. Then, I needed to export the MSI for my application, so I could install it on the test server. Now THAT was a Big Deal! :-)

I got this one:

A really silly restriction on a quite normal Windows Server 2003 R2 - as you can see, the entire path of a file, including the filename, must be less than 260 characters long. And the path itself must be less than 248 characters long.

This had me stunned for a moment, until I took a closer look at what file creation was the issue. It turns out, that the issue was with creating temporary files in c:\documents and settings\administrator\local settings\temp. Yes, I am logged in as administrator. No, I wouldn't normally do that. Quit asking these questions, and let me finish the post! Right. Then I got clever, if I might say so myself (nobosy else is saying it, so I suppose I have to do it myself :-) )... Turns out that the temporary files are created in the %TMP% (NOT the %TEMP% one...) directory. So what to do? Simple - change the %TMP% environment variable to point at c:\tmp in stead of c:\documents and settings\administrator\local settings\temp. That's what I did, and it worked. I got my MSI file.

BUT... Well... You know that sometimes you do something that is like peeing in your pants? At first it is warm, but then it just gets cold and nasty? Well, this is like that. Because when I then took the MSI file to the test server and tried to install it (not the import part, but the install part), I got the exact same error. The default installation path is C:\Program Files\Generated by BizTalk\ - which is also a rather long path. So in order to install my application, I ended up installing it to c:\biz. Now having to tell your customer that they can't install the application to a path longer than 5 characters really isn't an option.

So my clever and very nice workaround to just set the TMP environment variable to c:\tmp in order to generated the MSI file really wasn't all that clever, since the installation wasn't acceptable at all. Had the issue just been my own developers box, I wouldn't have minded... but now I have to go rename all artefacts anyway. Bugger!

So basically, this post is written for people looking for a workaround for the error they get with long filenames/paths. My suggestion: Rename your artefacts, and don't wet your pants! :-)

--
eliasen

Sunday, October 14, 2007 9:52:42 PM (Romance Daylight Time, UTC+02:00)  #    Comments [0]  | 
Sunday, October 7, 2007

Hi

Well, some people have their BizTalk vNext wishlist on their blog. I'd like to add a couple of requests to the growing list :-)

  1. For development purposes, it would be really nice to be able to rightclick a receive location that is disabled and choose "Execute". If for instance I have a SQL adapter receive location that is supposed to poll every minute, then I don't want to have to quickly disable the receive location once it has been fired. I want to keep it disabled, so data wont go through my system when I am not ready, and then just execute it whenever I am ready.
  2. Deployment of single assembly from VS.NET. If I have three projects in my solution: Schemas, Maps and Orchestrations, and both Maps and Orchestrations reference Schemas, then I can not deploy them all at the same time from VS.NET :-( Deploying Orchestrations will make VS.nET deploy Schemas as well - even if there are no changes to it. To deploy Schemas, the current Schemas assemblymust be undeplyed, and therefore, the Maps assembly must also be undeployed. So VS.NET will Undeploy Orchestrations, Undeploy Maps, Undeploy Schemas, Deploy Schemas, Deploy Orchestrations. This isn't acceptable, because Maps isn't deployed anymore. If I then deploy Maps, the same thing happens, only the Orchestrations gets undeployed and it isn't redeployed. To me, VS.NET should ONLY interfere like that if I deploy the entire solution. If I deploy just project, then just let me do so! Right now, I would have to let Orchestrations reference Maps even if it isn't necessary and then always deploy Orchestrations.
  3. Restart Host Instances only once. Right now, if I deploye my solution from VS.NET, and this solution has 10 proejcts that are all set to "Restart Host Instances" on deployment, then the host instances will get restarted 10 times. Would be nice if VS.NET could figure this out and only do it once.
  4. Specify the node that is body, when using enveloping and not just the parent. It makes great sense, that I can specify a node and all child elements are then submitted as seperate messages from the receive pipeline. This is how we can receive orders, invoices, etc. in the same XML. BUT, if I receive XML where I only need the Orders, then I would like to point at the Orders element so that is all I get. Right now I have to use standard enveloping, and implement logic to just delete the invoices, etc. Not really nice, I think.

That's it for now :-)

--
eliasen

Sunday, October 7, 2007 12:40:36 AM (Romance Daylight Time, UTC+02:00)  #    Comments [0]  | 

Hi

A guy on the newsgroups recently needed to create exactly 5 elements in the output of his map, no matter how many records appeared in the input.

Well, I am always looking for new things to try out, and frankly, my XSLT coding skills could be better, so I thought I'd give it a shot.

I created a project with the following input schema:

The schema is for an XML document, and has a header (1..1), a LoopingRecord (1..1) and a footer (1..1). The LoopingRecord has a Field5 element, that can appear at most 5 times.

The output schema looks like this:

This schema is for a flat file. It baiscally has the same signature as the input schema - exception being that the Field1 element has minOccurs=5. It MUST be present 5 times - this is a schema for a positional file.

The map is pretty simple:

Header and footer are mapped using regular mapping techniques. But the Detail-element is created using a custom scripting functoid.

The string concatenate functoid only has one input, the string "5". This is because I want to create exactly 5 elements in the ouput.

The custom scripting functoid is an "Inline XSLT Call TEmplate" scripting functoid with the following code:

<xsl:template name="CreateXElements">
   <xsl:param name="totalCount" />
      <Detail>
         <xsl:for-each select="/*[local-name()='InputRoot']/*[local-name()='LoopingRecord']/*[local-name()='Field5']">
            <DetailLoop>
               <Field1><xsl:value-of select="text()" /></Field1>
            </DetailLoop>
         </xsl:for-each>
         <xsl:variable name="countRecords" select="count(/*[local-name()='InputRoot']/*[local-name()='LoopingRecord']/*[local-name()='Field5'])" />
         <xsl:if test="$countRecords&lt;$totalCount + 1">
            <xsl:call-template name="BuildTheRest">
               <xsl:with-param name="counter"><xsl:value-of select="$countRecords + 1" /></xsl:with-param>
               <xsl:with-param name="totalCount"><xsl:value-of select="$totalCount" /></xsl:with-param>
            </xsl:call-template>
         </xsl:if>
      </Detail>
</xsl:template>
<xsl:template name="BuildTheRest">
   <xsl:param name="counter" />
   <xsl:param name="totalCount" />
      <DetailLoop>
         <Field1></Field1>
      </DetailLoop>
      <xsl:if test="$counter&lt;$totalCount">
         <xsl:call-template name="BuildTheRest">
            <xsl:with-param name="newCounter"><xsl:value-of select="$counter + 1" /></xsl:with-param>
         </xsl:call-template>
      </xsl:if>
</xsl:template>

Basically, I start by copying existing nodes to the destination. As I have explained in this post you need to use XSLT for the whole thing. You can't copy the existing nodes using the mapper and create the new nodes using XSLT. After the existing nodes have been copied, I create the new empty nodes, by recursively calling a template that will create a single element for me.

You can find my entire project here: CreateXNumberOfElements.zip (23.33 KB)

I hope this will come in handy for someone in the future.

--
eliasen

Sunday, October 7, 2007 12:09:42 AM (Romance Daylight Time, UTC+02:00)  #    Comments [4]  | 

Theme design by Jelle Druyts