Distributing SOA Information

As you might have guessed from the name of my blog, I have a long-term love of distributed applications. My infatuation with the technology actually goes back to earlier forms of COM+ and Web services. I believe that a well designed distributed application can be used to address the scalability, reliability and even identity issues that spring up in most large scale business applications. The biggest problem with designing distributed application is knowing which of the many available technologies is the best choice for the situation.

This is the reason that I was looking forward to the release of the Windows Communication Foundation (WCF). If nothing else, WCF provided a common interface to the multiple technologies used to build distributed applications. Well, WCF has been released for a few months now (and was actually in a 'go live' state for a lot longer), which means that interest in how it can be used in real-life is growing. To help people learn and use this very cool technology, ObjectSharp is introducing a new course on the best practices surrounding WCF. The course is being developed by Peter Madziak, with more information about the content and thinking behind the course found here. If you have any interest in distributed applications in general and WCF at all, you owe it to yourself to check out the course description.

Java, .NET, Web Services and Enums

While working on getting a Java Web service and a .NET Web service client to talk to one another, I ran into an interesting situation. The problem had to do with the WSDL being produced by the Java service. Actually, the entire process involved the following steps:

  • An interface written in C# was used to generate a WSDL file.
  • That WSDL file was imported into JDeveloper and a web service was created
  • The WSDL file exposed by the JDeveloper web service was used (through the wsdl.exe tool) to create a proxy class to be used by a .NET client.

The problem was caused by enumerations being used in the interface. The WSDL file generated using the C# interface included defined a separate type (with a base of string) for each enumeration and then restricted the string values for that type. However, the WSDL file exposed by the JDev web service expected that the enumerated parameters would be of type string. Not the restricted, created type that C# wants to send. The resulting type mismatch caused the requests from the .NET client to the Java web service to be rejected with an ‘unknown type’ message.

The solution, while admittedly a hack, demonstrations a little discussed features of enumerations. Consider property called Status that is declared as an enumerated type of CallStatus. I added a field called StatusString defined as below and decorated the Status property with a SoapIgnore attribute as follows:

[SoapElement(“Status”)]
public string StatusString
{
   get { return Enum.GetName(typeof(CallStatus), status); }
   set { status = (CallStatus)Enum.Parse(typeof(CallStatus), value); }
}

[SoapIgnore()]
public CallStatus Status
{ … }

The SoapIgnore attribute hides the ‘real’ Status property from the SOAP serialization process. Instead the StatusString property, which is used to convert enumerated values to and from a string, is marked as being the ‘Status’ from the perspective of SOAP serialization. One item that may or may not be a problem is that the assigned value of StatusString could be null. This isn’t considered as part of this example, as the Web service was under a compulsion to return a valid value. But if the field is nilable, then you would need to code for that in the StatusString setter.

 

Upgrading to WSE 3.0

If you weren’t aware, the version of WSE 3.0 built against the release version of Visual Studio was released on the Nov 7. I’m sure that it would have received launch parties and wide mention in blogs were it not for the conflicting launch of Visual Studio .NET, SQL Server 2005 and BizTalk 2006. :)

If you did any work with the CTP versions of WSE or if you are upgrading from WSE 2.0, there is one thing you should definitely be aware of. Specifically, I had created a WSE policy that use Anonymous over Certificate security. It was working in the CTP version. Then I upgraded to the release version. All of a sudden, I received the following error message on the client side:

WSE910: An error happened during the processing of a response message, and you can find the error in the inner exception. You can also find the response message in the Response property.

The inner exception was an InvalidOperationException with a Message of:

Security requirements are not satisfied because the security header is not present in the incoming message.

After a fair bit of digging, I determined that this message is actually a “can’t validate the user’s credentials” message. But the real cause (because, after all, I was still sending the same credentials that I did prior to upgrading) was a little more subtle. In order for the WSE functionality to work in 3.0, a new element needs to be added to the web.config of the service.

<system.web>
   <webServices>
      <soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
   </webServices>
</system.web>

When this tag gets added, all of a sudden the message went away. To be fair, this tag is documented as one of the changes between WSE 2.0 and 3.0. What surprised me is that it appears to also be one of the changes between the earlier CTP versions of WSE. Hopefully this post will help others avoid my not-so-brief struggle.

Toronto Code Camp Registration Opens

The rumours have been swirling. Now the truth is out.

On Sat. Jan 14, there will be a Toronto Code Camp. You can register/find more infomation/hang out at http://www.torontocodecamp.com/

If you're a developer looking for in-depth content from the people who know (that would be other developers), then the code camp is the place to be. If you're a developer that has in-depth content that other developers could use, this is you're chance to shine. Regardless, it will be a blast. Clear your schedule now to be there.

The end of Begin/End

While on my way back from the MVP Summit, I was playing around with some of the things I had discovered about VS 2005. I mean, if I was going to drip geekiness for the entire conference, why not extend it to the absolute limit. And what I found was something mildly disturbing.

A pet peeve of mine for a while has been how easy it is to make an asynchronous Web service call. Whether the caller knows it or now, that call actually makes your application multi-threaded. For the simplest case, that’s fine. But when you’re making the call from a Windows form application and need to update the user interface with the results of the Web method call, you are getting into an area of complexity that’s more complicated than you realize. Ask any decent developer what the hardest time of bug to crack is and invariably you’ll get ‘race conditions’, ‘deadlocks’ or just the generic ‘multiple threads’ back as the answer. And you have entered that realm unknowingly.

For VS 2005, Microsoft took my complaint and said ‘hey…if updating the UI is soooooo hard, we should make it easier’. Not what I had in mind, trust me. Ask me about a /nomultithread default compiler switch and you’ll be closer. So now instead of calling BeginHelloWorld and EndHelloWorld, it is possible to call HelloWorldAsync and create an event handler for HelloWorldCompleted. Yes, it’s a familiar model. And, as it turns out, HelloWorldCompleted actually fires on the main UI thread, so that ugly MethodInvoker stuff no longer needs to be understood.

But along with changing this asynchronous model, Microsoft also eliminated the Begin/End versions of the methods. Which means if you need to do something like a fork/join pattern, you can’t. Just so that we’re clear, a fork/join would have previously consisted of:

  IAsyncResult ar = ws.BeginHelloWorld(null, null);

  // Do some stuff in parallel with the web service call

  string result = ws.EndHelloWorld(ar);

Because of how EndHelloWorld works, the main thread will block until the background thread has completed. And if the background thread finishes first, processing will continue normally. This is a very common approach if you’re web page were to fire off an asynchronous call to a Web service and wanted to include the results on a page being returned to the client.

As I was saying, since the Begin/End methods are no longer included in the proxy class, this pattern (at least as I have outlined it) is no longer possible. And to replicate the pattern using the event handler model is non-trivial. So my solution was to take the class generated by WSDL (or by adding a Web reference) and putting back in the Begin/End methods that I need. The basic structure is:

  public IAsyncResult BeginHelloWorld(AsyncCallback callback, object asyncState)
  {
   return this.BeginInvoke("HelloWorld", new object[0], callback, asyncState);
  }

  public string EndHelloWorld(IAsyncResult ar)
  {
   object[] results = this.EndInvoke(ar);
   return ((string)(results[0]));
  }

The second parameter on the BeginInvoke call is an array of objects representing the parameters to HelloWorld, so if you’re doing this for a method that takes parameters, you’ll need to change the dimension of the object array and initialize it appropriately.

 

The floodgates are...well...beginning to open

From a couple of different sources, I'm seeing that the first set of documentation for Indigo is now available at http://winfx.msdn.microsoft.com.  And, as Andy Milligan suggests, the implication is that the bits for Indigo can't be far behind. Personally, my mouse is poised over the MSDN download page.  The rest of you probably have a life. ;)

Caching and Unit Tests

We've been playing with the Caching Application Block here at the client I'm currently working with and have found a couple of important items that will be of interest to anyone doing the same. I should say that we're using NUnit to run our unit tests, so some of the information applies specifically to that. 

Actually, both of the items we ran into had to do with the storage mechanism that we used.  The Caching Application Block includes implementations for three separate modes:  in process, memory-mapped files and SQL Server.  These three modes basically mirror the functionality available with the Cache object in ASP.NET. 

For all of the tests run to this point in the project, we had been using the in-process mode both in our unit tests and in the builds that have been sent to the system verification team.  However we recently made the choice to share the caching across web services, so we switched to the memory-mapped file mode. 

Oops. 

First off (and it should have been obvious), there is a different serialization technique used with memory-mapped files.  That is to say, that the in-process cache doesn't use serialization at all.  The memory-mapped version does serialize and deserialize the object as part of the default processing.  This change in caching mechanism should have caused us to go back to our unit tests, updating the storage type used there.  A couple of issues might very well have been exposed.  But after just a couple of minutes of seeing unexpected errors occur in unusual places, we did just that.

Second oops.

If you didn't realize it, NUnit depends a great deal on the AppDomain model to work its magic.  This allows things like the config file to be taken from the DLL's home directory.  A completely new AppDomain is created for each run of the tests.  So, as a for instance, you had created an in-process cache in one test, that cache wouldn't be there the next time the test was run.  New AppDomain = new memory = no old variables.

But what if you were to change the storage mechanism to a memory mapped file.  A mechanism that is specifically designed to share data across AppDomains.  So now, NUnit does its AppDomain creation thing and pow!  Cached value already exists.  Imagine our surprise.  Imagine how good you feel not having to go through it.

As a pointer, using the Flush method in the TestSetup section of NUnit is a good way to avoid this problem in the future.  Just something for you to consider.

Improving the Performance of Asynchronous Web Service Calls

Notice that the name of this post doesn't say that web service performance can be improved through asynchronous calls.  That is on purpose.  This particular post deals with a limitation that impacts applications that utilize async web service methods.  Actually, it has the potential to impact any application that interacts with the Internet.  This is actually one time I wish my blog was more widely read, because I can pretty much guarantee that there are thousands of developers who are unaware that the nice async design they've implemented isn't having the performance boosting effect that they expected.  And thanks to Marc Durand for pointing this out to me.

The limitation I'm talking about is one that is buried in the HTTP/1.1 specification (RFC2616).  The spec says that, to prevent a single computer from overrunning a server, the limit to the maximum number of connections that can be made to a server is two.  What this means is that if your application makes three async calls to the same server, the third call will be blocked until one of the first two is finished.  I know that this came as a big surprise to me.

Fortunately, there is a configuration setting that can adjust this number without requiring any coding changes.  In the app.config (or machine.config) file, add a connectionManagement tag.  Within connectionManagement, the add tag is used to specify the optional server and the maximum connections allowed.  The following example allows up to 10 simultaneous connections to be made to 216.221.85.164 and 40 to any server.

<configuration>
  <system.net>
    <connectionManagement>
      <add address="216.221.85.164" maxconnection="10" />
      <add address="*" maxconnection="40" />
    </connectionManagement>
  </system.net>
</configuration>

For those who like to program, you can accomplish the same behavior on a temporary basis using the ServicePointManager.DefaultConnectionLimit property.  But I was never big into adding code when I didn't have to.

FileNotFoundException in ASP.NET Web Services

As you work with web services in ASP.NET, it is likely that you will eventually come upon a weird file not found exception.  The actual text of the exception will look something like “File or assembly name jdiw83ls.dll, or one of its dependencies, was not found".  Now, since it unlikely that you have a project with a name of jdiw84ls in your solution, the source of this exception and it's resolution will be hard to see.

To understand where the message is coming from requires a little detail about how ASP.NET services moves complex objects across its boundary.  If you pass a complex object to a web service, the client side serializes the class into an XML document.  On the receiving side (the server), the inbound XML document is deserialized back into a class.  This knowledge is part of Web Services 101.

However, what happens when the class

<configuration>
    <system.diagnostics>
         <switches>
            <add name="XmlSerialization.Compilation" value="4"/>
         </switches>
    </system.diagnostics>
</configuration>

 

Web Services and Proxy Servers

I'm currenting working with a team that is putting the finishing touches on a commercial application that uses web services as a major component of the infrastructure.  As part of putting the client portion through its paces, an environment that included a proxy server was tested.  The initial result was not surprising to anyone who has significant experience with web services:  a connection could not be made exception was thrown. The reason for this problem is that the method for defining a proxy server to the web service proxy class on the client side is a little unexpected.  And I apologize in advance for having to use the same word (proxy) to describe to separate items (the server and the web service class). 

If you are running Internet Explorer, then the place where the the proxy server settings are configured is in the Tools | Internet Options dialog.  Within the dialog, click on the Connections tab and the LAN Settings button.  Here you can specify whether proxy server settings are required and which server and port are used.  You can also identify whether local addresses are exempt from the proxy process.  This is fairly well known information, especially if you normally operate from behind a proxy server.

The disconnect occurs when you make calls to web services from this same machine.  Under the covers, the HttpWebRequest class is used to transmit the call to the desired server.  However, even when the proxy server information has been specified as just described, those details are NOT used by HttpWebRequest.  Instead, by default, no proxy is used to handle the request.  This is what causes the connection exception. I know the first time I ran into this issue was a surprise to me.

There are two possible solutions to this problem.  The first is to assign a WebProxy object to the Proxy property on the web service proxy class.  You can programmatically specify the proxy server information, but that is very difficult to modify.  Instead of creating the WebProxy object on the fly, use the GetDefaultProxy static method on the System.Net.WebProxy object.  This method reads “the nondynamic proxy settings stored by Internet Explorer 5.5” and returns them as a WebProxy object that can be assigned to the Proxy property .  This technique works fine assuming that your client has IE installed and that none of the scripts run at login time have modified the proxy settings.

There is an alternative that is a little more flexible.  There is a app.config element called defaultProxy that is part of the System.Net configuration section.  Within this element, the details of the proxy server can be specified independently of the IE settings.  The basic format of the defaultProxy element can be seen below.

<system.net>
   <defaultProxy>
      <proxy
         proxyaddress = "http://proxyserver:80"
         bypassonlocal = "true"
      />
   </defaultProxy>
</system.net>

The proxy element also includes an attribute called usesystemdefault which, when set to true, causes the IE settings to be used.  The benefit of this approach is that no additional coding is required.  The settings defined in defaultProxy are use by HttpWebRequest (and, therefore, web service calls) with no change to the application required.

As an added benefit, this element can be added to machine.config, which allows it to be applied to every HttpWebRequest made from the client machine regardless of the application.  Keeping in mind that an uneducated developer could assign the Proxy object in code, overriding this nice, easily configurable default.