tsJensen

A quest for software excellence...

ServiceWire and ServiceMq Improvements

Over the past several days, I’ve been working on a day-job project that may be using ServiceMq which uses ServiceWire under the covers. I say “may” because it depends on whether the prototype proves to be sufficiently reliable and efficient. The prototype is really more of an extended integration test with the following requirements:

  • Blocking Send method that throws if sending fails.
    • Tries the primary destination first.
    • Alternative destinations are tried successively until the message is successfully sent.
    • Control over send connection timeout failure to enable “fail fast.”
  • Standard caching receive.

This is because the senders are transient and may not be restarted should they fail. The sender’s also need immediate feedback because the action is part of a transaction involving other operations.

The first order of business was to add the Flash class to ServiceMq. This evolved to become the Flasher class which implements IDisposable in order to take advantage of client connection pooling using the updated PooledDictionary class in ServiceWire (more on this later). The Flasher’s Send method allows you to send a message to a primary destination with zero to many alternate destinations.

[TestMethod]
public void FlashDestDownTcpTest()
{
   var qfrom = new Address(Dns.GetHostName(), 8966);
   var q1Address = new Address(Dns.GetHostName(), 8967);
   var q2Address = new Address(Dns.GetHostName(), 8968);

   // create and use Flasher in using to guarantee Dispose call
   using (var flash = new Flasher(qfrom))
   {
      // create a receiving queue
      using (var q2 = new MessageQueue("qf2", q2Address, @"c:\temp\qf2"))
      {
	     // send to primary which does not exist - received on secondary q2
         var id = flash.Send(q1Address, "my test message", q2Address);
         var msg = q2.Receive();
         Assert.IsTrue(msg.Id == id);
      }

      using (var q1 = new MessageQueue("qf1", q1Address, @"c:\temp\qf1"))
      {
	     // send to primary - received on primary
         var id = flash.Send(q1Address, "my test message", q2Address);
         var msg = q1.Receive();
         Assert.IsTrue(msg.Id == id);
      }

	  // demonstrate Send throws when neither receiver is "up"
      try
      {
         var id = flash.Send(q1Address, "my test message", q2Address);
      }
      catch (Exception e)
      {
         Assert.IsTrue(e is System.Net.WebException);
      }
   }
}

In order to support a more robust client side connection timeout, a significant improvement was made to ServiceWire. The TcpEndPoint class was introduced and an overloaded constructor was added to TcpChannel which allows you to specify a connection timeout value when creating an instance of TcpClient<T> (see below). This involved use of the Socket class’s ConnectAsync method with a SockeAsyncEventArgs object.

private void Initialize(Type serviceType, 
   IPEndPoint endpoint, int connectTimeoutMs)
{
   _serviceType = serviceType;
   _client = new Socket(AddressFamily.InterNetwork, 
                        SocketType.Stream, ProtocolType.Tcp);
   _client.LingerState.Enabled = false;

   var connected = false;
   var connectEventArgs = new SocketAsyncEventArgs
   {
      // must designate the server you want to connect to
      RemoteEndPoint = endpoint
   };
   connectEventArgs.Completed 
      += new EventHandler<SocketAsyncEventArgs>((sender, e) =>
         {
            connected = true;
         });

   if (_client.ConnectAsync(connectEventArgs))
   {
      //operation pending - (false means completed synchronously)
      while (!connected)
      {
         if (!SpinWait.SpinUntil(() => connected, connectTimeoutMs))
         {
            if (null != _client) _client.Dispose();
            throw new TimeoutException("Unable to connect within " 
                                       + connectTimeoutMs + "ms");
         }
      }
   }
   if (connectEventArgs.SocketError != SocketError.Success)
   {
      if (null != _client) _client.Dispose();
      throw new SocketException((int)connectEventArgs.SocketError);
   }

   if (!_client.Connected) throw new SocketException(); 
   _stream = new BufferedStream(new NetworkStream(_client), 8192);
   _binReader = new BinaryReader(_stream);
   _binWriter = new BinaryWriter(_stream);
   SyncInterface(_serviceType);
}

The final problem to solve was TCP/IP port exhaustion. My original implementation had the sending client being created and taken down with each call to the Send method. The construction overhead is minimal but the connect time and the port exhaustion problem quickly becomes a problem where there are potentially many threads sending messages from the same client machine.

To solve the problem, I used a connection pooling strategy that involved making the PooledDictionary<TKey, TValue> implement the IDisposable interface to allow for easy disposal of pooled client objects. The Send method then uses one of two client pools, depending on whether it is a local Named Pipes connection of a TCP connection.

private void SendMessage(OutboundMessage message)
{
   NpClient<IMessageService> npClient = null;
   TcpClient<IMessageService> tcpClient = null;
   IMessageService proxy = null;
   var poolKey = message.To.ToString();
   try
   {
      // determine whether to use NamedPipes or Tcp
      var useNpClient = false;
      if (message.To.Transport == Transport.Both)
      {
         if (message.To.ServerName == message.From.ServerName)
         {
            useNpClient = true;
         }
      }
      else if (message.To.Transport == Transport.Np) useNpClient = true;

	  // requet a client from the pool, providing a way to create a new one
      if (useNpClient)
      {
         npClient = npClientPool.Request(poolKey, 
            () => new NpClient<IMessageService>(
               new NpEndPoint(message.To.PipeName, _connectTimeOutMs)));
         proxy = npClient.Proxy;
      }
      else
      {
         tcpClient = tcpClientPool.Request(poolKey,
            () => new TcpClient<IMessageService>(new TcpEndPoint(
               new IPEndPoint(IPAddress.Parse(message.To.IpAddress), 
                  message.To.Port), _connectTimeOutMs)));
         proxy = tcpClient.Proxy;
      }

	  // send the message via the proxy RPC Enqueue* method
      if (null == message.MessageBytes)
      {
         proxy.EnqueueString(message.Id, message.From.ToString(), 
		    message.Sent, message.SendAttempts,
            message.MessageTypeName, message.MessageString);
      }
      else
      {
         proxy.EnqueueBytes(message.Id, message.From.ToString(), 
		    message.Sent, message.SendAttempts,
            message.MessageTypeName, message.MessageBytes);
      }
   }
   finally
   {
      if (null != tcpClient) tcpClientPool.Release(poolKey, tcpClient);
      if (null != npClient) npClientPool.Release(poolKey, npClient);
   }
}

It remains to be seen whether these changes will result in a sufficiently robust message passing and queuing system to allow it to be used on my day job project. More testing and prototyping is required. There are alternatives to which I can fall back, but none of them are trivial and all of them are less desirable. Given my personal bias, I must take extra care to scrutinize this possible solution and abandon it should it prove to be insufficient.

BufferedStream Improves .NET Sockets Performance

.NET’s BufferedStream saved the day, instantly reducing 200-400ms operations across the wire to 1ms. Why? Simple answer, the Socket class returns a NetworkStream. Wire up that stream to a StreamWriter and a StreamReader, and you’re good to go, right? Wrong. Turns out the StreamWriter and StreamReader have a default 16 byte read/write buffer. And NetworkStream has none.

So if you have a TCP socket wired up to a NetworkStream, you’re trying to send or receive just 16 bytes at a time, utterly killing performance over TCP. Now magically wrap that NetworkStream into a BufferedStream and pass that BufferedStream into your StreamReader and StreamWriter and you get instant performance gains that will knock your sockets off.

Backstory: For months I’ve been writing and improving my DuoVia.Net fast services library. And recently the my day job’s team began using it some very clever ways (sorry, NDA and all), but we ran into a major performance problem. While performance on the same machine across processes using Named Pipes was excellent, the same was not true of machine-to-machine communications over TCP/IP. Sub-millisecond calls between services were taking 200-400ms across the wire. Something was terribly wrong. And when we tried Named Pipes from server to server, the performance problem went away. Of course, this was not the final answer because a .NET Named Pipes host can only handle 254 concurrent connections and we need to be able to scale beyond that.

Solving the problem required several sleepless nights and a weekend searching for the answer. My tests for TCP/IP with respect to performance have always run locally on the localhost loopback stack. The trouble with that, I have since learned (and should have known), is that when running locally, the Windows TCP stack bypasses the TCP stack altogether, or nearly so—sufficiently at least to mask the underlying problem of reading and writing only 16 bytes at a time directly on the NetworkStream.

After examining a number of open source implementations of Sockets on a server host, I ran into one or two smart enough to be using the BufferedStream to wrap that NetworkStream that a raw Socket object gives you. While doing all of this research, I also ran into the MSDN explanation (see Remarks and Example section) of how to improve server side asynchronous Socket handling. So I threw that into the solution as well. Once wired up and tested across machines on my home network, I breathed a huge sigh of relief. And here is what the code looks like now. First server and then client.

using System;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DuoVia.Net.TcpIp
{
  public class TcpHost : Host
  {
    private Socket _listener;
    private IPEndPoint _endPoint;
    private ManualResetEvent _listenResetEvent = new ManualResetEvent(false);

    /// <summary>
    /// Constructs an instance of the host and starts listening for 
		/// incoming connections on any ip address.
    /// All listener threads are regular background threads.
    /// </summary>
    /// <param name="port">The port number for incoming requests</param>
    /// <param name="log"></param>
    /// <param name="stats"></param>
    public TcpHost(int port, ILog log = null, IStats stats = null)
    {
      Initialize(new IPEndPoint(IPAddress.Any, port), log, stats);
    }

    /// <summary>
    /// Constructs an instance of the host and starts listening for incoming 
		/// connections on designated endpoint.
    /// All listener threads are regular background threads.
    /// 
    /// NOTE: the instance created from the specified type 
		/// is not automatically thread safe!
    /// </summary>
    /// <param name="endpoint"></param>
    /// <param name="log"></param>
    /// <param name="stats"></param>
    public TcpHost(IPEndPoint endpoint, ILog log = null, IStats stats = null)
    {
      Initialize(endpoint, log, stats);
    }

    private void Initialize(IPEndPoint endpoint, ILog log, IStats stats)
    {
      base.Log = log;
      base.Stats = stats;
      _endPoint = endpoint;
      _listener = new Socket(AddressFamily.InterNetwork, 
			  SocketType.Stream, ProtocolType.Tcp);
      _listener.SetSocketOption(SocketOptionLevel.Socket, 
			  SocketOptionName.KeepAlive, true);
      _listener.SetSocketOption(SocketOptionLevel.Socket, 
			  SocketOptionName.DontLinger, true);
    }

    /// <summary>
    /// Gets the end point this host is listening on
    /// </summary>
    public IPEndPoint EndPoint
    {
      get { return _endPoint; }
    }

    protected override void StartListener()
    {
      Task.Factory.StartNew(Listen, TaskCreationOptions.LongRunning);
    }

    private SocketAsyncEventArgs _acceptEventArg;

    /// <summary>
    /// Listens for incoming tcp requests.
    /// </summary>
    private void Listen()
    {
      try
      {
        _listener.Bind(_endPoint);
        _listener.Listen(8192);

        _acceptEventArg = new SocketAsyncEventArgs();
        _acceptEventArg.Completed 
				  += new EventHandler<SocketAsyncEventArgs>
					   (acceptEventArg_Completed);

        while (!_disposed)
        {
          // Set the event to nonsignaled state.
          _listenResetEvent.Reset();
          _acceptEventArg.AcceptSocket = null;
          try
          {
            if (!_listener.AcceptAsync(_acceptEventArg))
            {
              AcceptNewClient(_acceptEventArg);
            }
          }
          catch (Exception ex)
          {
            _log.Error("Listen error: {0}", 
						  ex.ToString().Flatten());
            break; //break loop on unhandled
          }

          // Wait until a connection is made before continuing.
          _listenResetEvent.WaitOne();
        }
      }
      catch (Exception e)
      {
        _log.Fatal("Listen fatal error: {0}", e.ToString().Flatten());
      }
    }

    private void acceptEventArg_Completed(object sender, 
		  SocketAsyncEventArgs e)
    {
      AcceptNewClient(e);
    }

    private void AcceptNewClient(SocketAsyncEventArgs e)
    {
      try
      {
        if (e.SocketError != SocketError.Success)
        {
          if (!_disposed) _listenResetEvent.Set();
          return;
        }

        Socket activeSocket = null;
        BufferedStream stream = null;
        try
        {
          activeSocket = e.AcceptSocket;

          // Signal the listening thread to continue.
          _listenResetEvent.Set();

          stream = new BufferedStream
					  (new NetworkStream(activeSocket), 8192);
          base.ProcessRequest(stream);
        }
        catch (Exception ex)
        {
          _log.Error("AcceptNewClient_ProcessRequest error: {0}", 
					  ex.ToString().Flatten());
        }
        finally
        {
          if (null != stream)
          {
            stream.Close();
          }
          if (null != activeSocket && activeSocket.Connected)
          {
            try
            {
              activeSocket.Shutdown(SocketShutdown.Both);
            }
            catch (Exception shutdownException)
            {
              _log.Error("AcceptNewClient_ActiveSocketShutdown error: {0}", 
							  shutdownException.ToString().Flatten());
            }

            try
            {
              activeSocket.Close();
            }
            catch (Exception closeException)
            {
              _log.Error("AcceptNewClient_ActiveSocketClose error: {0}", 
							  closeException.ToString().Flatten());
            }
          }
        }
      }
      catch (Exception fatalException)
      {
        _log.Fatal("AcceptNewClient fatal error: {0}", 
				  fatalException.ToString().Flatten());
      }
    }

    #region IDisposable Members

    private bool _disposed = false;

    protected override void Dispose(bool disposing)
    {
      if (!_disposed)
      {
        _disposed = true; //prevent second call to Dispose
        if (disposing)
        {
          _listenResetEvent.Set();
          _acceptEventArg.Dispose();
          _listener.Close();
          _listenResetEvent.Close();
        }
      }
      base.Dispose(disposing);
    }

    #endregion
  }
}

Client code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace DuoVia.Net.TcpIp
{
  public class TcpChannel : StreamingChannel
  {
    private Socket _client;

    /// <summary>
    /// Creates a connection to the concrete object handling 
    /// method calls on the server side
    /// </summary>
    /// <param name="serviceType"></param>
    /// <param name="endpoint"></param>
    public TcpChannel(Type serviceType, IPEndPoint endpoint)
    {
      _serviceType = serviceType;
      _client = new Socket(AddressFamily.InterNetwork, 
        SocketType.Stream, ProtocolType.Tcp);
      _client.LingerState.Enabled = false;
      _client.Connect(endpoint);
      if (!_client.Connected) throw new SocketException(); 
      _stream = new BufferedStream(new NetworkStream(_client), 8192);
      _binReader = new BinaryReader(_stream);
      _binWriter = new BinaryWriter(_stream);
      _formatter = new BinaryFormatter();
      SyncInterface(_serviceType);
    }

    public override bool IsConnected 
    { 
      get 
      { 
        return (null != _client) && _client.Connected; 
      } 
    }

    #region IDisposable override

    protected override void Dispose(bool disposing)
    {
      base.Dispose(disposing);
      if (disposing)
      {
        _binReader.Close();
        _binWriter.Close();
        _client.Close();
      }
    }

    #endregion
  }
}

You can find all of the ServiceWire code on GitHub or install the package from NuGet.

Making Distributed Computing Relevant and Accessible

First, let us assume that distributed computing is generally that area of developing and running software designed to process large numbers of long running tasks on servers that are optimally proximal to the data being processed.

Second, let us agree, if for this discussion only, that distributed computing is NOT your collection of services on back end servers that support your service oriented architecture (SOA) for your web and mobile apps.

Third, let us presume that you are NOT already blessed with a job where you write distributed computing software.

How then can distributed computing be relevant to you? And how can you take advantage of distributed computing without becoming an expert in one of the several well known distributed computing platforms on the market today?

Both are excellent questions. Thank you for asking. Let’s try a practical approach.

Imagine you are at your desk and your boss comes to you and ask how fast your web servers respond to the customer. Of course, your first instinct is to write this program to find out:

private static void DoTenUrlsInParallel()
{
   Console.WriteLine("Do 10 urls in parallel");
   var sw = Stopwatch.StartNew();
   ISpeedTest test = new SpeedTest();
   Parallel.ForEach(TestUrls, (url) =>
   {
      var result = test.GetSpeed(url);
      Console.WriteLine("r:{0}, s:{1}, b:{2}, u:{3}",
         result.ResponseTimeMs, result.ReadStreamTimeMs, 
         result.ResponseLength, result.Url);
   });
   sw.Stop();
   Console.WriteLine("Total elapsed time: {0}", 
      sw.ElapsedMilliseconds);
   Console.WriteLine(string.Empty);
}

You take him the results and he says, “But isn’t this from your desk? I want to know what these numbers look like from all around the world. East and west U.S. North and west Europe. And east and south east Asia. And I want a regular stream of these numbers fed into a spreadsheet for me every day.”

Do you say, “No problem.” You do if you have a Windows Azure account and you know about the distributed task parallel library from DuoVia called DuoVia.Net.Distributed. You go back to your desk and modify the code to look like this:

private static void DoTenUrlsThreeTimesEachAroundTheWorldInParallel(bool runLocal = false)
{
   var serverEndpoints = new IPEndPoint[0];
   if (runLocal)
   {
      serverEndpoints = new IPEndPoint[] { new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9096) };
   }
   else
   {
      //these server names are temporary - to run this test use your own
      var servers = new string[]
      {
         "myaz-westus.cloudapp.net",
         "myaz-eastus.cloudapp.net",
         "myaz-northeu.cloudapp.net",
         "myaz-westeu.cloudapp.net",
         "myaz-soeastasia.cloudapp.net",
         "myaz-eastasia.cloudapp.net"
      };

      serverEndpoints = new IPEndPoint[servers.Length];
      for (int i = 0; i < servers.Length; i++)
      {
         var host = Dns.GetHostAddresses(servers[i]);
         var ip = (from n in host 
                   where n.AddressFamily == AddressFamily.InterNetwork 
                   select n).First();
         serverEndpoints[i] = new IPEndPoint(ip, 9096);
      }
   }

   float subscriptionRate = 2.0f; //oversubscribed 
   int logPollingIntervalSeconds = 2;
   using (DistributedClient<ISpeedTest> client = 
          Distributor.Connect<ISpeedTest>(typeof(SpeedTest),
          subscriptionRate,
          logPollingIntervalSeconds,
          LogLevel.Debug,
          serverEndpoints))
   {
      for (int i = 0; i < 3; i++)
      {
         var sw = Stopwatch.StartNew();
         Console.WriteLine(@"round:{0}", i + 1);
         var loopResult = client.ForEach(TestUrls, (url, proxy) => proxy.GetSpeed(url));
         foreach (var result in loopResult.Results)
         {
            Console.WriteLine(@"r:{0}, s:{1}, b:{2}, on: {3}, u:{4}",
               result.ResponseTimeMs, result.ReadStreamTimeMs, 
			   result.ResponseLength, result.MachineName, result.Url);
         }
         sw.Stop();
         Console.WriteLine("Total elapsed time: {0}", sw.ElapsedMilliseconds);
         Console.WriteLine(string.Empty);
      }
   }
}

And you and your boss are happy.

Sometimes distributed computing is more about location and proximity to data or infrastructure than it is to getting massive amounts of data processed in as little time as possible.

You can find the full demo source code here.

DomainAspects: Aspect Oriented Programming with Castle Windsor Interceptor

Last week I released DomainAspects 2.0 without many details other than its general features. In this post and future posts, I’m going to delve into the details one area or feature at a time. My purpose is to help you understand how each piece works and provide examples of how you might use the library or the code in your own projects.

The few aspect oriented programming (AOP) languages and frameworks that I have looked at seem to me to be unwieldy and unnecessarily intrusive in the the daily workflow of an application developer, cluttering up the code and creating cumbersome dependencies on the AOP construct itself. Fortunately there is a cleaner alternative to AOP languages found in the inversion of control (IoC) containers we so commonly use for dependency injection in order to enjoy the benefits of SOLID Design: the Interceptor.

Interception is supported by many of the IoC libraries. I’ve used Unity a little but most of my experience is with Castle Windsor, so of course, I prefer Windsor. I also prefer Windsor’s interception approach because I find it easier. If you are a Unity user, take a look at Dino Esposito’s Unity Interception article on MSDN. You an see for yourself that the Unity IInterceptionBehavior implementation is relatively more complex than Windsor’s IInteceptor:

public interface IInterceptor
{
   void Intercept(IInvocation invocation);
}

In DomainAspects, I wanted my Interceptor to handle logging and exception handling, which I like to call “auditing”, probably the most common of the cross cutting concerns handled by AOP. I also wanted the Interceptor to handle authorization security. But I wanted to have a simple Interceptor class that would have its “auditor” and “authorization” dependencies injected by the same container. Each dependency would handle its specific responsibilities.

Here’s the Windsor fluent configuration code for each of these. Note the first component is the IPrincipalProvider which is a dependency of the IOperationAuthorizer implementation. I then register the components for the authorizer and the auditor. The last component configured by the DomainAspects ServiceFactory class is the OperationInterceptor.

_container.Register(
   Component.For<IPrincipalProvider>()
      .ImplementedBy(_principalProviderType)
      .Named("PrincipalProvider")
      .LifeStyle.Transient,

   Component.For<IOperationAuthorizer>()
   .ImplementedBy(_operationAuthorizerType)
   .Named("OperationAuthorizer")
   .LifeStyle.Transient,

   Component.For<IOperationAuditor>()
   .ImplementedBy(_operationAuditorType)
   .Named("OperationAuditor")
   .LifeStyle.Transient,

   Component.For<OperationInterceptor>()
   .Named("OperationInterceptor")
   .LifeStyle.Transient);

When the DomainAspects ServiceFactory’s Create method is called, if the service has not already been registered with the Windsor container, it will register the container and wrap it with the Interceptor we have just configured using Windsor’s fluent interface. Here’s the code:

_container.Register(
   Component.For(interfaceType)
   .ImplementedBy(implementedByType)
   .Named(implementedByType.Name)
   .Interceptors(InterceptorReference.ForKey("OperationInterceptor")).Anywhere
   .LifeStyle.PerThread);

Note that the .Interceptors method takes a params of InterceptorReference objects. So like Unity, you can chain interception. Unlike Unity, the chaining occurs automatically for you in sequence of the array. Your IInterceptor implementation does not require you to be concerned with wiring up the chain as does the Unity IInterceptorBehavior.

Now take a look at the relatively simple, application requirement focused OperationInterceptor class which implements the Windsor IInterceptor interface with a single method and depends on the container to inject its two dependencies. The code in the interceptor class here just handles the business case of examining the class and method being intercepted for attributes that will require action by one or both of its dependencies.

public class OperationInterceptor : IInterceptor   
{
   private IOperationAuditor auditor;
   private IOperationAuthorizer authorizer;

   public OperationInterceptor(IOperationAuditor opAuditor, IOperationAuthorizer opAuthorizer)
   {
      auditor = opAuditor;
      authorizer = opAuthorizer;
   }

   public void Intercept(IInvocation invocation)
   {
      AutoLogAttribute autoLogAttribute = null;
      AuthorizeAttribute authorizeAttribute = null;
      var methodInfo = invocation.MethodInvocationTarget;
      object invokedKey = null;
      try
      {
         //find AutoLogAttribute
         autoLogAttribute = ((AutoLogAttribute[])methodInfo
            .GetCustomAttributes(typeof(AutoLogAttribute), true))
            .FirstOrDefault();

         if (null == autoLogAttribute) //try class level
            autoLogAttribute = ((AutoLogAttribute[])methodInfo.DeclaringType
            .GetCustomAttributes(typeof(AutoLogAttribute), true))
            .FirstOrDefault();

         if (null != autoLogAttribute &&  null != auditor)
         {
            //log invocation
            auditor.LogOperationInvoked(methodInfo, 
               invocation.Arguments, 
               invocation.GenericArguments, 
               out invokedKey);
         }

         //find AuthorizeAttribute
         authorizeAttribute = ((AuthorizeAttribute[])methodInfo
            .GetCustomAttributes(typeof(AuthorizeAttribute), true))
            .FirstOrDefault();

         if (null == autoLogAttribute) //try class level
            authorizeAttribute = ((AuthorizeAttribute[])methodInfo.DeclaringType
            .GetCustomAttributes(typeof(AuthorizeAttribute), true))
            .FirstOrDefault();

         if (null != authorizeAttribute && null != authorizer)
         {
            //authorize
            authorizer.Authorize(methodInfo, invocation.Arguments, invocation.GenericArguments);
         }

         //proceed with invocation
         invocation.Proceed();
      }
      catch(Exception e)
      {
         //log exception and throw
         if (null != autoLogAttribute && null != auditor)
         {
            auditor.LogOperationException(invokedKey, methodInfo, e);
         }
         throw; //always throw to bubble up exception and preserve call stack
      }
   }
}

If you are considering aspect oriented programming or you need interception for another reason, I hope this post is helpful. If you are looking through the DomainAspects 2.0 library code, I hope this will help you understand how and why I’ve used Windsor’s IoC container and their interception facility.

DomainAspects 2.0: Aspect Oriented Library with Generic WCF Host

Would you like to just focus on your business domain and host it anywhere easily rather than fussing with infrastructure? With DomainAspects you just write the interface in a project called [MyDomain].Common and the implementation is a project called [MyDomain]. Now add a brief and easy configuration string to both client and service host and xcopy deploy. Restart your hosting service if you are using the domain remotely.

With DomainAspects, all access to the implementation is now controlled as you have specified through easy attributes on your implementation without ever writing specific code to validate and authorize. Each and every call is logged without adding any logging code. Each and every exception is logged without ever adding a try/catch block in your code. And exceptions are captured, logged, and thrown up the chain to the client.

Introducing the 2.0 version of DomainAspects. This new version contains some major changes, the chief among them is the introduction of a WCF host container that allows you to access your aspect oriented domain layer remotely. More on the changes and features later, but first, let’s review what has come before and contributed to this new release:

And some earlier posts that have formed the creation of the WCF host in this new version:

DomainAspects 2.0 Introduced Today

Over the last couple of months, I’ve spend considerable time on the weekends to complete the idea of merging my previous work on a generic WCF host into my DomainAspects project. Since I had not touched either of these projects for some time, it was fun and interesting to look at them from a new perspective. There are many changes for the better here. Please download it and give it a try. I am eager to hear your feedback.

New in DomainAspects 2.0

Today, I’m releasing DomainAspects 2.0 which supports the following new features:

  • A WCF host service for accessing domain services running in another process or server with the following features/benefits:
    • Fast and encrypted net.tcp binding with Windows permissions.
    • Simplified custom configuration section that is the same on client and server.
    • Custom instance provider uses the DomainAspects service factory and Windsor for instance creation and release.
    • Ability to specify service instance lifestyle closely matching Windsor (PerThread, Pooled, Singelton, SingleCall).
    • Service host that will run in console mode for easy debugging.
    • Flip a config switch and install the service host as a windows service. No recompile required.
    • RemoteClient implements IDisposable correctly, dealing with Abort vs Close for you.
    • Host can be configured to use a fake PrincipalProvider for easily testing a variety of user roles and combinations.
    • Reliance on DomainAspects for authorization rather than configured local Windows groups.
  • A light remote client assembly allows access DomainAspects with minimal deployment requirements.
  • Local client and remote client both return an instance of the service interface, allowing a domain to be moved to another process or remote server with minimal changes to client code.
  • Upgrade to the current stable release Castle Windsor 3.0 container libraries.
  • Improved domain service factory allows greater instance creation control.
  • Additional tests, including multi-threaded remote tests focusing on instance creation and pooling.
  • More intuitive, self-describing classes to make understanding the code easier.

Using DomainAspects 2.0

Using the DomainAspects solution is easy. You must have Visual Studio 2010 Pro or higher. If you do not, you may spend considerable time trying to get it running. I would not recommend it.

Download the code and make sure you right click the zip file and go to properties and unlock the zip file before you extract it.

To run remote tests, be sure to start the DomainAspects.Host without debugging first. I recommend running the MultiRemoteTests class using a multiple project startup with the host running first and the DomainAspects.TestConsole running the test rather than the automated tests runner since I have not found a way to get those tests to run properly within the test harness.

Now run the tests. Watch the host console as the MultiRemoteTests run. Note the instance creation on second and third run take zero time because these instances have been pooled.

When you are ready to build your own domain service, just follow the examples in the TestDomain and TestDomain.Common projects. Configure the host and the client as shown in the app.config files in the included projects appropriately to match your new domain and domain.Common assemblies.

If you are going remote, build and deploy the DomainAspects.Host. Make sure you switch the “consoleMode” attribute in the config on the server side to “Off” so that it will install and run as a service.

Download DomainAspects20.zip (2.10 mb)

Learning from the Elevator State Machine Programming Test

In a recent job interview I was asked to build an elevator simulator. I was given the weekend to do it. I had never written a state machine before. It wasn't perfect but it passed all the tests I could come up with based on my own assumptions about the rules of behavior based on the following text from the interviewer:

Build an elevator simulator. It should have a UI that shows 5 floors, with the call buttons for each floor. The UI should also show the panel of buttons inside the elevator. As a user, I can press any floor call button (up or down), as well as elevator panel buttons to move the elevator. The elevator should move at a realistic speed (not just go instantaneously to the desired floor).

Evaluation criteria:

  1. Accuracy of the elevator state machine with various button-press scenarios.
  2. The object design of your project – how you organize the design into classes and their relationships, what design patterns you choose to use.
  3. Coding style and clarity.
  4. The UI doesn’t need to be fancy, but it needs to enable the functional requirements stated above. You can use any UI toolkit of your choice.
  5. The code should be written in C#.

Unfortunately, my assumptions were not the same as the evaluation team's assumptions, so they found some "bugs" in the behavior of my elevator. Honestly, I was not surprised. In fact, when I submitted the code, I had offered the following observations:

I did not spend much time refactoring or documenting, so you're getting to see the "first draft" of the code.

Some refactoring that I would do:

1. Create tighter assurances in the tests with required sequence of logged events rather. In running the tests, I took a shortcut and debugged through the tests to review the log entries from the state machine to verify the sequence of actions. This should be corrected.

2. Clean up each of the two state machines, AtFloor and Moving. To simplify, I might create one or two more state machine classes to make the logic rules easier to follow and remove some of the "if" fall through logic states.

3. Tighten up UI with view data model to reduce the clutter in the code or perhaps even rewrite the UI in WPF with an MVVM architecture. My choice of Windows Forms was based on time limitations and my limited experience with WPF.

4. Review and tighten up naming and coding conventions for improved readability.

The "bug" in the elevator was not the reason I did not get the job. Fortunately, the recruiter sent me the feedback she received from the interview team. This is rare. I found it helpful and will certainly take it into account in the future.

The positive and exciting thing about this entire experience was having a reason to write my first state machine in a fun exercise which I want to share with you here. This was certainly the most comprehensive programming test I've ever been given in conjunction with an interview. I applaud the employer for having such a thorough and extensive evaluation process. And I thank the interview team for their feedback. Such thoroughness really helps to determine whether a person will be a good fit for the team. And above all else, that fit is of paramount importance.

Please download the code and let me know what you think. There are clearly flaws, as I would expect of any code thrown together over a weekend, especially where the particular pattern being implemented is a first attempt. When I have time, I may want to pull this off the shelf and do the refactoring I suggested when I submitted the code. But first, I need to find an employer and settle down. I think that will happen soon.

ElevatorControl.zip (29.94 kb)

Moved from dasBlog to BlogEngine.NET

I bit the bullet today and moved from dasBlog to BlogEngine.NET after having upgraded my hosting account to .NET 4.0 and having way too many problems with my dasBlog install. I just exported the dasBlog content to BlogML.There are multiple posts about doing this.

The only thing I changed was the Global.asax code to create a permanent redirect for my dasBlog links out in the world to the BlogEngine.NET links using the following:

void Application_BeginRequest(object source, EventArgs e)
{
   HttpApplication app = (HttpApplication)source;
   HttpContext context = app.Context;
    
   // Attempt to perform first request initialization
   FirstRequestInitialization.Initialize(context);

   //redirect to ~/post/2012/03/30/DomainAspects+Inject.aspx
   //when url is ~/2012/03/30/DomainAspects+Inject.aspx
   if (context.Request.Url.AbsolutePath.EndsWith(".aspx"))
   {
      Match m = dateRegex.Match(context.Request.Url.AbsolutePath);
      if (m.Success)
      {
         string url = context.Request.Url.AbsolutePath;
         string dt = m.ToString();
         url = url.Replace(dt, @"/post" + dt);
         context.Response.RedirectPermanent(url, true);
      }
   }
}

static Regex dateRegex = new Regex(@"(?<!/post)/\d{4}/\d{1,2}/\d{1,2}/");

DomainAspects: Inject Fake PrincipalProvider and Avoid Fake HttpContext for Testing

Today I began playing with the DomainAspects project again and realized that my tests were breaking when I switched to the .NET 4.0 Framework. After a little research, it became clear. My test helper class in the previous version of DomainAspects committed a Class A coding misdemeanor. It relied on reflection to set the value of a private member on object returned by an internal method in the Thread class.

In my own defense, I did not write that code. I borrrowed it from somewhere online to allow me to set the HttpContext even when there really isn't one available when I run my tests. This was clearly bad form and came back to bite me. So I decided to eliminate the need and just added a facility in my DomainFactory class to substitute one or more of the Windsor components used by the DomainFactory.Create<T> method which is wrapped in an IDisposable via the DomainProxy<T> class being used in the tests.

Here is the simple addition to the DomainFactory. Note that we must remove these components in reverse order and then add them back since there are dependencies involved. Also note that this method will fail if you have already created an instance of a domain interface using the proxy or factory class.

/// <summary>
/// Replaces default aspect oriented operations components with client supplied components.
/// Used for testing or customizing operations withing the factory IoC container.
/// </summary>
/// <param name="principalProviderType"></param>
/// <param name="operationAuthorizerType"></param>
/// <param name="operationAuditorType"></param>
/// <param name="operationInterceptorType"></param>
/// <exception cref=""></exception>
public static void SubstituteComponents(
	Type principalProviderType = null, 
	Type operationAuthorizerType = null, 
	Type operationAuditorType = null)
{
	//set default types where param is null otherwise check for proper interface
	if (principalProviderType == null)
		principalProviderType = typeof(PrincipalProvider);
	else if (principalProviderType.GetInterface(typeof(IPrincipalProvider).FullName) == null)
		throw new ApplicationException("principalProviderType is not of type IPrincipalProvider.");
		
	if (operationAuthorizerType == null) 
		operationAuthorizerType = typeof(OperationAuthorizer);
	else if (operationAuthorizerType.GetInterface(typeof(IOperationAuthorizer).FullName) == null)
		throw new ApplicationException("operationAuthorizerType is not of type IOperationAuthorizer.");

	if (operationAuditorType == null) 
		operationAuditorType = typeof(OperationAuditor);
	else if (operationAuditorType.GetInterface(typeof(IOperationAuditor).FullName) == null)
		throw new ApplicationException("operationAuditorType is not of type IOperationAuditor.");


	if (container.Kernel.RemoveComponent("OperationInterceptor")
		&& container.Kernel.RemoveComponent("OperationAuditor")
		&& container.Kernel.RemoveComponent("OperationAuthorizer")
		&& container.Kernel.RemoveComponent("PrincipalProvider"))
	{
		container.Register(
			Component.For<IPrincipalProvider>()
				.ImplementedBy(principalProviderType)
				.Named("PrincipalProvider")
				.LifeStyle.Transient,

			Component.For<IOperationAuthorizer>()
			.ImplementedBy(operationAuthorizerType)
			.Named("OperationAuthorizer")
			.LifeStyle.Transient,

			Component.For<IOperationAuditor>()
			.ImplementedBy(operationAuditorType)
			.Named("OperationAuditor")
			.LifeStyle.Transient,

			Component.For<OperationInterceptor>()
			.Named("OperationInterceptor")
			.LifeStyle.Transient);
	}
	else
	{
		throw new ApplicationException("SubstituteComponents failed due to invoked component dependencies.");
	}
}

Once the new method was added to the DomainFactory class, I removed the TestHelper.cs file which included this very naughty code which fails in .NET 4.0 because the implementation of the Thread class changed and the GetIllogicalCallContext internal method went away.

//broken in .NET 4.0 - GetIllogicalCallContext does not exist in Thread class anymore
public static void SetCurrentContext(string fileName, string url, string queryString, FakePrincipal principal)
{
	var context = CreateHttpContext(fileName, url, queryString);
	context.User = principal;
	var result = RunInstanceMethod(Thread.CurrentThread, "GetIllogicalCallContext", new object[] { });
	SetPrivateInstanceFieldValue(result, "m_HostContext", context);
}

Now that the offending code is gone, the RegistrationServiceTests test class is broken as you see below:

[TestInitialize]
public void Initialize()
{
	//set up a fake http context with fake IPrincipal
	string[] roles =
		{
			 "Admin",
			 "User",
			 "Local Office"
		};
	TestHelper.SetCurrentContext(new FakePrincipal("Fake", "testuser", true, roles));
}

I replaced that code with this:

static bool isInitialized = false;

[TestInitialize]
public void Initialize()
{
	if (!isInitialized)
	{
		isInitialized = true;
		//only do this once per test/process run
		DomainFactory.SubstituteComponents(typeof(FakePrincipleProvider));
	}
}

And created the new FakePrincipleProvider class to create and deliver the IPrincipal as required by the IPrincipalProvider:

public class FakePrincipleProvider : IPrincipalProvider
{
	FakePrincipal principal;

	public IPrincipal GetPrincipal()
	{
		if (principal == null)
		{
			string[] roles =
			{
				 "Admin",
				 "User",
				 "Local Office"
			};
			principal = new FakePrincipal("Fake", "testuser", true, roles);
		}
		return principal;
	}
}

And now my tests pass again because my IoC container is passing along the FakePrincipleProvider to my OperationAuthorizer class.

There will be more to come with DomainAspects soon.

DomainAspects_v1_2.zip (2.97 MB)