Tuesday, May 22, 2007

Annoying Web Services

Believe or not...not all people create their Web Services in a BizTalk-friendly fashion! I know it's difficult to grasp, but it's the sad reality.

Recently, I had problems with a Java-based Web Service for a mailing list application. To familiarize myself with the possibilities of the Web Service I created a sandbox .Net assembly with a reference to the Web Service and played around with it for a while, calling the different methods, testing the results, etc. No problem at all.

The problems began, when I added a reference to the Web Service in my BizTalk project. The project simply wouldn’t compile after adding the reference! Apparently, there was a naming clash between a part of the Web Service and some word restrictions imposed by BizTalk. It must be BizTalk specific, since a non-BizTalk project compiles perfectly well with the Web Service reference.

Actually, the error messages when compiling weren’t really helpful, so I can’t say exactly what the problem was. However, that’s not the point of this post anyway so never mind that.

The point of this post is to talk about what you could do if you for some reason want to use a Web Service in a BizTalk project without using the built-in feature in Visual Studio to generate a proxy.

You could choose to create some sort of wrapper or proxy for the Web Service yourself – it could be a less complex Web Service, or simply an assembly that could be called directly from an expression shape in an Orchestration. Both of these approaches would allow you to only implement support for the needed parts of the original interface, thus keeping the complexity to a minimum. This was desirable in my case, since the original Web Service had 30+ methods – try adding a couple of ports for such a Web Service in an Orchestration!

The obvious downside to this approach is that you actually have to code the wrapping of the Web Service yourself – with all the usual possibilities of introducing bugs. Also, if the Web Service interfaces changes you’ll have to update the wrapper code manually.

There’s also an automated approach that will create a wrapper class (proxy) for you. In the C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin folder you’ll find the command-line tool WSDL.exe. With this tool you can generate an assembly – or proxy if you will – that matches a specific Web Service. This is the approach I chose for my project.

Executing WSDL.exe from a command prompt will display all the functions of the tool. Some of the important ones are:
  • First of all you have to specify a URL to an instance of the Web Service.
  • /namespace - set the namespace of the generated code.

  • /username and /password - set the credentials used to make a connection to the original Web Service.

  • /out - set the ouput filename for the generated code.

  • /urlkey - set the name of a config key to store the URL for the original Web Service.

Rather than having configuration information spread out on a number of config-files, I chose not to use the /urlkey option. Instead I added a key in the BtsNtSvc.exe.config to store the URL of the target Web Service and used this to set the URL runtime in the Orchestration – the generated proxy-code includes a method to set the URL for the target Web Service. I used the same approach to set the username and password for the target Web Service runtime as well.

The generated assembly of course needs to be strongly named.

You can read more about WSDL.exe on http://msdn2.microsoft.com/en-us/library/7h3ystb6(VS.80).aspx.

The tool also exists in a .Net 1.1 version.

Monday, May 21, 2007

Windows SFU and the BizTalk FILE adapter

In the previous post I mentioned a problem we had picking up files from a UNIX box using the FTP adapter. In the lack of a good solution to the FTP problem, we decided to try the Windows Services for UNIX (SFU) and then to use a simple file adapter to pick up the files.

The Windows SFU will let you connect to UNIX folders as if the where Windows folders. You basically just apply the UNIX credentials the "Client for NFS" part of SFU enables Windows computers to access UNIX files and directories without making any changes on the UNIX box. You can the browse the folders by mapping the them as network drives or by using the UNC path. (You can read more on http://technet.microsoft.com/en-us/interopmigration/bb380242.aspx)

Having set up SFU using the supplied administrative console, I could browse the files on the UNIX box through Windows Explorer as if they were any other network share.

Two receive locations were configured to poll the new network shares using the FILE adapter, and I started the application. But it didn't work as planned. I tried various approaches, but none of them worked:
  1. Setting the file pick-up folder to point to a mapped network drive (i.e. y:\MyFolder\*.xml).
    Problem: I would get a "path not found" error in the eventlog even though I could copy the path to an Explorer and browse the files fine.

  2. Setting the file pick-up folder to point to the UNC path of the UNIX share (i.e. \\MyServer\MyFolder\*.xml).
    Problem: I would get a "Logon failure: unknown user name or bad password".

  3. Setting the file pick-up folder to point to the UNC path of the UNIX share (i.e. \\MyServer\MyFolder\*.xml) AND applying the UNIX credentials as alternative authentication on the FILE adapter properties.
    Problem: Nothing happened! Absolutely nothing! The files were not picked up and there was no errors to be found in the eventlog.

There really wasn't much help to be found anywhere on the net, but it seemed obvious for the problems to be related to some security issue. The solution turned out be to map the Windows user running the BizTalk Host Instance to the UNIX user applied in SFU and then to go with the 2. setup described above: Setting the file pick-up folder to point to the UNC path of the UNIX share.

FTP adapter stopped polling

The project required files to be picked up by BizTalk from two locations on a UNIX box.
We chose to set up two FTP sites on the UNIX box and have BizTalk poll the two sites using the FTP adapter. This approach seemed to work fine for a long while. There was never a problem on the development environment, and for a couple of weeks everything worked fine in production as well.
Then all of the sudden the FTP receive location for either or both sites would stop polling the site. Looking in the BizTalk Administration Console would show no signs of something being wrong, the receive locations would be enabled, the eventlog would show no error and the Group Hub Page would show nothing unusual.
The log on the UNIX box would just show that at a given time one or both polling activities would stop.
Restarting the Host Instance would immediately make the receive location pick up the files that were piling up in the FTP folder, and everything would work as expected for some time again. But only for a while. After a few days the same situation would occur.

I never managed to find an actual fix for this problem, but I eventually did find out that the clients UNIX OS was not on the list of supported operating systems for the BizTalk FTP adapter (http://support.microsoft.com/kb/841478). Our client was running SCO.
There is a fix for a problem with similar symptoms concerning IBM AIX based FTP servers (http://support.microsoft.com/kb/932886), but we never tried installing that, as we chose a completely different approach: Windows Services for UNIX (SFU).