The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the 'agatha' Category

Using Agatha’s Client-Side Caching

Posted by Davy Brion on 9th August 2010

Soon after i introduced Agatha’s server-side caching, people started asking for client-side caching as well. There are indeed quite a few scenarios where it makes sense to cache the response of a service call on the client instead of merely doing it on the server. After all, what kind of service call can be faster than one you don’t have to make? It’s finally been added to the trunk, and it will be available in the upcoming 1.2 release. So for those of you want to use it but are still on 1.1, you can safely upgrade to the current trunk.

Usage of the client-side caching is practically identical to usage of the server-side caching feature, which means you have to use the EnableClientResponseCaching attribute on your request types where you want to use caching, and they have to implement the Equals and GetHashCode methods properly (read this post for more info on this).

Here’s a small example from the Sample that is included in the Agatha source code:

    [EnableServiceResponseCaching(Minutes = 5)]

    [EnableClientResponseCaching(Seconds = 30)]

    public class ReverseStringRequest : Request

    {

        public string StringToReverse { get; set; }

 

        public bool Equals(ReverseStringRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return Equals(other.StringToReverse, StringToReverse);

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(ReverseStringRequest)) return false;

            return Equals((ReverseStringRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return (StringToReverse != null ? StringToReverse.GetHashCode() : 0);

        }

    }

 

In this case, both the EnableServiceResponseCaching and EnableClientResponseCaching attributes were used, which means that responses for this request will be cached for 5 minutes on the server, and for 30 seconds on the client. You don’t have to use both attributes simultaneously, you can use either one of them as well depending on where you want to cache the response. You can also set a region (like you can with the server-side caching) so you can explicitely clean a certain region of the cache if you need to at some point.

Everything happens transparently from your code. If you make a service call with one request, and there is a cached response available for that request, the service call is not made and you’ll get the cached response. If you send a batch of requests, and there are cached responses available for any of those requests, the call that is sent to the service will only include the requests for which no cached response was available.

Posted in agatha | 1 Comment »

Using Agatha’s Server-Side Caching

Posted by Davy Brion on 20th June 2010

One of the most important new additions in the Agatha 1.1 release is the ability to have the service layer cache responses for requests that are eligible for caching.  Obviously, this doesn’t happen automatically and you need to configure this yourself.  Unfortunately, i’ve never really written a post to describe how to do this and what you need to keep in mind.  Hopefully, all of this will be clear after this post.

There are only two things you need to do to use Agatha’s server-side caching feature:

1. Use the EnableServiceResponseCaching attribute

If you want certain Request-derived types to be eligible for caching, you need to put the EnableServiceResponseCaching attribute on top of them.  This attribute enables you to set the logical region (more on that later) where the Response for this Request needs to stored in the cache, and it requires you to set an expiration.  Here’s a simple example:

    [EnableServiceResponseCaching(Minutes = 10, Region = "Issues")]

    public class GetUnassignedIssuesForProjectRequest : Request

    {

        public Guid ProjectId { get; set; }

    }

 

For this particular request type, responses should be cached for a maximum duration of 10 minutes, and the cached responses will be stored in the Issues region.  A region is pretty much just a section within the cache.  If you don’t specify a region, each response will be placed in the default region.  If you do specify one, each cached response for that region is placed within that section.  This gives you the ability to clear an entire region (and thus, all the cached responses that are stored in that region) without impacting any of the other regions (including the default one).

The expiration can be configured by providing a number of hours, minutes or seconds (or a combination of those three) to the attribute.

Now obviously, Agatha needs a way to differentiate between multiple instances of the GetUnassignedIssuesForProjectRequest class.  More specifically, Agatha needs to know when a request can be considered equal to a previous request for which a response has already been cached.  So that brings us to the next thing you need to do:

2. Override the Equals and GetHashCode methods

The response for a GetUnassignedIssuesForProjectRequest instance with ProjectId set to e35c60f7-c35e-43db-9988-0dab3f39c61b will obviously contain a different set of unassigned issues than one for a GetUnassignedIssuesForProjectRequest with ProjectId set to 5d47161a-f334-4cce-9cc4-9606a9d294a6.  To make sure that Agatha knows which response can be returned for a given request, your request needs to override the Equals and GetHashCode methods so you can tell Agatha when an instance of a certain request can be considered equal to one for which a cached response already exists.  In the case of our example, requests of type GetUnassignedIssuesForProjectRequest can be considered equal if they both return the same value through their ProjectId property.  So in this case, our request class needs to look like this:

    [EnableServiceResponseCaching(Minutes = 10, Region = "Issues")]

    public class GetUnassignedIssuesForProjectRequest : Request

    {

        public Guid ProjectId { get; set; }

 

        public bool Equals(GetUnassignedIssuesForProjectRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return other.ProjectId.Equals(ProjectId);

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(GetUnassignedIssuesForProjectRequest)) return false;

            return Equals((GetUnassignedIssuesForProjectRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return ProjectId.GetHashCode();

        }

    }

 

Now that we have an Equals and a GetHashCode method which only looks at the value of the ProjectId property, Agatha can differentiate between different requests on a value basis instead of a reference basis.  Note that this doesn’t mean that your request types need to be value objects in the truest sense of the term.  They just need to be able to perform an equality check based on the values that make the difference between actually handling the request, or returning the response that has previously been cached for the set of values that you’re using to determine equality.  Simply overriding the Equals method is not enough, since Agatha will use these instances of requests as keys in a dictionary so you need to provide a proper GetHashCode implementation as well (which is recommended anyway if you’re overriding the Equals method).

It’s very important to really consider which properties you want to include in the equality check and the hashcode calculation.  If your request type inherits from some base request (typically one that contains user credentials and stuff like that), then you typically don’t want to include those inherited property values in your equality check, unless you really want to cache different responses based on one of those inherited properties.  I’d recommend writing enough tests to verify that your equality checks and hashcode calculations indeed behave the way you want them to because if they don’t, you will either get suboptimal results from Agatha’s caching or even incorrect ones which would lead to bugs that will be very hard to debug.

A question that came up recently in the Agatha discussion group was how to implement the Equals and GetHashCode method for request types for which each instance should really be considered equal.  For instance, a request type like this:

    [EnableServiceResponseCaching(Hours = 2, Region = "ReferenceData")]

    public class GetAllCountriesRequest : Request {}

 

In this case, the default Equals and GetHashCode implementations will be reference-based and not value based.  But as you can see, there are no values to differentiate between requests.  In this case, there is only one way to retrieve the known Countries in this system, so how do we implement the Equals and GetHashCode methods so this request type can be used correctly with Agatha’s caching layer?  Well, the solution isn’t very nice but it is pretty simple.  You can just introduce a dummy field with a fixed value:

    [EnableServiceResponseCaching(Hours = 2, Region = "ReferenceData")]

    public class GetAllCountriesRequest : Request

    {

        private string dummyValue = typeof(GetAllCountriesRequest).FullName;

 

        public bool Equals(GetAllCountriesRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return Equals(other.dummyValue, dummyValue);

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(GetAllCountriesRequest)) return false;

            return Equals((GetAllCountriesRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return dummyValue.GetHashCode();

        }

    }

 

Now, every instance of the GetAllCountriesRequest will be considered equal to each other and they’ll all return the same hashcode as well.  So every incoming instance of this request will return the same cached response (once it’s been cached that is).

That’s pretty much it.  In itself, the caching layer of Agatha is very easy to use, but you definitely need to make sure that your Equals and GetHashCode implementations are correct.  That’s pretty much the only tricky part (and downside) to how Agatha’s caching works, but i was unfortunately unable to come up with something that was easier to use.

One final word on the usage of regions.  If you’re caching responses, then you typically want a way to remove stale responses from the cache.  If some of the data that you’re caching is changed before the cached responses expire, you can clear the region in which those cached responses are being stored.  Just add an ICacheManager constructor parameter to your handler (or any other class for that matter) and call the Clear method which takes a region name as a parameter.

As always with caching: be careful in how you use it, and make sure you think it through :)

Posted in agatha | 3 Comments »

Consuming An Agatha Service From A Non-Agatha-Aware Client

Posted by Davy Brion on 14th May 2010

A question that also comes up occasionally is how you can use an Agatha service from a client which isn’t aware of Agatha? Or more specifically: can an Agatha service be used from a client which has generated a proxy based on the WSDL of the Agatha service? The answer is yes :)

First of all, make sure your service exposes its metadata.  You do this in the usual WCF fashion:

    <behaviors>

      <serviceBehaviors>

        <behavior name="RequestProcessorBehavior">

          <serviceMetadata httpGetEnabled="true"/>

          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>

          <serviceThrottling maxConcurrentCalls="500" maxConcurrentInstances="500"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

 

The serviceMetadata element with the httpGetEnabled=”true” attribute is the important one in the snippet above.

After that, you can simply generate a service proxy through visual studio or svcutil or whatever:

add_service_reference

Now you can write the following code to communicate with your Agatha Service Layer:

using System;

using Sample.NonAgathaAwareClient.MyAgathaService;

 

namespace Sample.NonAgathaAwareClient

{

    class Program

    {

        static void Main(string[] args)

        {

            using (var proxy = new MyAgathaService.WcfRequestProcessorClient())

            {

                var responses = proxy.ProcessRequests(new[] { new HelloWorldRequest() });

                var helloWorldResponse = (HelloWorldResponse)responses[0];

                Console.WriteLine(helloWorldResponse.Message);

                Console.Read();

            }

        }

    }

}

 

Notice that there are no Agatha-related using statements, nor is there any reference to Agatha or the assembly which contains the Request/Response types. All of the required data can be found within the WSDL and you can generate proxies for it just as you could with any other WCF service.  The client-side usage model is of course as bad as it always is with standard WCF (for more information, be sure to read: Why I Dislike Classic Or Typical WCF Usage) but if you’re willing to put up with it, then at least you can ;)

 

This also means that you should be able to generate service proxies for other platforms as well, as long as they support SOAP services.

Posted in agatha | 5 Comments »

Agatha 1.1 Is Out

Posted by Davy Brion on 9th May 2010

I just released the 1.1 version of Agatha.  It’s a bit sooner than i had originally expected it to be, but the reason why i’m releasing the current trunk is because i want to move the current trunk to .NET 4 and Silverlight 4.  So, the 1.1 version is still targeting .NET 3.5 and Silverlight 3 but apart from possible bugfix releases (1.1.x), there will be no more version targeting .NET 3.5 and Silverlight 3.

These are the changes between the 1.0.1 and the 1.1 release:

  • Support for the NInject container (patch contributed by Ian Davis).
  • First version of the server side caching layer.  Consider this implementation to be experimental and there are most likely plenty of issues with it.  Issues that pop up will obviously be fixed in further 1.1.x releases and the trunk as well. 
  • AsyncRequestDispatcher and RequestDispatcher now have a virtual AfterSendingRequests virtual method where you can add some custom code if you need to.
  • Both Request/Response types and RequestHandler can now be located in multiple assemblies (patch contributed by Jason Diamond)
  • Castle Windsor binaries have been updated to version 2.1
  • Castle support for Silverlight has been added
  • The Process method of the IWcfRequestProcessor service contract now allows transaction flowing
  • All configuration classes have been made a bit more fluently (thanks to Mark Meyers)
  • There is now an Agatha.Servicelayer.Silverlight assembly which contains a lightweight version of the service layer to run within your Silverlight application if you want/need this
  • Support for the StructureMap container (patch contributed by Andrew Rea)
  • The IWcfRequestProcessor service contract now supports REST (JSON + XML) (patch contributed by Andrew Rea)
  • RequestDispatcher contains a BeforeReturningResponses method where you can put some additional code to modify responses before they are returned to the consumer of the dispatcher.
  • The serverside RequestProcessor contains a few extra virtual methods which enables you to customize how exceptions are logged (patch contributed by Emil Ingerslev)
  • Fixed NullReferenceException in MessageInspector when using one-way requests in combination with INFO logging

So basically, everyone that’s been running on the trunk is probably better off using the 1.1 version, unless you’re willing to move to .NET 4.

You can download the 1.1 version here.

The goals for the 1.2 release are to take as much advantage as possible from new .NET 4 and WCF 4 improvements, and also to make the caching layer as good as it can be.  And yes, that will include some form of client-side caching :)

Posted in agatha | 5 Comments »

Consuming Multiple Agatha Services

Posted by Davy Brion on 8th May 2010

One question that occasionally comes up is how a client can use multiple Agatha services.  While it’s not possible with Agatha’s out-of-the-box configuration and usage patterns, it can be done if you’re willing to write a little bit of glue code. So, let’s go through the steps to make it work. I’m gonna use one of our Silverlight applications for this example, but it works just the same for regular .NET clients.

First of all, the Silverlight client’s WCF config has 2 defined endpoints:

    <client>

      <endpoint binding="basicHttpBinding" bindingConfiguration="firstServiceBinding"

            contract="Agatha.Common.WCF.IWcfRequestProcessor"

            name="firstService" />

 

      <endpoint binding="basicHttpBinding" bindingConfiguration="secondServiceBinding"

            contract="Agatha.Common.WCF.IWcfRequestProcessor"

            name="secondService" />

    </client>

 

Notice that each endpoint has a defined name.

Now you can create 2 new service proxies which inherit from Agatha’s proxy:

    public class FirstServiceProxy : Agatha.Common.WCF.AsyncRequestProcessorProxy

    {

        public FirstServiceProxy()

            : base("firstService", GetServiceUrl()) {}

 

        private static string GetServiceUrl()

        {

            // return the correct url from somewhere…

        }

    }

 

    public class SecondServiceProxy : Agatha.Common.WCF.AsyncRequestProcessorProxy

    {

        public SecondServiceProxy()

            : base("secondService", GetServiceUrl()) {}

 

        private static string GetServiceUrl()

        {

            // return the correct url from somewhere…

        }

    }

 

Once you have those proxies, you can create new request dispatchers, which also inherit from Agatha’s:

    public interface IFirstDispatcher : Agatha.Common.IAsyncRequestDispatcher {}

 

    public class FirstDispatcher : Agatha.Common.AsyncRequestDispatcher, IFirstDispatcher

    {

        public FirstDispatcher(FirstServiceProxy requestProcessor) : base(requestProcessor) { }

    }

 

    public interface ISecondDispatcher : Agatha.Common.IAsyncRequestDispatcher {}

 

    public class SecondDispatcher : Agatha.Common.AsyncRequestDispatcher, ISecondDispatcher

    {

        public SecondDispatcher(SecondServiceProxy requestProcessor) : base(requestProcessor) { }

    }

 

If you register those types with your container (make sure it’s the same container instance that Agatha uses) and you can have the correct dispatchers injected for whichever service you want to communicate with.  But in the case of asynchronous request dispatchers, you typically use a factory to get them, so you probably want to add something like this:

    public interface IFirstDispatcherFactory : Agatha.Common.IAsyncRequestDispatcherFactory {}

 

    public class FirstDispatcherFactory : IFirstDispatcherFactory

    {

        public IAsyncRequestDispatcher CreateAsyncRequestDispatcher()

        {

            return IoC.Container.Resolve<IFirstDispatcher>();

        }

    }

 

    public interface ISecondDispatcherFactory : Agatha.Common.IAsyncRequestDispatcherFactory {}

 

    public class SecondDispatcherFactory : ISecondDispatcherFactory

    {

        public IAsyncRequestDispatcher CreateAsyncRequestDispatcher()

        {

            return IoC.Container.Resolve<ISecondDispatcher>();

        }

    }

 

And there you go… inject the proper factory (or both of them) and just use whichever one you need to get a dispatcher for the service you want.

Posted in agatha | 8 Comments »

Looking For Agatha Testimonials

Posted by Davy Brion on 5th May 2010

I’ve noticed recently that i’m gradually getting more visitors to this blog through Agatha’s project site.  Pretty glad to see that, though the numbers are still very low.  Nevertheless, once you notice that something you’ve created is actually being used by people, you love to hear more about what their experiences are.  Which is kinda hard in this case since i picked one of the worst possible names for a project if you ever want to be able to search google or twitter to read what people are saying about it.  

So, i figured i’d just ask you guys.  Have you used Agatha? Did you have positive experiences with it? If so, i’d really appreciate any testimonials you can send me (email address is ralinx at the domain name of this blog).  Not only do i get to read about your experiences, i can add them to the project site as well which does kinda boost the credibility of the project for people who never heard about it before.  If you’re willing to write such a testimonial (which only needs to be one or two sentences, though something longer than that is more than welcome as well), please include your name, your jobtitle and the name of your company in the email.

Also, if you have tried it and were not happy with it or ran into problems with it, i’d definitely like to hear from you as well so i can look into possible solutions or improvements.

Thanks!

Posted in agatha | 3 Comments »

Securing Your Agatha Service Layer

Posted by Davy Brion on 27th January 2010

The question of how to implement security for an Agatha Service Layer is one that comes up frequently.  First of all, you need to remember that if you’re using Agatha with WCF you can use any of the WCF features that you’d normally use to secure your WCF service.  There’s already plenty of information available online or in books on implementing security for WCF services so i’m not going to spend time on covering those options.  What i am going to cover is the approach that we typically use for our Agatha service layers.

I don’t like to tie myself to WCF-specific features, so i always plug in custom authentication into either a custom Request Processor, or a base Request Handler class that all other Request Handlers must inherit from.   But first, how do we get the authentication-related data from the client to the service?

In each project i use Agatha in, i always have a MyProjectRequest and MyProjectResponse base class:

    public class MyProjectRequest : Request

    {

        public string UserName { get; set; }

        public byte[] PasswordHash { get; set; }

    }

 

    public class MyProjectResponse : Response {}

 

Each request in the project inherits from this base request, and each response inherits from the base response.  The base response class is often empty, though this does make it very easy if you ever need to send something back with every response.

Now obviously, if every single request that is sent to your service layer needs values for the UserName and PasswordHash properties you want this to be done in only one place.  I do this by using a custom request dispatcher:

    public class MyProjectAsyncRequestDispatcher : AsyncRequestDispatcher

    {

        private readonly IUserContext userContext;

 

        public MyProjectAsyncRequestDispatcher(IAsyncRequestProcessor requestProcessor, IUserContext userContext) : base(requestProcessor)

        {

            this.userContext = userContext;

        }

 

        protected override void BeforeSendingRequests(IEnumerable<Request> requestsToProcess)

        {

            base.BeforeSendingRequests(requestsToProcess);

 

            foreach (var myProjectRequest in requestsToProcess.OfType<MyProjectRequest>())

            {

                myProjectRequest.UserName = userContext.UserName;

                myProjectRequest.PasswordHash = userContext.PasswordHash;

            }

        }

    }

 

The IUserContext dependency is just a component that is registered in my IOC container and will be injected automatically whenever you get an instance of IAsyncRequestDispatcher.   Now, in this example you can see that i add the authentication data to every request in a batch, even though the batch will be sent in one roundtrip.  If you want, you can add the authentication data only to the first request and then only use the first request to do the authentication within your service layer.  I prefer to add the authentication data to each request and then authenticate every single request (even subsequent requests in a batch) within the service layer.  I’ll get back to this point later on.

Now, the only thing we need to do to make sure that your requests will always have the authentication data contained within them is to instruct Agatha to always use instances of your MyProjectAsyncRequestDispatcher class whenever an IAsyncRequestDispatcher is needed.  This is easily done during Agatha’s client-side configuration:

            new ClientConfiguration(typeof(MyProjectRequest).Assembly, new Agatha.Castle.Container(myContainerWrapper))

                {

                    AsyncRequestDispatcherImplementation = typeof(MyProjectAsyncRequestDispatcher)

                }

                .Initialize();

 

Keep in mind that you still have to register your IUserContext with the container on your own though. 

With that in place, we are sure that each request that comes from our clients always contains the proper authentication data.  Now we need to make sure that we actually authenticate these requests within the service layer.  You basically have 2 options: either implement your own Request Processor which adds authentication checks, or create a base Request Handler that your other Request Handlers inherit from.

We’ll first cover the option of using a custom Request Processor.   You could create one like this:

    public class MyProjectRequestProcessor : RequestProcessor

    {

        private readonly IAuthenticator authenticator;

 

        public MyProjectRequestProcessor(IAuthenticator authenticator, ServiceLayerConfiguration serviceLayerConfiguration, ICacheManager cacheManager)

            : base(serviceLayerConfiguration, cacheManager)

        {

            this.authenticator = authenticator;

        }

 

        protected override void BeforeHandle(Request request)

        {

            var myProjectRequest = request as MyProjectRequest;

 

            if (myProjectRequest != null)

            {

                if (!authenticator.AreValidCredentials(myProjectRequest.UserName, myProjectRequest.PasswordHash))

                {

                    throw new MySecurityException();

                }

            }

        }

    }

 

The BeforeHandle virtual method is called right before the request is passed to its Request Handler to be handled.  Note that this Request Processor would authenticate every request.  If you want a Request Processor that only authenticates the first request, you could do so like this:

    public class MyProjectRequestProcessor : RequestProcessor

    {

        private readonly IAuthenticator authenticator;

 

        public MyProjectRequestProcessor(IAuthenticator authenticator, ServiceLayerConfiguration serviceLayerConfiguration, ICacheManager cacheManager)

            : base(serviceLayerConfiguration, cacheManager)

        {

            this.authenticator = authenticator;

        }

 

        protected override void BeforeProcessing(IEnumerable<Request> requests)

        {

            var myProjectRequest = (MyProjectRequest)requests.ElementAt(0);

 

            if (!authenticator.AreValidCredentials(myProjectRequest.UserName, myProjectRequest.PasswordHash))

            {

                throw new MySecurityException();

            }

        }

    }

 

The BeforeProcessing virtual method is called before any of the requests are handled, so you could authenticate only the first request in a batch and then proceed with regular processing if the first one is authenticated.  Now, the big problem that i have with this approach is that you aren’t really in control of what is sent to your service layer.  Yes, you can guarantee that each request coming from your clients contains the proper authentication data.  What you simply can’t guarantee however is what other people or custom clients can send to your service layer.  If they send you a batch of 2 requests, the first containing valid credentials of a normal user for a benign request, it will pass the authentication just fine.  If the second request in that batch contains invalid credentials (to trick your authorization into believing it’s from a user with higher privileges for instance) for a request that could cause some damage (deleting important information or triggering certain tasks or whatever), then you can’t really do anything to prevent that.  Unless of course, you reject this approach and authenticate every single request.

As for the MySecurityException type, that’s up to you as well.  When you configure your Agatha service layer, you can set the SecurityExceptionType property to the type of exception that should be considered as a security exception.  When the Request Processor catches an exception of that type, it will set the ExceptionType property of the response to ExceptionType.Security so you can check for that specific situation in your client.

To configure Agatha to use your custom Request Processor, your configuration code would look like this:

            new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(), typeof(MyProjectRequest).Assembly,

                new Agatha.Castle.Container(containerWrapper))

                {

                    RequestProcessorImplementation = typeof(MyProjectRequestProcessor),

                    SecurityExceptionType = typeof(MySecurityException)

                }

                .Initialize();

 

Another alternative is to create a base Request Handler for your project and to have each Request Handler inherit from it.  Something like this, for instance:

    public abstract class MyProjectRequestHandler<TRequest, TResponse> : RequestHandler<TRequest, TResponse>

        where TRequest : MyProjectRequest

    {

        public IAuthenticator Authenticator { get; set; }

 

        public override void BeforeHandle(TRequest request)

        {

            base.BeforeHandle(request);

 

            if (!Authenticator.AreValidCredentials(request.UserName, request.PasswordHash))

            {

                throw new MySecurityException();

            }

 

            Authorize(request);

        }

 

        protected virtual void Authorize(TRequest request) {}

    }

 

In case you’re wondering why i’m using Setter-injection here instead of Constructor-injection, read this.

I typically prefer the custom Request Handler approach for authentication.  In most applications that we write, authentication is not enough and we need custom authorization checks for many requests.  So i’m going to need a base Request Handler which introduces the virtual Authorize method anyway.  So i might as well do my authentication check right before it.

With the custom Request Handler approach, you probably still want to configure Agatha to use your custom security exception type:

            new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(), typeof(MyProjectRequest).Assembly,

                new Agatha.Castle.Container(containerWrapper))

                {

                    SecurityExceptionType = typeof(MySecurityException)

                }

                .Initialize();

 

And then you just need to let your own Request Handlers inherit from your MyProjectRequestHandler.  Authentication will be performed for each request by default, and you can easily add specific authorization logic for every request. 

And those are pretty much the options you have to secure your Agatha Service Layer.   Oh, and be sure to only expose your Service Layer through SSL :)

Posted in agatha | 4 Comments »

Agatha Vs NServiceBus?

Posted by Davy Brion on 26th January 2010

Ever since i open sourced Agatha, i’ve gotten questions from people who are wondering whether they should use Agatha or NServiceBus.  I’ve also gotten questions about things that people wanted to do with Agatha but that aren’t really supported.  And i’ve also noticed that people were coming to my site with search keywords like “agatha vs nservicebus”.  The thing is, they are hardly comparable.

Agatha is a Request/Response Service Layer framework.  It basically supports synchronous and asynchronous Request/Response style communication and tries to make it as easy as possible to write a service layer for that type of communication.  Apart from being easy to use, it also encourages a clean implementation of your service layer and a way to minimize the repetitiveness of cross-cutting concerns.  It also enables you to get better performance than with typical Remote Procedure Call or Remote Method Invocation style service layers because it will try to minimize roundtrips by batching requests and responses together.  In the next release, it will also offer a caching layer so certain requests (depending on how you set it up) don’t need to be processed and cached responses can simply be returned.  There’s also support for one-way requests (or fire-and-forget requests) but it has the same downsides as one-way requests with typical WCF services have. That’s pretty much all it does.  That’s probably all it’ll ever do.  In short, it’s just an upgrade over your typical WCF services.

NServiceBus on the other hand also does Request/Response, but that’s just one of the things it can do.  Again, Agatha is essentially an RPC or RMI framework whereas NServiceBus is built on top of one-way messaging technology.  This allows for much more possibilities when it comes to communicating between different applications or different parts or processes within the same application boundary.  A great overview of those possibilities can be found here.  Because it is based on messaging, there are a lot of benefits that you can get from NServiceBus that you’ll probably never get from Agatha.  For one, the ‘Store & Forward’ messaging model from NServiceBus might seem similar to Agatha’s one-way requests on first sight, but there are some very important differences.  If you send a fire-and-forget request with Agatha, and the service is currently down, then that request is essentially lost.  With NServiceBus, the message is stored in a message queue and it will be processed when the target of the fire-and-forget message comes up again.  From a reliability point of view, that’s obviously a tremendous improvement over what Agatha can offer you.  Another area where NServiceBus truly shines (IMO) is in its Publish/Subscribe implementation.  Some people have asked me if i’ll ever provide something like that in Agatha and the answer has always been ‘no’.   For one, it doesn’t fit into what Agatha tries to do and i don’t see the point in implementing it if a better implementation is available already in another project.   There’s plenty more interesting things in NServiceBus to deal with more advanced scenarios, which you’ll have to find out about on your own ;)

So which one is more suitable for you or your applications? As with every technology choice, it depends.  Agatha is great for most typical business applications.  If you need to communicate between one or more different clients (with different i don’t mean multiple instances but different types of clients like a web app, a silverlight client and/or a WPF client) and one service (you can obviously use it with more than one service as well if you want to) on an application server which encapsulates your business layer then it is a very attractive solution, as long as you don’t need the superior reliability that NServiceBus can offer you.  With superior reliability i particularly mean the ability to still process received messages once the service layer comes back up after having been unavailable.  In my experience, most business applications don’t really need that, since most of those applications are entirely unusable if the service they depend on is down.  In short, if all the possible downsides of using a WCF service layer are not an issue for your project, then Agatha will be a great fit.

If however, you need to maximize reliability, performance and general robustness of a critical enterprise application, then NServiceBus will definitely be a much better choice.  If you’re dealing with many distributed parts, NServiceBus will also make things much easier for you than Agatha (or any other WCF service layer for that matter) will.   And obviously, if you want to integrate multiple applications while reducing coupling between applications as much as possible, NServiceBus will also be a much better fit than Agatha.  With NServiceBus, you’d only need to share an assembly containing the types of the messages.  With Agatha, you either need to share an assembly with shared request/response types or use proxies for them and you would also have to know about the other applications since you’d need to access their services directly.  This can get quite ugly pretty fast.

And in some cases, you can just use both of them at the same time.  At work we have two projects that use Agatha for all of their internal communication within their own application boundary, yet they use NServiceBus to notify each other of certain events.  Neither of the applications knows about the existence of the other… the only thing they share is one assembly with some shared message types.  We’ve also started working on a new platform where each application in the platform will use Agatha for all of the communication within their own application boundary (since they’re all typical silverlight clients backed by a WCF service style applications) but they will use NServiceBus for every kind of communication that goes outside of the application boundary.

As with many things, it’s just a matter of choosing the right tool for the right job.  Hopefully, this post will help some of you make that decision should you need to make it in the future :)

Posted in agatha, nservicebus | 8 Comments »

Testing Agatha’s Caching Functionality With QuickNet

Posted by Davy Brion on 24th December 2009

In this post i’m going to give you a very detailed explanation of a QuickNet test that i wrote for Agatha’s caching layer.  If i do my job well, you’ll have a much better view on what QuickNet does, how it works, and how it can help you.  I do want to ask you to keep a very open mind and to forget pretty much everything that you know about automated testing, including your opinions on what should or should not be done in an automated test.  If you have problems with that, you might be interested in more conservative reading on automated testing.  Still here? Alright, let’s get started.  Please stay focused throughout, because you will need it :p

First of all, requests whose response is eligible for caching must override the Equals method and the GetHashCode method.  I’ll use the following two request/response combinations for this test:

    [EnableResponseCaching(Seconds = 1)]

    public class FirstCachedRequest : Request

    {

        public string String { get; set; }

 

        public bool Equals(FirstCachedRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return Equals(other.String, String);

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(FirstCachedRequest)) return false;

            return Equals((FirstCachedRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return (String != null ? String.GetHashCode() : 0);

        }

    }

 

    public class FirstCachedResponse : Response { }

 

    [EnableResponseCaching(Seconds = 2)]

    public class SecondCachedRequest : Request

    {

        public int Integer { get; set; }

 

        public bool Equals(SecondCachedRequest other)

        {

            if (ReferenceEquals(null, other)) return false;

            if (ReferenceEquals(this, other)) return true;

            return other.Integer == Integer;

        }

 

        public override bool Equals(object obj)

        {

            if (ReferenceEquals(null, obj)) return false;

            if (ReferenceEquals(this, obj)) return true;

            if (obj.GetType() != typeof(SecondCachedRequest)) return false;

            return Equals((SecondCachedRequest)obj);

        }

 

        public override int GetHashCode()

        {

            return Integer;

        }

    }

 

    public class SecondCachedResponse : Response {}

 

Agatha’s Request Processor should cache responses for requests that are eligible for caching, and when subsequent requests need to be processed which are equal (in their values) to previous requests whose response has been cached already, the cached response needs to be returned instead of handling the request again.

In order to inspect the usage of the caching layer during tests, i wrote the following CacheManagerSpy class which inherits from my normal CacheManager class (which is used by Agatha):

    public class CacheManagerSpy : CacheManager

    {

        private List<CacheEntry> cacheEntries;

        private List<Response> returnedCachedResponses;

 

        public IEnumerable<CacheEntry> CacheEntries

        {

            get { return cacheEntries; }

        }

 

        public IEnumerable<Response> ReturnedCachedResponses

        {

            get { return returnedCachedResponses; }

        }

 

        public CacheManagerSpy(CacheConfiguration configuration, ICacheProvider cacheProvider) : base(configuration, cacheProvider)

        {

            Clear();

        }

 

        public void Clear()

        {

            cacheEntries = new List<CacheEntry>();

            returnedCachedResponses = new List<Response>();

        }

 

        protected override Response GetCachedResponseFor(Request request, string region)

        {

            var cachedResponse = base.GetCachedResponseFor(request, region);

            returnedCachedResponses.Add(cachedResponse);

            return cachedResponse;

        }

 

        protected override void StoreInCache(Request request, Response response, TimeSpan expiration, string region)

        {

            cacheEntries.Add(new CacheEntry(request, response, expiration, region));

            base.StoreInCache(request, response, expiration, region);

        }

 

        public class CacheEntry

        {

            public Request Request { get; private set; }

            public Response Response { get; private set; }

            public TimeSpan Expiration { get; private set; }

            public string Region { get; private set; }

 

            public CacheEntry(Request request, Response response, TimeSpan expiration, string region)

            {

                Request = request;

                Response = response;

                Expiration = expiration;

                Region = region;

            }

        }

    }

 

This Spy basically gives me the ability to see which entries are stored in the cache, and which responses have been returned.

Now i can create a QuickNet Acid test.  I’m going to go over the code step by step instead of listing it all at once because each step probably needs quite a bit of explanation if you don’t understand QuickNet yet.

First of all, here’s the definition of the test:

    public class RequestProcessorCachingSpecs : AcidTest

    {

        public RequestProcessorCachingSpecs() : base(10, 2000) { }

 

The 10 means that QuickNet will perform 10 testruns.  The 2000 means that each testrun will contain 2000 executions of the defined transitions.  Don’t worry yet about what a transition is, i’ll get to that later on in the post.

We’ll also need some fields to access some of the classes that will be used in this test:

        protected static IRequestHandler<FirstCachedRequest> firstCachedRequestHandler;

        protected static IRequestHandler<SecondCachedRequest> secondCachedRequestHandler;

        protected static IRequestProcessor requestProcessor;

        protected static CacheManagerSpy cacheManager;

 

Yeah, i know what you’re thinking.  Static is bad right?  Well, not in this case since we need to be able to use these instances in some inner classes that we’ll go over soon enough and these references will hold the same instance for each testrun (which, as mentioned consists of 2000 transition executions).  Anyway, forget about the static keyword for a second and keep reading.

Now we can implement the SetUp of our testrun:

        public override void SetUp()

        {

            IoC.Container = new Agatha.Castle.Container();

 

            var serviceLayerConfiguration = new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(),

                Assembly.GetExecutingAssembly(), IoC.Container)

            {

                BusinessExceptionType = typeof(BusinessException),

                SecurityExceptionType = typeof(SecurityException),

                CacheManagerImplementation = typeof(CacheManagerSpy)

            };

            serviceLayerConfiguration.Initialize();

 

            // i want to take advantage of the automatic initialization, so i’m just resolving the requestprocessor instead of creating it

            requestProcessor = IoC.Container.Resolve<IRequestProcessor>();

            // the cache manager is a singleton so i can just resolve it and it’ll be the same one the request processor uses

            cacheManager = (CacheManagerSpy)IoC.Container.Resolve<ICacheManager>();

 

            firstCachedRequestHandler = MockRepository.GenerateMock<IRequestHandler<FirstCachedRequest>>();

            secondCachedRequestHandler = MockRepository.GenerateMock<IRequestHandler<SecondCachedRequest>>();

 

            IoC.Container.RegisterInstance(firstCachedRequestHandler);

            IoC.Container.RegisterInstance(secondCachedRequestHandler);

        }

 

This setup code will be executed for each testrun.  So QuickNet will execute this 10 times, and each time it will run 2000 transition executions on the classes that we set up for the current testrun. 

So what exactly is a transition? It’s just a piece of code that you want to execute.  That piece of code can receive input and it can return output.  It’s basically the code that you’re testing.  Our transition will simply consist of calling Agatha’s Request Processor and instructing it to process 2 requests.  Those requests would be the two request types shown earlier which are eligible for caching.  After QuickNet executes the transition, it will also verify that our defined specifications for that particular transition are indeed correct.

Let’s define the input that our transition will receive.  In this particular case, we need a Request instance, an instance of a Request Handler for that Request, and the Response that the Request Handler needs to return if there’s no valid Response available in the cache.  So we’ll use the following helper class to define this input:

        public class ProcessInputElement

        {

            public IRequestHandler RequestHandler { get; private set; }

            public Request Request { get; private set; }

            public Response Response { get; private set; }

 

            public bool RequestHandlerWasExecuted { get; private set; }

 

            public ProcessInputElement(IRequestHandler requestHandler, Request request, Response response)

            {

                RequestHandler = requestHandler;

                Request = request;

                Response = response;

            }

 

            public void StubHandler()

            {

                RequestHandler

                    .Stub(r => r.Handle(Arg<Request>.Is.Same(Request))) // WHY: reference check iso equality check

                    .Return(Response)

                    .WhenCalled(a => RequestHandlerWasExecuted = true)

                    .Repeat.Once();

            }

        }

 

An instance of this class basically combines the Request, its Request Handler and the Response that needs to be returned.  It also contains a helper method so we can easily instruct the mocked Request Handler to return the given Response when it is asked to handle the given Request.  And we’ll also set a simple flag to true if the Request Handler has indeed been called.

As i mentioned a few times already, QuickNet will execute our transition (which i’ll show later on in the post) 2000 times for each testrun.  Obviously, we can’t be expected to create these instances manually all the time, so we need to define some generators that QuickNet will be able to use to randomly generate the input that it can pass to the transition.  We first need two generators which are capable of generating random instances of the FirstCachedRequest and SecondCachedRequest types:

        public class FirstRequestGenerator : BaseGenerator<FirstCachedRequest>

        {

            public FirstRequestGenerator()

            {

                AddGeneratorForProperty(r => r.String, new StringGenerator(1, 1)); // generates a random string of 1 character

            }

        }

 

        public class SecondRequestGenerator : BaseGenerator<SecondCachedRequest>

        {

            public SecondRequestGenerator()

            {

                AddGeneratorForProperty(r => r.Integer, new IntGenerator(0, 5));

            }

        }

 

The FirstRequestGenerator class is capable of returning a new instance of FirstCachedRequest whenever it is asked to do so, and it will populate the FirstCachedRequest instance’s String property with a random string consisting of one character.   Some of the generated instances will be considered equals of each other if the generated string value is equal, and some will not be considered as equals if the generated string value is not equal.  The SecondRequestGenerator basically does the same thing, except that it will populate the SecondCachedRequest instances’ Integer property with a random int value between 0 and 5.  So again, some of the generated instances will be considered as equals, and some won’t.   The important part to remember is that QuickNet will generate random instances for us and that we don’t have to worry about it.

Now that we have the generators for the request instances, we can write a generator which can generate random ProcessInputElement instances:

        public class ProcessInputTupleGenerator : BaseGenerator<Tuple<ProcessInputElement, ProcessInputElement>>

        {

            private FirstRequestGenerator firstRequestGenerator = new FirstRequestGenerator();

            private SecondRequestGenerator secondRequestGenerator = new SecondRequestGenerator();

 

            protected override Tuple<ProcessInputElement, ProcessInputElement> GetDefaultInstance()

            {

                var firstElement = new ProcessInputElement(firstCachedRequestHandler, firstRequestGenerator.GetRandomValue(),

                                                           new FirstCachedResponse());

                var secondElement = new ProcessInputElement(secondCachedRequestHandler, secondRequestGenerator.GetRandomValue(),

                                                            new SecondCachedResponse());

 

                return Tuple.New(firstElement, secondElement);

            }

        }

 

Actually, this generator doesn’t just generate one instance of ProcessInputElement, it generates a tuple consisting of two ProcessInputElement instances.  The first value in the tuple will always contain a random instance of FirstCachedRequest, its Request Handler and a FirstCachedResponse instance that needs to be returned by the Request Handler if there’s no cached response yet.  The same goes for the second value in the tuple, except that it has a random instance of SecondCachedRequest, its Request Handler and a SecondCachedResponse instance.

Again, every time QuickNet will execute our transition, it will ask the ProcessInputTupleGenerator to generate a new tuple, and that tuple will contain the random request instances.  The generated tuple is then passed into the transition and the transition will be executed.

Now i can finally show you the transition that we’ll define:

        public class ProcessRequestsTransition : MetaTransition<Tuple<ProcessInputElement, ProcessInputElement>, Response[]>

        {

            public ProcessRequestsTransition()

            {

                Generator = new ProcessInputTupleGenerator();

                Execute =

                    input =>

                        {

                            cacheManager.Clear(); // clears the spy for every execution of this transition

 

                            input.First.StubHandler();

                            input.Second.StubHandler();

 

                            return requestProcessor.Process(new[] {input.First.Request, input.Second.Request});

                        };

            }

        }

 

As you can see, the ProcessRequestsTransition inherits from the MetaTransition<TInput, TOutput> class.  So we basically just defined that the input of the transition is a Tuple<ProcessInputElement, ProcessInputElement> and the output is an array of Response objects.  In the constructor of the transition, we define that the generator to be used to generate the input values is the ProcessInputTupleGenerator.  And we also define what actually needs to be executed by the transition.  In this case, the piece of code that will always be executed will first clear the CacheManagerSpy instance (so we can safely inspect it during our specification verification), it will then prepare both Request Handler mocks and then it simply calls the Process method of the Request Processor.  It’s output (a Response array) will be the output of the transition since that is our return value.

After all that work, we can finally define our specifications for this transition.  Let’s start with the first one:

        [SpecFor(typeof(ProcessRequestsTransition))]

        public Spec ResponsesAreCachedIfTheyArentInTheCacheYet(Tuple<ProcessInputElement, ProcessInputElement> input, Response[] output)

        {

            return new Spec(() =>

                    {

                        Action<ProcessInputElement> verify =

                            element =>

                                {

                                    Ensure.Equal(element.Response, cacheManager.CacheEntries.First(e => e.Request.Equals(element.Request)).Response);

                                    Ensure.True(output.Contains(element.Response));

                                    Ensure.True(element.RequestHandlerWasExecuted);

                                };

 

                        if (cacheManager.CacheEntries.Any(e => e.Request.Equals(input.First.Request)))

                        {

                            verify(input.First);

                        }

 

                        if (cacheManager.CacheEntries.Any(e => e.Request.Equals(input.Second.Request)))

                        {

                            verify(input.Second);

                        }

                    })

                .IfAfter(() => cacheManager.ReturnedCachedResponses.Any(r => r == null));

        }

 

The SpecFor attribute makes it possible to define which Transition this Spec belongs to.  The method has 2 parameters, which correspond with the input that will be passed into the transition, and the output that the transition returned.  It’s very important to realize that this method is executed before the transition is executed (yet after the input has been generated), but the block of code that we pass into the Spec instance will only be executed after the transition has been executed.  Actually, that block of code will only be executed if the Spec’s precondition and postcondition have been satisfied.  The precondition (which can be defined with the Spec class’ If method) will be evaluated before the transition is executed.  If it evaluates to false, the spec will be ignored for the current execution of the transition.  The postcondition (which can be defined with the Spec class’ IfAfter method) is evaulated after the transition is executed.  If it evaulates to false, the spec will be ignored.  If it evaluates to true, the spec will be verified using the input that was passed into the transition and the output that was returned from the transition.

For this particular spec, we define a postcondition that the spec only needs to be verified if the CacheManager returned one or more null values instead of cached responses.  If the CacheManager returns a null, it means that there was no cached response for the request it was given.  And that is when we need to verify the following things:

  1. The request was handled by the Request Handler
  2. The response that was returned by the Request Handler has been put in the cache
  3. The response array that was returned by the Request Processor contains the expected response

We perform this check for both requests, or only one of them, depending on which one was not in the cache yet.  Remember that the transition will be executed 2000 times using the same request processor and the same cache manager.  Which means that cached responses from previous transition executions might still be in the cache.  Also keep in mind that one of the request types has a defined expiration of 1 second, and the other an expiration of 2 seconds which means that there will be plenty of transition executions where they are either both in the cache, only one of them, or none of them.  All of those cases are now covered with the code in this spec.

Here’s another spec:

        [SpecFor(typeof(ProcessRequestsTransition))]

        public Spec CachedResponsesAreReturnedWhenAvailableInsteadOfCallingTheHandler(Tuple<ProcessInputElement, ProcessInputElement> input, Response[] output)

        {

            return new Spec(() =>

                        {

                            Action<ProcessInputElement> verify =

                                element =>

                                    {

                                        Ensure.False(element.RequestHandlerWasExecuted);

                                        Ensure.True(output.Contains(cacheManager.ReturnedCachedResponses.First(r => r != null && r.GetType() == element.Response.GetType())));

                                    };

 

                            if (cacheManager.ReturnedCachedResponses.Any(r => r != null &&  r.GetType() == input.First.Response.GetType()))

                            {

                                verify(input.First);

                            }

 

                            if (cacheManager.ReturnedCachedResponses.Any(r => r != null && r.GetType() == input.Second.Response.GetType()))

                            {

                                verify(input.Second);

                            }

                        })

                .IfAfter(() => cacheManager.ReturnedCachedResponses.Any(r => r != null));

        }

 

Here we verify that when a cached response was returned by the CacheManager:

  1. The Request Handler was not executed
  2. The response array returned by the Request Processor contains the cached response

We again perform this check for both requests, or only one of them depending on which one had a cached response.

You might think that this was a lot of work, but was it really?  It’s about 160 lines of code, and i’m quite sure that the functionality that i’m testing is covered much more thoroughly than it would’ve been with 160 lines of code for classical unit tests.   In fact, i challenge each one of you to come up with a more thorough test for this in less than 160 lines of code.  Also, i can keep adding specs quite easily and those really don’t contain that much code.  But my functional coverage would increase dramatically, much more than it would with classical unit tests.

Granted, the learning curve is steep as i mentioned already in a previous post.  But once you start to get it, you become pretty productive with it and you’ll catch a lot more bugs before you deliver your software because of it.

Now, i tried hard to make everything here as clear as possible, so i’d love to hear from you whether or not:

  1. you understood it
  2. you like it
  3. you think it’s way over the top
  4. you want to start doing this too

Posted in Test Driven Development, agatha, quicknet | 9 Comments »

How QuickNet Found 2 Bugs That You And I Didn’t

Posted by Davy Brion on 22nd December 2009

I recently posted the first draft of the caching implementation of Agatha.  You might want to take another look at the piece of code that deals with processing requests in the Request Processor.  I thought it was alright.  And if only 10% of my readers actually read that code, then it means that about 200 people thought it was alright too because nobody mentioned a possible problem with that part.  Today i was adding some cached requests/responses to the RequestProcessor’s QuickNet exception handling test.  And lo and behold, 2 bugs showed up that i hadn’t anticipated.

Before i discuss the two bugs, i’d like to explain what the exception handling quicknet test does, and how it works.  It basically calls the request processing code a bunch of times, each time with a set of requests where either none, one or more of the request handlers will throw an exception during the handling of the requests.  The order of the exceptions or which handlers will throw an exception is completely randomized (thanks to QuickNet) and thus it varies from test to test.  This particular QuickNet test will perform 50 testruns, where each testrun consists of 50 transitions that will be executed.  Each transition is a piece of functionality that will be executed (in this case, the processing of requests) with randomized input (in this case, there is a fixed set of requests but which ones will fail will differ with each run of the transition) and after a transition is executed, the relevant specs are verified (in this case, a bunch of checks to make sure that the whole error handling functionality always does what it needs to do) to make sure that the piece of code that you’re testing (your transition, in this case the processing of requests) actually works.

Instead of testing with a mocked caching layer, i used the real thing in the tests.  I also added 2 cached request types to the test request types, and gave one of them an expiration of 1 second, the other an expiration of 2 seconds.  This means that during the entire QuickNet testrun, some requests will return cached responses, some won’t, some cached responses will expire and subsequent requests of that particular type need to be executed and have their responses cached again until they expire.   In the meantime, QuickNet is constantly firing requests at the RequestProcessor, and some of them will randomly fail.  Our specs need to verify that the returned responses always contain the correct exception information for the batch of requests that was processed.

And here’s the beauty of the whole thing.  I hadn’t even thought about how exception handling also influences how you deal with cached responses.  I didn’t take exception handling into account when adding the caching code, and without even adding specific tests to see whether the caching worked correctly, my QuickNet specs that intended to cover something that doesn’t really have anything to do with caching uncovered 2 issues with my caching code.   I was suddenly getting error messages from QuickNet that in some cases, the exception information wasn’t correct.   And it frequently took over 30 executions of the transition, or sometimes multiple testruns before some of those specs would fail.  The longer it takes for a bug to show up in a QuickNet test, the better the bug is at hiding and the harder it is to find it manually because it almost certainly is an edge-case that you hadn’t considered at all and that only occurs in certain situations.

And those are the type of bugs that you typically don’t find with traditional unit tests.  When you write traditional tests that are aimed at asserting correct behavior, you typically only write tests for the problems that you thought about.  Sometimes you’ll get lucky and traditional unit tests will inform you of incorrect behavior that you didn’t think of,  but it rarely happens for the edge-cases.  And those are the bugs that can be really hard and painful to find and fix.

By now you’re probably wondering what the two bugs are.  The first one is that if an exception occurs during the handling of a request which is eligible for caching, the response with the exception information would be stored in the cache, and the next time that that particular request would be processed while the cached response hadn’t expired yet, you’d simply get the original response with the exception information again instead of actually handling the request again (which might have been handled successfully this time).  The second bug was that if an earlier request in the batch of requests already failed, it could possibly return a valid response later on in the same batch for one of the cached requests if its response hadn’t expired yet.   Pretty stupid huh?  But they were there nevertheless, and sooner or later somebody would’ve tripped over it and it would’ve caused frustration for the user who would run into it, and pain for me because i’d have to go looking for it long after i’d written the code.

Again, i seriously doubt that traditional unit tests would’ve prevented the existence of these 2 problems since it never occurred to me while i was writing it.  The QuickNet tests did find it, even before i added specific tests for the caching functionality to them, which i found pretty impressive and a huge benefit to this sort of testing.  Granted, the learning curve for writing valuable QuickNet tests is steep (i’m not even halfway there IMO) and it takes a lot of effort when you’re starting out with it.  But if it helps me prevent the sort of bugs that are otherwise easily missed and could negatively influence the perception of my project, then i definitely consider it worth it.

Posted in Test Driven Development, agatha, quicknet | 4 Comments »