I’ll be speaking in Rotterdam in October

The second annual SOA Symposium will be held in Rotterdam (Netherlands) this year October 22nd and 23rd, you can get details here. I really enjoyed this event when I spoke at it in Amsterdam last year, and expect this second one to be both as informative as well as fun. Led by renowned author and industry guru Thomas Erl, there’s a stellar cast of speakers lined up that I’m honored to be part of.

This will be a pretty intense trip (as most are):

It’s been a long time since I was last in Rotterdam, I’m looking forward to this. If you’re there, I hope to see you at one of those events.

BizTalk Project Creation Fails – or, Why did BizTalk in VS 2008 break?

BizTalk Project Creation Fails – or, Why did BizTalk in VS 2008 break?

I found this post on the BizTalk Customer Response team blog about the problems people are having with the BizTalk project system integrated into Visual Studio 2008.  Apparently, the team built very closely on the C# project type, but that integration is causing some problems as any patches to VS can cause values to be overwritten, removing the relationship of the btproj to the csproj projects.  I have run into this on several machines and always had to repair the BizTalk installation in order to fix it.  That takes more time than I think it should to fix this type of problem, so I was glad to see the solution is a simple registry edit. 

 

You should be able to create a reg file the following contents to fix this on an x86 box:

 

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Projects\{FAE04EC0-301F-11d3-BF4B-00C04F79EFBC}]
"PossibleProjectExtensions"="csproj;btproj"

 

For a 64-bit installation, you can use a similar file, but with a slightly different path for the key. So the reg file would look like this:

 

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\Projects\{FAE04EC0-301F-11d3-BF4B-00C04F79EFBC}]
"PossibleProjectExtensions"="csproj;btproj"

 

I plan on having these registry files around on my machines with BizTalk developer tools on it so that I can quickly apply this fix anytime I patch (or Windows Update patches for me) my Visual Studio installation. 

WSCF.blue – Paste-As-Schema

WSCF.blue – Paste-As-Schema

WSCF.blue now has a new feature called “Paste-As-Schema” (which takes inspiration from the REST starter kit’s Paste-As-Type). Alex explains the new feature in detail in his post.
The MSI has now been updated to version 1.0.4. It is still formally in Beta-2. It also includes a few bug fixes in the original Beta-2 (1.0.3) release. Please […]

BAP 2.0 – using the SAP Adapter and SAP Router Strings

I thought I’d share a few interesting SAP tales.

I’ve been working on a project lately of integrating with not 1 SAP Server, but 2
and the 2nd one is across the seas accessible via a SAP Router (which
is similar to Proxy Servers for the internet). I’ve got to thank Rohit Singh (MS)
and his team for some great feedback, as well as Scotty and Kent Weare whom were helping
me to nut out where half these settings go.

Specifically I needed BTS to be a ’remote RFC server’ for the two SAP Servers.

What does a Router string look like I hear you ask – “/H/devapp1/S/3300/H/acmesaprouter.acme/S/3300/H/sapdb01.acme”. Something
like that, and the user’s type this into the SAP Client UI to connectmy chances of
being able to ’stick’ this somewhere in the BizTalk world was diminishing.

So I had to get my BizTalk box to talk through the ’SAP Router’ out with the right
credentials to another SAP Server 1200KMs away”good luck” little adapter I thought.
(“good luck” Mick I though too)

Here’s the low down:

  1. Use a saprfc.ini file – scarce documentation, but do able.
  2. Set a RFC_INI System Environment variable.
  3. Turn on Rfc Tracing
  4. Get on well with the SAP teams.
  5. Get on well with the SAP teamsoh I mentioned that one already.

Here’s how you do it – after you’ve installed and setup the prereqs for the SAP Adapter
(don’t forget to add the SAP Adapter property schema to BizTalk)

Starting out:

– I jumped in and used the ‘Consume Service Adapter’ Wizard to work out connection
details and look at the IDOCs schemas.

The problem is – as time goes by, you want to see debugging and other details to tweak
as trying to establish a connection. The Receive Location (WCF-Custom, sapBinding)
SAP URI get’s horribly long.

 

I was happy to put up with this when I got the first connection to the SAP Server1
(local).

 

This *didn’t* work for SAP Server2(remote) – trust me, it’s a square peg in a round
hole.

 

Using SAPRFC.INI :(generally the MS Docs will get you started, but
I found they had incomplete settings so I had to go elsewhere – a Siebel->SAP 2001
document served the purpose)

  1. Create a System Environment Variable called RFC_INI  and point
    it to where you want your saprfc.ini file to live.
    e.g. SET RFC_INI=d:\BizTalk_Dev\SAP\saprfc.ini
    (the MS documentation doesn’t say *exactly* where to put the saprfc.ini –
    I tried it in the bts folder, windir…many places)
  2. Set the Receive Location to use the saprfc.ini – e.g. sap://client=110;lang=en;@D/SAPSERVER?LISTENERDEST=BTS_INBOUND&RfcTraceSdk=true
  3. Using the SAPRFC.INI file

Sample SAPRFC.INI – for local SAP connection

DEST=SAPSERVER
TYPE=A
ASHOST=DEVAPP1
GWHOST=DEVDB1
GWSERV=sapgw00
SYSNR=00
RFC_TRACE=0
ABAP_DEBUG=0
USE_SAPGUI=0

DEST=BTS_INBOUND
TYPE=R
GWHOST=DEVDB1
GWSERV=sapgw00
PROGID=BizTalkDev_Inbound  (<– this is allocated from SAP)
SYSNR=00
RFC_TRACE=0
ABAP_DEBUG=0
USE_SAPGUI=0

Connecting to a SAP Server via a SAP Router String – sample
saprfc.ini
e.g. router string -/H/devapp1/S/3300/H/acmesaprouter.acme/S/3300/H/sapdb01.acme

ListenerURI (BTS Receive Location) = sap://client=110;lang=en;@D/ACMESAP?LISTENERDEST=ACMESAP_INBOUND&RfcTraceSdk=true

DEST=ACMESAP
TYPE=A
ASHOST=/H/devapp1/S/3300/H/acmesaprouter.acme/S/3300/H/sapdb01.acme
GWHOST/H/devapp1/S/3300/H/acmesaprouter.acme/S/3300/H/sapdb01.acme

GWSERV=sapgw00
SYSNR=00
RFC_TRACE=0
ABAP_DEBUG=0

DEST=ACMESAP_INBOUND
TYPE=R
GWSERV=sapgw00
GWHOST=/H/devapp1/S/3300/H/acmesaprouter.acme/S/3300/H/sapdb01.acme
PROGID=BizTalkDev2_Inbound
SYSNR=00
RFC_TRACE=0
ABAP_DEBUG=0

 

 

HTH folks and saves you guys some time – 🙂

Powershell Zip Files on Network Drive

I was having a frustrating time zipping files in a Powershell script, one that I had created based on those discussed in David Aiken’s blog post. The name of the zip files created were quite long and were being generated a 8.3 filename automatically whenever the CopyHere method was being called on the zip folder where the files were being added. It was certainly something related to this method, as the New-Zip function was creating the zip file with the desired name, but was renamed only after the CopyHere method was used.

Now I still haven’t found a solution to this problem so if anyone has any suggestions they are most welcome to post them. What I did do however was create a workaround which entails creating the zip file locally on the machine where the script is executing and then move this to the destination. It turns out this problem only happens when attempting to write to a network folder directly.

The following function had the issue with CopyHere

function Add-Zip
{
param([string]$zipfilename)

if(-not (test-path($zipfilename)))
{
set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
(dir $zipfilename).IsReadOnly = $false
}

# Return the application object
$shellApplication = new-object -com shell.application

# Returns a folder object for the specified folder
$zipPackage = $shellApplication.NameSpace($zipfilename)

# Returns file object for the zip file
$zip = Get-Item $zipfilename
$activity = 'Zipping file to ' + $zip.Name + ': '
foreach($file in $Input)
{
Write-Progress -activity $activity -status $file.Name
$zipPackage.CopyHere($file.FullName,256)
Start-sleep -milliseconds 500
}
}

So I simply created a temporary zip and then moved it

# For some reason the filename is getting trimmed when writing directly to the network, so
# we use a temporary folder here for storage before moving to the final destination
$filename = "$element-$(Get-Date -f dd-MMM-yy-HH-mm-ss)"
$zipPath = "$tempFolder\$filename.zip"

# Create a new zip file
New-Zip $zipPath
$path = $element.PSPath

# Add each item in this elements path to the zip file
Get-Item $element.PSPath | Add-Zip $zipPath

# Now move it to the final destination
Move-Item $zipPath $componentfolder
Set your BizTalk Server 2009 and 2006 R2 services start up type to Automatic (Delayed Start)

Set your BizTalk Server 2009 and 2006 R2 services start up type to Automatic (Delayed Start)

We’ve recently had some development and test BizTalk environments move data centres, and after the BizTalk Server machines were restarted the BizTalk host instance services stayed disabled.
By default the BizTalk host instance service (the windows services named ’BizTalk Service BizTalk Group: <host name>’) have a start up type of Automatic. There is a known […]

Utah Code Camp – Fall 2009

Utah Code Camp – Fall 2009

I had a great time speaking at the Utah Code Camp this weekend – a fun event with engaging attendees and lots of good swag from sponsors. If you’re looking for the slides from my presentations, you can grab them here:

Pluralsight was one of the sponsors at the show. We gave every attendee a free trial pass to Pluralsight On-Demand! and raffled off an unlimited full-year subscription at the end of the day. We also had several of our new “cloud tag” t-shirts to give away.

If you received one of our promo cards at the event, you can activate it here. Remember the card expires in 30-days.

Sweden UG Visit Wrap Up

Sweden UG Visit Wrap Up

Last week I had the privilege of speaking at the BizTalk User Group Sweden. Stockholm pretty much matched all my assumptions: clean, beautiful and full of an embarrassingly high percentage of good looking people. As you can imagine, I hated every minute of it.
While there, I first did a presentation for Logica on the topic […]

CA1502:AvoidExcessiveComplexity and Lambdas

[Source: http://geekswithblogs.net/EltonStoneman]

In code with lots of lambda expressions, you may trigger a false positive for the Code Analysis rule CA1502 “AvoidExcessiveComplexity”. The rule calculates cyclomatic complexity using the logic in Microsoft.FxCop.Sdk.MethodMetrics, which enumerates the instruction set and increments complexity count when it finds one of a given set of opcodes.

The rule was triggered code which uses the Fluent DAL approach to populate a composite entity:

public static Entity GetEntity(int entityId)

{

//populate basic details:

Entity entity = Fluently.Load<Entity>().With<EntityMap>()

.From<GetEntity>(i => i.Id = entityId,

x => x.Execute());

//load child entities:

if (entity.IsKnown)

{

entity.Address = Fluently.Load<Address>().With<AddressMap>()

.From<GetEntityAddresses>(i => i.Id = entityId,

x => x.Execute());

entity.Contact = Fluently.Load<Contact>().With<ContactMap>()

.From<GetEntityContacts>(i => i.Id = entityId,

x => x.Execute());

}

else

{

//more of the same

The method in question had a single if/else branch, no other conditional logic, but 7 fluent calls totalling 12 lambdas. I calculate the cyclomatic complexity to be 2, and NDepend agrees. FxCop tells me the complexity is 26.

I stripped this down to a much simpler sample and found the same issue:

public void CCCheck2()

{

Fluently.Load().With().From(i => i.ToString(), x => x.ToString());

Fluently.Load().With().From(i => i.ToString(), x => x.ToString());

Fluently.Load().With().From(i => i.ToString(), x => x.ToString());

}

– this gives a CC of 13, although it has no conditional logic at all.

The answer’s in the IL – the lambdas are emitted as private static classes and executed using an instance which is lazy-loaded:

IL_000b: ldsfld class [System.Core]System.Func`2<int32,string> FxCopCC.LambdaSample::’CS$<>9__CachedAnonymousMethodDelegate6′

IL_0010: brtrue.s IL_0025

IL_0012: ldnull

IL_0013: ldftn string FxCopCC.LambdaSample::'<CCCheck>b__0′(int32)

IL_0019: newobj instance void class [System.Core]System.Func`2<int32,string>::.ctor(object,

native int)

IL_001e: stsfld class [System.Core]System.Func`2<int32,string> FxCopCC.LambdaSample::’CS$<>9__CachedAnonymousMethodDelegate6′

IL_0023: br.s IL_0025

br and brtrue are transfer of control statements, so every lambda expression actually causes a branch – where the IL checks to see if there’s a cached instance of the delegate, or whether it needs to instantiate one – and a return. The complexity rating is correct for the IL, as 1 + 2x(number of lambdas).

But cyclomatic complexity is a measure of readability, so the additional branches in the IL should be irrelevant. The short term solution is to suppress the message on methods with heavy lambda usage. A longer term option is an alternative rule which uses a different calculation.

A side point is that the IL isn’t aggressively optimised by the compiler – lambdas with identical code are generated as separate private classes, each with their own lazy-loading check, so to avoid that overhead lambdas which are reused can be centralised:

private Func<int, string> GetInitialise()

{

return new Func<int,string>(i => i.ToString());

}