<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>The Inquisitive Coder - Davy Brion&#039;s Blog &#187; agatha</title> <atom:link href="http://davybrion.com/blog/category/agatha/feed/" rel="self" type="application/rss+xml" /><link>http://davybrion.com/blog</link> <description>inquisitive: adjective. given to inquiry, research, or asking questions; eager for knowledge; intellectually curious</description> <lastBuildDate>Sun, 29 Jan 2012 10:48:12 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>Agatha 1.3 Is Out</title><link>http://davybrion.com/blog/2011/07/agatha-1-3-is-out/</link> <comments>http://davybrion.com/blog/2011/07/agatha-1-3-is-out/#comments</comments> <pubDate>Sat, 16 Jul 2011 10:09:28 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=3389</guid> <description><![CDATA[It's been a while since the last release (september 2010) but there is a major new feature which warrants a new one. And since i've noticed an increased interest in Agatha in the past few weeks, the timing could not have been better. One of the few (IMO) problems that Agatha suffered from, was that [...]]]></description> <content:encoded><![CDATA[<p>It's been a while since the last release (september 2010) but there is a major new feature which warrants a new one. And since i've noticed an increased interest in Agatha in the past few weeks, the timing could not have been better.</p><p>One of the few (IMO) problems that Agatha suffered from, was that it sorta pushed you down the inheritance-road if you wanted to deal with cross-cutting concerns. Well, not anymore. Earlier this year, Bart Deleye started working on a way to use interceptor classes to do the same thing. It enables you to write small interceptor classes which just focus on one thing and have them executed before and after requests are processed. It's sort of similar to global action filters in ASP.NET MVC3, except that it's not attribute based. The order of execution is also guaranteed to be in the order in which the interceptors were registered. Bart and his team have been using this for a while now in their own projects, and recently contributed the changes back to the project. You can read more about these interceptors <a
href="https://github.com/davybrion/Agatha/wiki/RequestHandlerInterceptors" target="_blank">here</a> and you can find some real examples <a
href="https://github.com/davybrion/Agatha/wiki/RequestHandlerInterceptorsExamples" target="_blank">here</a>.</p><p>Another problem that Agatha suffered from was that there was no way to definitively know which type of Response corresponded with a certain type of Request. Because that was important to the interceptors feature, Bart went ahead and implemented something for that as well, so you can now define request/response conventions which can be used in your code. You can read about those <a
href="https://github.com/davybrion/Agatha/wiki/Conventions" target="_blank">here</a>.</p><p>Those are the two most important new features, but some of you will be glad to hear that we finally have nuget packages as well. Because of the problem i described <a
href="http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/" target="_blank">here</a>, i ended up with 8 nuget packages:</p><ul><li><a
href="http://nuget.org/List/Packages/Agatha-Common-Castle-Windsor" target="_blank">Agatha-Common-Castle-Windsor</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-ServiceLayer-Castle-Windsor" target="_blank">Agatha-ServiceLayer-Castle-Windsor</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-Common-Ninject" target="_blank">Agatha-Common-Ninject</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-ServiceLayer-Ninject" target="_blank">Agatha-ServiceLayer-Ninject</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-Common-StructureMap" target="_blank">Agatha-Common-StructureMap</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-ServiceLayer-StructureMap" target="_blank">Agatha-ServiceLayer-StructureMap</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-Common-Unity" target="_blank">Agatha-Common-Unity</a></li><li><a
href="http://nuget.org/List/Packages/Agatha-ServiceLayer-Unity" target="_blank">Agatha-ServiceLayer-Unity</a></li></ul><p>The packages for Castle Windsor, Unity and Ninject each support Silverlight as well. All container dependencies are now based on their latest Nuget packages. With Agatha 1.2, it was clear that the majority of people downloaded the source code instead of the binary release (i presume to build against whatever version of container they used) so you can still get the entire source package on <a
href="http://code.google.com/p/agatha-rrsl/downloads/list" target="_blank">Google Code</a> or on <a
href="https://github.com/davybrion/Agatha/zipball/agatha-1.3" target="_blank">Github</a>. I didn't create another binary package since i figured that most people who want that will be using Nuget anyway.</p><p>The two other changes are:</p><ul><li>now possible to POST to the IWcfRestJsonRequestProcessor (contributed by Andrew Rea)</li><li>our container abstraction allows key-based resolving (contributed by Nikos Baxevanis)</li></ul><p>My favorite part about this release is that all of the new code has been contributed by other people <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>For 1.4, the focus might be more about making Agatha as easy as possible to consume from JavaScript, which may or may not introduce a new REST based service interface.  Though none of that is certain at this point, so we'll see how it goes <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2011%2F07%2Fagatha-1-3-is-out%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2011/07/agatha-1-3-is-out/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2011/07/agatha-1-3-is-out/"  data-text="Agatha 1.3 Is Out" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2011/07/agatha-1-3-is-out/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2011/07/agatha-1-3-is-out/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2011/07/agatha-1-3-is-out/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>A Nuget Packaging Dilemma</title><link>http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/</link> <comments>http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/#comments</comments> <pubDate>Sun, 27 Mar 2011 15:53:05 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=3225</guid> <description><![CDATA[I've been thinking about how Agatha should be packaged for Nuget and i just can't come up with something that i like. The problem is that Nuget misses a concept that is necessary for packages which depend on one of many possible dependencies. Agatha requires an Inversion Of Control container, but it allows you to [...]]]></description> <content:encoded><![CDATA[<p>I've been thinking about how <a
href="http://code.google.com/p/agatha-rrsl/">Agatha</a> should be packaged for <a
href="http://nuget.org/">Nuget</a> and i just can't come up with something that i like. The problem is that Nuget misses a concept that is necessary for packages which depend on one of many possible dependencies.  Agatha requires an Inversion Of Control container, but it allows you to use the container you prefer.  I've talked before about the <a
href="http://davybrion.com/blog/2010/02/when-it-comes-to-ioc-containers-we-seem-to-be-pretty-loyal/">loyalty</a> that many of us show to our preferred container, and i'm pretty sure that forcing users to use a specific container would severely limit the number of possible users Agatha could attract.  So right now, Agatha users need to pick which container they want to use.</p><p>Now how do you make that fit into the Nuget packaging system? Ideally, Nuget would someday support a scenario where i can define that my package requires the user to also select one package from a list of suitable packages but until that's possible i can't really come up with a solution that i like.  Here's what i specifically don't want:</p><ul><li>I don't want the package to include something that the user might not want.</li><li>I don't want to force a particular container on users</li><li>I don't want to ILMerge any container assemblies because that would cause problems if users themselves make use of a container already.</li><li>I don't want to do it like the current <a
href="http://nuget.org/List/Packages/NHibernate">NHibernate 3.1 package</a> because that pretty much guarantees nobody will install it. NHibernate can get away with something like that because it's already an established project.</li></ul><p>Ideally, i'd be able to define the following package structure:</p><ul><li>Agatha-RRSL, requires one of the following packages to be installed (if no selection is made, go with Agatha-Windsor by default):<ul><li>Agatha-Windsor, depends on Agatha-RRSL and Castle Windsor</li><li>Agatha-StructureMap, depends on Agatha-RRSL and StructureMap</li><li>Agatha-NInject, depends on Agatha-RRSL and NInject</li><li>... (one for each supported container)</li></ul></li></ul><p>If that were possible, users wouldn't have to include anything they don't like and it could work together nicely with the packages of the various IOC containers.</p><p>As for how it should be packaged for now, i still have no idea. Suggestions are welcome <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2011%2F03%2Fa-nuget-packaging-dilemma%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/"  data-text="A Nuget Packaging Dilemma" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2011/03/a-nuget-packaging-dilemma/feed/</wfw:commentRss> <slash:comments>26</slash:comments> </item> <item><title>Using Distributed Caching With Agatha</title><link>http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/</link> <comments>http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/#comments</comments> <pubDate>Sun, 27 Feb 2011 18:33:45 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=3116</guid> <description><![CDATA[As you may or may not know, Agatha has supported server-side caching of responses for a while now (it also sports built-in client-side caching actually). But it only came with one in-memory implementation of that cache. And while that implementation works well, it's still just an in-process cache which just isn't sufficient for some scenarios. [...]]]></description> <content:encoded><![CDATA[<p>As you may or may not know, Agatha has supported <a
href="http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/">server-side caching of responses</a> for a while now (it also sports built-in <a
href="http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/">client-side caching</a> actually). But it only came with one in-memory implementation of that cache. And while that implementation works well, it's still just an in-process cache which just isn't sufficient for some scenarios.</p><p>This week i was introduced to <a
href="http://www.membase.org/">Membase</a>, a great distributed caching solution which is very easy to set up. I wanted to see what it would take to make Agatha's server-side caching work with Membase. With a little help from the <a
href="http://memcached.enyim.com/">Enyim Membase client</a>, it turned out to be very easy.  If you want to change the actual caching implementation that Agatha uses, you have to implement 2 interfaces. First, you'll need a custom implementation of the ICache interface:</p><div><pre class="brush: csharp; title: ; notranslate">
    public class MembaseCache : ICache
    {
        private readonly MembaseClient membaseClient;

        public MembaseCache(string region = null)
        {
            // this implementation assumes password-less buckets
            membaseClient = new MembaseClient(region, null);
        }

        public Response GetCachedResponseFor(Request request)
        {
            return membaseClient.Get&lt;Response&gt;(GetKey(request));
        }

        public void Store(Request request, Response response, TimeSpan expiration)
        {
            membaseClient.Store(StoreMode.Set, GetKey(request), response, expiration);
        }

        public void Clear()
        {
            membaseClient.FlushAll();
        }

        private static string GetKey(Request request)
        {
            return string.Format(&quot;{0}_{1}&quot;, request.GetType().FullName, request.GetHashCode());
        }
    }
</pre></div><p>With Agatha's caching, you can use regions in your caching configuration. A region corresponds with a bucket in Membase.  If you don't specify a region name when configuring caching for a response, Agatha will use the default region which is named _defaultRegion.  You will need to create at least the _defaultRegion bucket in your Membase cluster, and you'll also need to create a bucket for each other region you use in your caching configuration.  When your service layer is initialized, Agatha will create an ICache instance for each known region to be used.</p><p>Then you'll need an ICacheProvider implementation:</p><div><pre class="brush: csharp; title: ; notranslate">
    public class MembaseCacheProvider : ICacheProvider
    {
        public ICache BuildCache(string region)
        {
            return new MembaseCache(region);
        }
    }
</pre></div><p>Now, because the Enyim Membase client uses binary serialization of cached objects by default, we're going to provide our own ITranscoder (defined in the Enyim assembly) implementation which uses the DataContractSerializer:</p><div><pre class="brush: csharp; title: ; notranslate">
    public class MembaseTranscoder : ITranscoder
    {
        public CacheItem Serialize(object o)
        {
            using (var stream = new MemoryStream())
            {
                var serializer = new DataContractSerializer(typeof(Response), KnownTypeProvider.GetKnownTypes(null));
                serializer.WriteObject(stream, o);
                var data = stream.ToArray();

                return new CacheItem(((ushort)(((ushort)Type.GetTypeCode(o.GetType())) | 0x100)),
                    new ArraySegment&lt;byte&gt;(data, 0, data.Length));
            }
        }

        public object Deserialize(CacheItem item)
        {
            using (var stream = new MemoryStream(item.Data.Array.Skip(item.Data.Offset).ToArray()))
            {
                var serializer = new DataContractSerializer(typeof(Response), KnownTypeProvider.GetKnownTypes(null));
                return serializer.ReadObject(stream);
            }
        }
    }
</pre></div><p>That's actually all we need to support distributed response caching with Membase.  To use this, you'd need to add this to the configuration file of your service host:</p><div><pre class="brush: xml; title: ; notranslate">
  &lt;membase&gt;
    &lt;servers bucket=&quot;_defaultRegion&quot;&gt;
      &lt;add uri=&quot;http://localhost:8091/pools/default&quot; /&gt;
    &lt;/servers&gt;
    &lt;transcoder type=&quot;Agatha.Common.Caching.MembaseTranscoder, Agatha.Common&quot; /&gt;
  &lt;/membase&gt;
</pre></div><p>Obviously, you'd need a bucket definition for every region that you'd use and you'll probably need a different bucket URI as well <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><p>You'd also need to configure Agatha to use the MembaseCacheProvider implemention:</p><div><pre class="brush: csharp; title: ; notranslate">
            var config = new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(), 
                typeof(HelloWorldRequest).Assembly, typeof(Agatha.Castle.Container))
                            {
                                CacheProviderImplementation = typeof(MembaseCacheProvider)
                            };
            config.Initialize();
</pre></div><p>And that's it... distributed caching of service-layer responses has never been this easy <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><p>Note that i haven't committed this implementation to Agatha's Subversion repository... the plan is to add it in the 2.0 version, which will have many more changes (more on that in a future post).  But if you need it already, or you need inspiration for an implementation that targets a different distributed caching server, the information in this post should get you going.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2011%2F02%2Fusing-distributed-caching-with-agatha%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/"  data-text="Using Distributed Caching With Agatha" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2011/02/using-distributed-caching-with-agatha/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>First NuGet Experience</title><link>http://davybrion.com/blog/2011/01/first-nuget-experience/</link> <comments>http://davybrion.com/blog/2011/01/first-nuget-experience/#comments</comments> <pubDate>Thu, 06 Jan 2011 13:12:54 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category> <category><![CDATA[Software Development]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2989</guid> <description><![CDATA[I haven't used NuGet before, and just now i accidentally triggered its UI while playing around with an ASP.NET MVC3 sample project. When i clicked on the link for online packages, the first thing i saw was this: I didn't even know there was a NuGet package for Agatha, so this was a nice surprise. [...]]]></description> <content:encoded><![CDATA[<p>I haven't used NuGet before, and just now i accidentally triggered its UI while playing around with an ASP.NET MVC3 sample project.  When i clicked on the link for online packages, the first thing i saw was this:</p><p><a
href="http://davybrion.com/blog/wp-content/uploads/2011/01/nuget_first_experience.png" rel="prettyPhoto[2989]"><img
src="http://davybrion.com/blog/wp-content/uploads/2011/01/nuget_first_experience.png" alt="first look at Nuget" title="nuget_first_experience" width="897" height="248" class="aligncenter size-full wp-image-2990" /></a></p><p>I didn't even know there was a NuGet package for Agatha, so this was a nice surprise. I have no idea who made the package, but thanks <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2011%2F01%2Ffirst-nuget-experience%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2011/01/first-nuget-experience/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2011/01/first-nuget-experience/"  data-text="First NuGet Experience" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2011/01/first-nuget-experience/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2011/01/first-nuget-experience/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2011/01/first-nuget-experience/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Agatha 1.2 Is Available</title><link>http://davybrion.com/blog/2010/09/agatha-1-2-is-available/</link> <comments>http://davybrion.com/blog/2010/09/agatha-1-2-is-available/#comments</comments> <pubDate>Tue, 28 Sep 2010 15:54:04 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2720</guid> <description><![CDATA[Agatha 1.2 is now available... keep in mind that this version targets .NET 4 and Silverlight 4 only. The most important change in this version is by far the client-side caching support, but there are some other improvements as well. These are the changes that were made between 1.1 and 1.2: Client-side caching (BREAKING CHANGE: [...]]]></description> <content:encoded><![CDATA[<p>Agatha 1.2 is now available... keep in mind that this version targets .NET 4 and Silverlight 4 only.  The most important change in this version is by far the <a
href="http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/">client-side caching support</a>, but there are some other improvements as well.  These are the changes that were made between 1.1 and 1.2:</p><ul><li>Client-side caching (BREAKING CHANGE: EnableResponseCachingAttribute no longer exists, use the EnableServiceResponseCachingAttribute instead) -> this is not supported in the in-process model</li><li>RequestProcessor now has an AfterHandle(request, response) virtual method which is called after the request has been handled by the handler</li><li>ReceivedResponses now has a Responses property which returns all of the retrieved responses</li><li>ExceptionInfo now has a FaultCode property (string) which will be automatically filled in as long as your BusinessException type contains a FaultCode property (thanks to a patch from Huseyin Tufekcilerli)</li><li>Agatha.Spring has been included (thanks to a patch from Jernej Logar)</li><li>Agatha.StructureMap.Container has been fixed so that it instructs StructureMap to use the default constructors of RequestProcessorProxy and AsyncRequestProcessorProxy (thanks to a patch by Bart Deleye)</li><li>Added BeforeResolvingRequestHandler virtual method to the RequestProcessor which gets called right before a RequestHandler is resolved through the container</li><li>Fixed logging of WCF messages where some requests were logged as "... stream ..." (thanks to patch by Bart Deleye)</li><li>Added Agatha.Ninject.Silveright (thanks to patch by Bart Deleye)</li><li>Updated Agatha.Unity and Agatha.Unity.Silverlight to use the 2.0 version of Unity</li><li>Applied patch from Andrew Rea to improve REST support (xml and json)</li></ul><p>Thanks to everyone who contributed to this release. It's very nice to see the list of contributors growing with each release <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>You can download the source code or the binaries <a
href="http://code.google.com/p/agatha-rrsl/downloads/list">here</a>.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F09%2Fagatha-1-2-is-available%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/09/agatha-1-2-is-available/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/09/agatha-1-2-is-available/"  data-text="Agatha 1.2 Is Available" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/09/agatha-1-2-is-available/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/09/agatha-1-2-is-available/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/09/agatha-1-2-is-available/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>Using Agatha&#8217;s Client-Side Caching</title><link>http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/</link> <comments>http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/#comments</comments> <pubDate>Mon, 09 Aug 2010 14:27:51 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2496</guid> <description><![CDATA[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 [...]]]></description> <content:encoded><![CDATA[<p>Soon after i introduced <a
href="http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/">Agatha's server-side caching</a>, 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 <em>don't</em> 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.</p><p>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 <a
href="http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/">this post</a> for more info on this).</p><p>Here's a small example from the Sample that is included in the Agatha source code:</p><div><pre class="brush: csharp; title: ; notranslate">
    [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);
        }
    }
</pre></div><p>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.</p><p>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 <em>not</em> 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 <em>only</em> include the requests for which no cached response was available.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F08%2Fusing-agathas-client-side-caching%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/"  data-text="Using Agatha&#8217;s Client-Side Caching" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/08/using-agathas-client-side-caching/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Using Agatha&#8217;s Server-Side Caching</title><link>http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/</link> <comments>http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/#comments</comments> <pubDate>Sun, 20 Jun 2010 16:00:46 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/</guid> <description><![CDATA[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.&#160; Obviously, this doesn’t happen automatically and you need to configure this yourself.&#160; Unfortunately, i’ve never really written a post to describe how to do this and [...]]]></description> <content:encoded><![CDATA[<p>One of the most important new additions in the <a
href="http://code.google.com/p/agatha-rrsl/" target="_blank">Agatha</a> 1.1 release is the ability to have the service layer cache responses for requests that are eligible for caching.&#160; Obviously, this doesn’t happen automatically and you need to configure this yourself.&#160; Unfortunately, i’ve never really written a post to describe how to do this and what you need to keep in mind.&#160; Hopefully, all of this will be clear after this post.</p><p>There are only two things you need to do to use Agatha’s server-side caching feature:</p><p><strong>1. Use the EnableServiceResponseCaching attribute</strong></p><p>If you want certain Request-derived types to be eligible for caching, you need to put the EnableServiceResponseCaching attribute on top of them.&#160; 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.&#160; Here’s a simple example:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #00008b">EnableServiceResponseCaching</span>(<span
style="color: purple">Minutes</span> = 10, <span
style="color: purple">Region</span> = <span
style="color: #a31515">&quot;Issues&quot;</span>)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #00008b">GetUnassignedIssuesForProjectRequest</span> : <span
style="color: #00008b">Request</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #00008b">Guid</span> <span
style="color: purple">ProjectId</span> { <span
style="color: #008b8b">get</span>; <span
style="color: #008b8b">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p></div><p>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.&#160; A region is pretty much just a section within the cache.&#160; If you don’t specify a region, each response will be placed in the default region.&#160; If you do specify one, each cached response for that region is placed within that section.&#160; 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).</p><p>The expiration can be configured by providing a number of hours, minutes or seconds (or a combination of those three) to the attribute.</p><p>Now obviously, Agatha needs a way to differentiate between multiple instances of the GetUnassignedIssuesForProjectRequest class.&#160; 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.&#160; So that brings us to the next thing you need to do:</p><p><strong>2. Override the Equals and GetHashCode methods</strong></p><p>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.&#160; 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.&#160; 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.&#160; So in this case, our request class needs to look like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #00008b">EnableServiceResponseCaching</span>(<span
style="color: purple">Minutes</span> = 10, <span
style="color: purple">Region</span> = <span
style="color: #a31515">&quot;Issues&quot;</span>)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #00008b">GetUnassignedIssuesForProjectRequest</span> : <span
style="color: #00008b">Request</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #00008b">Guid</span> <span
style="color: purple">ProjectId</span> { <span
style="color: #008b8b">get</span>; <span
style="color: #008b8b">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> <span
style="color: #008b8b">Equals</span>(<span
style="color: #00008b">GetUnassignedIssuesForProjectRequest</span> other)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">null</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">this</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> other.<span
style="color: purple">ProjectId</span>.<span
style="color: #008b8b">Equals</span>(<span
style="color: purple">ProjectId</span>);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">bool</span> <span
style="color: #008b8b">Equals</span>(<span
style="color: blue">object</span> obj)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">null</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">this</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (obj.<span
style="color: #008b8b">GetType</span>() <span
style="color: #008b8b">!=</span> <span
style="color: blue">typeof</span>(<span
style="color: #00008b">GetUnassignedIssuesForProjectRequest</span>)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: #008b8b">Equals</span>((<span
style="color: #00008b">GetUnassignedIssuesForProjectRequest</span>)obj);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">int</span> <span
style="color: #008b8b">GetHashCode</span>()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: purple">ProjectId</span>.<span
style="color: #008b8b">GetHashCode</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p></div><p>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.&#160; Note that this doesn’t mean that your request types need to be value objects in the truest sense of the term.&#160; 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 <em>set of values</em> that you’re using to determine equality.&#160; 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).</p><p>It’s very important to really consider which properties you want to include in the equality check and the hashcode calculation.&#160; If your request type inherits from some base request (typically one that contains user credentials and stuff like that), then you typically <em>don’t </em>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.&#160; I’d recommend writing enough tests to verify that your equality checks and hashcode calculations indeed behave the way you <em>want</em> 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.</p><p>A question that came up recently in the <a
href="http://groups.google.com/group/agatha-rrsl" target="_blank">Agatha discussion group</a> was how to implement the Equals and GetHashCode method for request types for which each instance should really be considered equal.&#160; For instance, a request type like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #00008b">EnableServiceResponseCaching</span>(<span
style="color: purple">Hours</span> = 2, <span
style="color: purple">Region</span> = <span
style="color: #a31515">&quot;ReferenceData&quot;</span>)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #00008b">GetAllCountriesRequest</span> : <span
style="color: #00008b">Request</span> {}</p><p
style="margin: 0px">&#160;</p></div><p>In this case, the default Equals and GetHashCode implementations will be reference-based and not value based.&#160; But as you can see, there are no values to differentiate between requests.&#160; 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?&#160; Well, the solution isn’t very nice but it is pretty simple.&#160; You can just introduce a dummy field with a fixed value:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #00008b">EnableServiceResponseCaching</span>(<span
style="color: purple">Hours</span> = 2, <span
style="color: purple">Region</span> = <span
style="color: #a31515">&quot;ReferenceData&quot;</span>)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #00008b">GetAllCountriesRequest</span> : <span
style="color: #00008b">Request</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">string</span> <span
style="color: purple">dummyValue</span> = <span
style="color: blue">typeof</span>(<span
style="color: #00008b">GetAllCountriesRequest</span>).<span
style="color: purple">FullName</span>;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> <span
style="color: #008b8b">Equals</span>(<span
style="color: #00008b">GetAllCountriesRequest</span> other)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">null</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">this</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: #008b8b">Equals</span>(other.<span
style="color: purple">dummyValue</span>, <span
style="color: purple">dummyValue</span>);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">bool</span> <span
style="color: #008b8b">Equals</span>(<span
style="color: blue">object</span> obj)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">null</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (<span
style="color: #008b8b">ReferenceEquals</span>(<span
style="color: blue">this</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (obj.<span
style="color: #008b8b">GetType</span>() <span
style="color: #008b8b">!=</span> <span
style="color: blue">typeof</span>(<span
style="color: #00008b">GetAllCountriesRequest</span>)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: #008b8b">Equals</span>((<span
style="color: #00008b">GetAllCountriesRequest</span>)obj);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">int</span> <span
style="color: #008b8b">GetHashCode</span>()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: purple">dummyValue</span>.<span
style="color: #008b8b">GetHashCode</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p></div><p>Now, every instance of the GetAllCountriesRequest will be considered equal to each other and they’ll all return the same hashcode as well.&#160; So every incoming instance of this request will return the same cached response (once it’s been cached that is).</p><p>That’s pretty much it.&#160; 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.&#160; 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.</p><p>One final word on the usage of regions.&#160; If you’re caching responses, then you typically want a way to remove stale responses from the cache.&#160; 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.&#160; 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.</p><p>As always with caching: be careful in how you use it, and make sure you think it through <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F06%2Fusing-agathas-server-side-caching%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/"  data-text="Using Agatha&rsquo;s Server-Side Caching" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/06/using-agathas-server-side-caching/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>Consuming An Agatha Service From A Non-Agatha-Aware Client</title><link>http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/</link> <comments>http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/#comments</comments> <pubDate>Fri, 14 May 2010 13:49:35 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/</guid> <description><![CDATA[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, [...]]]></description> <content:encoded><![CDATA[<p>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 <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>First of all, make sure your service exposes its metadata.&#160; You do this in the usual WCF fashion:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">behaviors</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">serviceBehaviors</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">behavior</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">RequestProcessorBehavior</span>&quot;<span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">serviceMetadata</span><span
style="color: blue"> </span><span
style="color: red">httpGetEnabled</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">true</span>&quot;<span
style="color: blue">/&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">dataContractSerializer</span><span
style="color: blue"> </span><span
style="color: red">maxItemsInObjectGraph</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">2147483647</span>&quot;<span
style="color: blue">/&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">serviceThrottling</span><span
style="color: blue"> </span><span
style="color: red">maxConcurrentCalls</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">500</span>&quot;<span
style="color: blue"> </span><span
style="color: red">maxConcurrentInstances</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">500</span>&quot;<span
style="color: blue">/&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">behavior</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">serviceBehaviors</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">behaviors</span><span
style="color: blue">&gt;</span></p></div><p>&#160;</p><p>The serviceMetadata element with the httpGetEnabled=”true” attribute is the important one in the snippet above.</p><p>After that, you can simply generate a service proxy through visual studio or svcutil or whatever:</p><p><a
href="http://davybrion.com/pictures/ConsumingAnAgathaServiceFromANonAgathaAw_DF1A/add_service_reference.png" rel="prettyPhoto[2314]"><img
style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="add_service_reference" border="0" alt="add_service_reference" src="http://davybrion.com/pictures/ConsumingAnAgathaServiceFromANonAgathaAw_DF1A/add_service_reference_thumb.png" width="635" height="510" /></a></p><p>Now you can write the following code to communicate with your Agatha Service Layer:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px"><span
style="color: blue">using</span> System;</p><p
style="margin: 0px"><span
style="color: blue">using</span> Sample.NonAgathaAwareClient.MyAgathaService;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px"><span
style="color: blue">namespace</span> Sample.NonAgathaAwareClient</p><p
style="margin: 0px">{</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">class</span> <span
style="color: #2b91af">Program</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">static</span> <span
style="color: blue">void</span> Main(<span
style="color: blue">string</span>[] args)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">using</span> (<span
style="color: blue">var</span> proxy = <span
style="color: blue">new</span> MyAgathaService.<span
style="color: #2b91af">WcfRequestProcessorClient</span>())</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> responses = proxy.ProcessRequests(<span
style="color: blue">new</span>[] { <span
style="color: blue">new</span> <span
style="color: #2b91af">HelloWorldRequest</span>() });</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> helloWorldResponse = (<span
style="color: #2b91af">HelloWorldResponse</span>)responses[0];</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Console</span>.WriteLine(helloWorldResponse.Message);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Console</span>.Read();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">}</p><p
style="margin: 0px">&#160;</p></div><p
style="margin: 0px">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.&#160; The client-side usage model is of course as bad as it always is with standard WCF (for more information, be sure to read: <a
href="http://davybrion.com/blog/2009/07/why-i-dislike-classic-or-typical-wcf-usage/" target="_blank">Why I Dislike Classic Or Typical WCF Usage</a>) but if you’re willing to put up with it, then at least you can <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">This also means that you should be able to generate service proxies for other platforms as well, as long as they support SOAP services.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F05%2Fconsuming-an-agatha-service-from-a-non-agatha-aware-client%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/"  data-text="Consuming An Agatha Service From A Non-Agatha-Aware Client" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/05/consuming-an-agatha-service-from-a-non-agatha-aware-client/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Agatha 1.1 Is Out</title><link>http://davybrion.com/blog/2010/05/agatha-1-1-is-out/</link> <comments>http://davybrion.com/blog/2010/05/agatha-1-1-is-out/#comments</comments> <pubDate>Sun, 09 May 2010 12:07:51 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/05/agatha-1-1-is-out/</guid> <description><![CDATA[I just released the 1.1 version of Agatha.&#160; 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.&#160; So, the 1.1 version is still targeting .NET 3.5 and Silverlight [...]]]></description> <content:encoded><![CDATA[<p>I just released the 1.1 version of Agatha.&#160; 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.&#160; 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.</p><p>These are the changes between the 1.0.1 and the 1.1 release:</p><ul><li>Support for the NInject container (patch contributed by Ian Davis).</li><li>First version of the <a
href="http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/" target="_blank">server side caching layer</a>.&#160; Consider this implementation to be experimental and there are most likely plenty of issues with it.&#160; Issues that pop up will obviously be fixed in further 1.1.x releases and the trunk as well.&#160;</li><li>AsyncRequestDispatcher and RequestDispatcher now have a virtual AfterSendingRequests virtual method where you can add some custom code if you need to.</li><li>Both Request/Response types and RequestHandler can now be located in multiple assemblies (patch contributed by Jason Diamond)</li><li>Castle Windsor binaries have been updated to version 2.1</li><li>Castle support for Silverlight has been added</li><li>The Process method of the IWcfRequestProcessor service contract now allows transaction flowing</li><li>All configuration classes have been made a bit more fluently (thanks to Mark Meyers)</li><li>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</li><li>Support for the StructureMap container (patch contributed by Andrew Rea)</li><li>The IWcfRequestProcessor service contract now <a
href="http://weblogs.asp.net/andrewrea/archive/2010/03/09/compiling-examples-for-consuming-the-rest-endpoints-for-wcf-service-using-agatha.aspx" target="_blank">supports REST (JSON + XML)</a> (patch contributed by Andrew Rea)</li><li>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.</li><li>The serverside RequestProcessor contains a few extra virtual methods which enables you to customize how exceptions are logged (patch contributed by Emil Ingerslev)</li><li>Fixed NullReferenceException in MessageInspector when using one-way requests in combination with INFO logging</li></ul><p>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.</p><p>You can download the 1.1 version <a
href="http://code.google.com/p/agatha-rrsl/downloads/list" target="_blank">here</a>.</p><p>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.&#160; And yes, that will include some form of client-side caching <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F05%2Fagatha-1-1-is-out%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/05/agatha-1-1-is-out/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/05/agatha-1-1-is-out/"  data-text="Agatha 1.1 Is Out" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/05/agatha-1-1-is-out/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/05/agatha-1-1-is-out/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/05/agatha-1-1-is-out/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>Consuming Multiple Agatha Services</title><link>http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/</link> <comments>http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/#comments</comments> <pubDate>Sat, 08 May 2010 17:21:35 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/</guid> <description><![CDATA[One question that occasionally comes up is how a client can use multiple Agatha services.&#160; 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 [...]]]></description> <content:encoded><![CDATA[<p>One question that occasionally comes up is how a client can use multiple Agatha services.&#160; 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.</p><p>First of all, the Silverlight client’s WCF config has 2 defined endpoints:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">client</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">endpoint</span><span
style="color: blue"> </span><span
style="color: red">binding</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">basicHttpBinding</span>&quot;<span
style="color: blue"> </span><span
style="color: red">bindingConfiguration</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">firstServiceBinding</span>&quot;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span
style="color: red">contract</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">Agatha.Common.WCF.IWcfRequestProcessor</span>&quot;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">firstService</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">endpoint</span><span
style="color: blue"> </span><span
style="color: red">binding</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">basicHttpBinding</span>&quot;<span
style="color: blue"> </span><span
style="color: red">bindingConfiguration</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">secondServiceBinding</span>&quot;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span
style="color: red">contract</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">Agatha.Common.WCF.IWcfRequestProcessor</span>&quot;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">secondService</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">client</span><span
style="color: blue">&gt;</span></p></div><p>&#160;</p><p>Notice that each endpoint has a defined name.</p><p>Now you can create 2 new service proxies which inherit from Agatha’s proxy:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">FirstServiceProxy</span> : Agatha.Common.WCF.<span
style="color: #2b91af">AsyncRequestProcessorProxy</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> FirstServiceProxy()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; : <span
style="color: blue">base</span>(<span
style="color: #a31515">&quot;firstService&quot;</span>, GetServiceUrl()) {}</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">static</span> <span
style="color: blue">string</span> GetServiceUrl()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// return the correct url from somewhere...</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">SecondServiceProxy</span> : Agatha.Common.WCF.<span
style="color: #2b91af">AsyncRequestProcessorProxy</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> SecondServiceProxy()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; : <span
style="color: blue">base</span>(<span
style="color: #a31515">&quot;secondService&quot;</span>, GetServiceUrl()) {}</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">static</span> <span
style="color: blue">string</span> GetServiceUrl()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// return the correct url from somewhere...</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>Once you have those proxies, you can create new request dispatchers, which also inherit from Agatha’s:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">IFirstDispatcher</span> : Agatha.Common.<span
style="color: #2b91af">IAsyncRequestDispatcher</span> {}</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">FirstDispatcher</span> : Agatha.Common.<span
style="color: #2b91af">AsyncRequestDispatcher</span>, <span
style="color: #2b91af">IFirstDispatcher</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> FirstDispatcher(<span
style="color: #2b91af">FirstServiceProxy</span> requestProcessor) : <span
style="color: blue">base</span>(requestProcessor) { }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">ISecondDispatcher</span> : Agatha.Common.<span
style="color: #2b91af">IAsyncRequestDispatcher</span> {}</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">SecondDispatcher</span> : Agatha.Common.<span
style="color: #2b91af">AsyncRequestDispatcher</span>, <span
style="color: #2b91af">ISecondDispatcher</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> SecondDispatcher(<span
style="color: #2b91af">SecondServiceProxy</span> requestProcessor) : <span
style="color: blue">base</span>(requestProcessor) { }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>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.&#160; 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:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">IFirstDispatcherFactory</span> : Agatha.Common.<span
style="color: #2b91af">IAsyncRequestDispatcherFactory</span> {}</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">FirstDispatcherFactory</span> : <span
style="color: #2b91af">IFirstDispatcherFactory</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IAsyncRequestDispatcher</span> CreateAsyncRequestDispatcher()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: #2b91af">IoC</span>.Container.Resolve&lt;<span
style="color: #2b91af">IFirstDispatcher</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">ISecondDispatcherFactory</span> : Agatha.Common.<span
style="color: #2b91af">IAsyncRequestDispatcherFactory</span> {}</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">SecondDispatcherFactory</span> : <span
style="color: #2b91af">ISecondDispatcherFactory</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IAsyncRequestDispatcher</span> CreateAsyncRequestDispatcher()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: #2b91af">IoC</span>.Container.Resolve&lt;<span
style="color: #2b91af">ISecondDispatcher</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>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.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F05%2Fconsuming-multiple-agatha-services%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/"  data-text="Consuming Multiple Agatha Services" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/05/consuming-multiple-agatha-services/feed/</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>Looking For Agatha Testimonials</title><link>http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/</link> <comments>http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/#comments</comments> <pubDate>Wed, 05 May 2010 15:02:51 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/</guid> <description><![CDATA[I’ve noticed recently that i’m gradually getting more visitors to this blog through Agatha’s project site.&#160; Pretty glad to see that, though the numbers are still very low.&#160; 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.&#160; Which is kinda [...]]]></description> <content:encoded><![CDATA[<p>I’ve noticed recently that i’m gradually getting more visitors to this blog through <a
href="http://code.google.com/p/agatha-rrsl" target="_blank">Agatha’s project site</a>.&#160; Pretty glad to see that, though the numbers are still very low.&#160; 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.&#160; 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.&#160;&#160;</p><p>So, i figured i’d just ask you guys.&#160; 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).&#160; 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.&#160; 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.</p><p>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.</p><p>Thanks!</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F05%2Flooking-for-agatha-testimonials%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/"  data-text="Looking For Agatha Testimonials" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/05/looking-for-agatha-testimonials/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Securing Your Agatha Service Layer</title><link>http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/</link> <comments>http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/#comments</comments> <pubDate>Wed, 27 Jan 2010 20:05:11 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/</guid> <description><![CDATA[The question of how to implement security for an Agatha Service Layer is one that comes up frequently.&#160; 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.&#160; There’s already plenty of information available [...]]]></description> <content:encoded><![CDATA[<p>The question of how to implement security for an Agatha Service Layer is one that comes up frequently.&#160; 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.&#160; 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.&#160; What i am going to cover is the approach that we typically use for our Agatha service layers.</p><p>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.&#160;&#160; But first, how do we get the authentication-related data from the client to the service?</p><p>In each project i use Agatha in, i always have a MyProjectRequest and MyProjectResponse base class:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">MyProjectRequest</span> : <span
style="color: #2b91af">Request</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">string</span> UserName { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">byte</span>[] PasswordHash { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">MyProjectResponse</span> : <span
style="color: #2b91af">Response</span> {}</p></div><p>&#160;</p><p>Each request in the project inherits from this base request, and each response inherits from the base response.&#160; 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.</p><p>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.&#160; I do this by using a custom request dispatcher:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">MyProjectAsyncRequestDispatcher</span> : <span
style="color: #2b91af">AsyncRequestDispatcher</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">readonly</span> <span
style="color: #2b91af">IUserContext</span> userContext;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> MyProjectAsyncRequestDispatcher(<span
style="color: #2b91af">IAsyncRequestProcessor</span> requestProcessor, <span
style="color: #2b91af">IUserContext</span> userContext) : <span
style="color: blue">base</span>(requestProcessor)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">this</span>.userContext = userContext;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">override</span> <span
style="color: blue">void</span> BeforeSendingRequests(<span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: #2b91af">Request</span>&gt; requestsToProcess)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">base</span>.BeforeSendingRequests(requestsToProcess);</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">foreach</span> (<span
style="color: blue">var</span> myProjectRequest <span
style="color: blue">in</span> requestsToProcess.OfType&lt;<span
style="color: #2b91af">MyProjectRequest</span>&gt;())</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; myProjectRequest.UserName = userContext.UserName;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; myProjectRequest.PasswordHash = userContext.PasswordHash;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>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.&#160;&#160; Now, in this example you can see that i add the authentication data to <em>every request </em>in a batch, even though the batch will be sent in one roundtrip.&#160; 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.&#160; 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.&#160; I’ll get back to this point later on.</p><p>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.&#160; This is easily done during Agatha’s client-side configuration:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> <span
style="color: #2b91af">ClientConfiguration</span>(<span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MyProjectRequest</span>).Assembly, <span
style="color: blue">new</span> Agatha.Castle.<span
style="color: #2b91af">Container</span>(myContainerWrapper))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AsyncRequestDispatcherImplementation = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MyProjectAsyncRequestDispatcher</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Initialize();</p></div><p>&#160;</p><p>Keep in mind that you still have to register your IUserContext with the container on your own though.&#160;</p><p>With that in place, we are sure that each request that comes from <em>our clients</em> always contains the proper authentication data.&#160; Now we need to make sure that we actually authenticate these requests within the service layer.&#160; 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.</p><p>We’ll first cover the option of using a custom Request Processor.&#160;&#160; You could create one like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">MyProjectRequestProcessor</span> : <span
style="color: #2b91af">RequestProcessor</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">readonly</span> <span
style="color: #2b91af">IAuthenticator</span> authenticator;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> MyProjectRequestProcessor(<span
style="color: #2b91af">IAuthenticator</span> authenticator, <span
style="color: #2b91af">ServiceLayerConfiguration</span> serviceLayerConfiguration, <span
style="color: #2b91af">ICacheManager</span> cacheManager)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; : <span
style="color: blue">base</span>(serviceLayerConfiguration, cacheManager)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">this</span>.authenticator = authenticator;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">override</span> <span
style="color: blue">void</span> BeforeHandle(<span
style="color: #2b91af">Request</span> request)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> myProjectRequest = request <span
style="color: blue">as</span> <span
style="color: #2b91af">MyProjectRequest</span>;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (myProjectRequest != <span
style="color: blue">null</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (!authenticator.AreValidCredentials(myProjectRequest.UserName, myProjectRequest.PasswordHash))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">throw</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">MySecurityException</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>The BeforeHandle virtual method is called right before the request is passed to its Request Handler to be handled.&#160; Note that this Request Processor would authenticate <em>every </em>request.&#160; If you want a Request Processor that only authenticates the first request, you could do so like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">MyProjectRequestProcessor</span> : <span
style="color: #2b91af">RequestProcessor</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">readonly</span> <span
style="color: #2b91af">IAuthenticator</span> authenticator;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> MyProjectRequestProcessor(<span
style="color: #2b91af">IAuthenticator</span> authenticator, <span
style="color: #2b91af">ServiceLayerConfiguration</span> serviceLayerConfiguration, <span
style="color: #2b91af">ICacheManager</span> cacheManager)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; : <span
style="color: blue">base</span>(serviceLayerConfiguration, cacheManager)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">this</span>.authenticator = authenticator;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">override</span> <span
style="color: blue">void</span> BeforeProcessing(<span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: #2b91af">Request</span>&gt; requests)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> myProjectRequest = (<span
style="color: #2b91af">MyProjectRequest</span>)requests.ElementAt(0);</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (!authenticator.AreValidCredentials(myProjectRequest.UserName, myProjectRequest.PasswordHash))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">throw</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">MySecurityException</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>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.&#160; 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.&#160; Yes, you can guarantee that each request coming from <em>your clients</em> contains the proper authentication data.&#160; What you simply can’t guarantee however is what other people or custom clients can send to your service layer.&#160; 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.&#160; 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.&#160; Unless of course, you reject this approach and authenticate every single request.</p><p>As for the MySecurityException type, that’s up to you as well.&#160; 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.&#160; 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.</p><p>To configure Agatha to use your custom Request Processor, your configuration code would look like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> <span
style="color: #2b91af">ServiceLayerConfiguration</span>(<span
style="color: #2b91af">Assembly</span>.GetExecutingAssembly(), <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MyProjectRequest</span>).Assembly,</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> Agatha.Castle.<span
style="color: #2b91af">Container</span>(containerWrapper))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RequestProcessorImplementation = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MyProjectRequestProcessor</span>),</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SecurityExceptionType = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MySecurityException</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Initialize();</p></div><p>&#160;</p><p>Another alternative is to create a base Request Handler for your project and to have each Request Handler inherit from it.&#160; Something like this, for instance:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">abstract</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">MyProjectRequestHandler</span>&lt;TRequest, TResponse&gt; : <span
style="color: #2b91af">RequestHandler</span>&lt;TRequest, TResponse&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">where</span> TRequest : <span
style="color: #2b91af">MyProjectRequest</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IAuthenticator</span> Authenticator { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">void</span> BeforeHandle(TRequest request)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">base</span>.BeforeHandle(request);</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (!Authenticator.AreValidCredentials(request.UserName, request.PasswordHash))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">throw</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">MySecurityException</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Authorize(request);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">virtual</span> <span
style="color: blue">void</span> Authorize(TRequest request) {}</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>In case you’re wondering why i’m using Setter-injection here instead of Constructor-injection, read <a
href="http://davybrion.com/blog/2009/11/constructor-injection-vs-sette-injection/" target="_blank">this</a>.</p><p>I typically prefer the custom Request Handler approach for authentication.&#160; In most applications that we write, authentication is not enough and we need custom authorization checks for many requests.&#160; So i’m going to need a base Request Handler which introduces the virtual Authorize method anyway.&#160; So i might as well do my authentication check right before it.</p><p>With the custom Request Handler approach, you probably still want to configure Agatha to use your custom security exception type:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> <span
style="color: #2b91af">ServiceLayerConfiguration</span>(<span
style="color: #2b91af">Assembly</span>.GetExecutingAssembly(), <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MyProjectRequest</span>).Assembly,</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> Agatha.Castle.<span
style="color: #2b91af">Container</span>(containerWrapper))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SecurityExceptionType = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">MySecurityException</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Initialize();</p></div><p>&#160;</p><p>And then you just need to let your own Request Handlers inherit from your MyProjectRequestHandler.&#160; Authentication will be performed for each request by default, and you can easily add specific authorization logic for every request.&#160;</p><p>And those are pretty much the options you have to secure your Agatha Service Layer.&#160;&#160; Oh, and be sure to only expose your Service Layer through SSL <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F01%2Fsecuring-your-agatha-service-layer%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/"  data-text="Securing Your Agatha Service Layer" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/01/securing-your-agatha-service-layer/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Agatha Vs NServiceBus?</title><link>http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/</link> <comments>http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/#comments</comments> <pubDate>Tue, 26 Jan 2010 20:50:51 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category> <category><![CDATA[nservicebus]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/</guid> <description><![CDATA[Ever since i open sourced Agatha, i’ve gotten questions from people who are wondering whether they should use Agatha or NServiceBus.&#160; I’ve also gotten questions about things that people wanted to do with Agatha but that aren’t really supported.&#160; And i’ve also noticed that people were coming to my site with search keywords like “agatha [...]]]></description> <content:encoded><![CDATA[<p>Ever since i open sourced <a
href="http://code.google.com/p/agatha-rrsl/" target="_blank">Agatha</a>, i’ve gotten questions from people who are wondering whether they should use Agatha or <a
href="http://nservicebus.com/" target="_blank">NServiceBus</a>.&#160; I’ve also gotten questions about things that people wanted to do with Agatha but that aren’t really supported.&#160; And i’ve also noticed that people were coming to my site with search keywords like “agatha vs nservicebus”.&#160; The thing is, they are hardly comparable.</p><p>Agatha is a Request/Response Service Layer framework.&#160; 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.&#160; 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.&#160; 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.&#160; 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.&#160; 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.&#160; That’s probably all it’ll ever do.&#160; In short, it’s just an upgrade over your typical WCF services.</p><p>NServiceBus on the other hand also does Request/Response, but that’s just one of the things it can do.&#160; Again, Agatha is essentially an RPC or RMI framework whereas NServiceBus is built on top of one-way messaging technology.&#160; This allows for much more possibilities when it comes to communicating between different applications or different parts or processes within the same application boundary.&#160; A great overview of those possibilities can be found <a
href="http://nservicebus.com/ArchitecturalPrinciples.aspx" target="_blank">here</a>.&#160; 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.&#160; For one, the ‘Store &amp; Forward’ messaging model from NServiceBus might seem similar to Agatha’s one-way requests on first sight, but there are some very important differences.&#160; If you send a fire-and-forget request with Agatha, and the service is currently down, then that request is essentially lost.&#160; 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.&#160; From a reliability point of view, that’s obviously a tremendous improvement over what Agatha can offer you.&#160; Another area where NServiceBus truly shines (IMO) is in its <a
href="http://en.wikipedia.org/wiki/Publish_subscribe" target="_blank">Publish/Subscribe</a> implementation.&#160; Some people have asked me if i’ll ever provide something like that in Agatha and the answer has always been ‘no’.&#160;&#160; 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.&#160;&#160; 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 <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><p>So which one is more suitable for you or your applications? As with every technology choice, it depends.&#160; Agatha is great for most typical business applications.&#160; 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<em> one </em>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.&#160; With superior reliability i particularly mean the ability to still process received messages once the service layer comes back up after having been unavailable.&#160; 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.&#160; 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.</p><p>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.&#160; 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.&#160;&#160; 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.&#160; With NServiceBus, you’d only need to share an assembly containing the types of the messages.&#160; With Agatha, you either need to share an assembly with shared request/response types or use proxies for them <em>and</em> you would also have to <em>know</em> about the other applications since you’d need to access their services directly.&#160; This can get quite ugly pretty fast.</p><p>And in some cases, you can just use both of them at the same time.&#160; 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.&#160; Neither of the applications knows about the existence of the other… the only thing they share is one assembly with some shared message types.&#160; 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.</p><p>As with many things, it’s just a matter of choosing the right tool for the right job.&#160; Hopefully, this post will help some of you make that decision should you need to make it in the future <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2010%2F01%2Fagatha-vs-nservicebus%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/"  data-text="Agatha Vs NServiceBus?" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2010/01/agatha-vs-nservicebus/feed/</wfw:commentRss> <slash:comments>8</slash:comments> </item> <item><title>Testing Agatha&#8217;s Caching Functionality With QuickNet</title><link>http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/</link> <comments>http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/#comments</comments> <pubDate>Thu, 24 Dec 2009 00:12:16 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category> <category><![CDATA[quicknet]]></category> <category><![CDATA[testing]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2126</guid> <description><![CDATA[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.&#160; 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.&#160; I do want to ask you to [...]]]></description> <content:encoded><![CDATA[<p>In this post i’m going to give you a very detailed explanation of a <a
href="http://code.google.com/p/quicknet/" target="_blank">QuickNet</a> test that i wrote for Agatha’s caching layer.&#160; 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.&#160; 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.&#160; If you have problems with that, you might be interested in more <a
href="http://osherove.com/" target="_blank">conservative reading on automated testing</a>.&#160; Still here? Alright, let’s get started.&#160; Please stay focused throughout, because you will need it :p</p><p>First of all, requests whose response is eligible for caching must override the Equals method and the GetHashCode method.&#160; I’ll use the following two request/response combinations for this test:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #2b91af">EnableResponseCaching</span>(Seconds = 1)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">FirstCachedRequest</span> : <span
style="color: #2b91af">Request</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">string</span> String { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> Equals(<span
style="color: #2b91af">FirstCachedRequest</span> other)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">null</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">this</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> Equals(other.String, String);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">bool</span> Equals(<span
style="color: blue">object</span> obj)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">null</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">this</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (obj.GetType() != <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">FirstCachedRequest</span>)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> Equals((<span
style="color: #2b91af">FirstCachedRequest</span>)obj);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">int</span> GetHashCode()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> (String != <span
style="color: blue">null</span> ? String.GetHashCode() : 0);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">FirstCachedResponse</span> : <span
style="color: #2b91af">Response</span> { }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #2b91af">EnableResponseCaching</span>(Seconds = 2)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">SecondCachedRequest</span> : <span
style="color: #2b91af">Request</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">int</span> Integer { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> Equals(<span
style="color: #2b91af">SecondCachedRequest</span> other)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">null</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">this</span>, other)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> other.Integer == Integer;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">bool</span> Equals(<span
style="color: blue">object</span> obj)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">null</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (ReferenceEquals(<span
style="color: blue">this</span>, obj)) <span
style="color: blue">return</span> <span
style="color: blue">true</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (obj.GetType() != <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">SecondCachedRequest</span>)) <span
style="color: blue">return</span> <span
style="color: blue">false</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> Equals((<span
style="color: #2b91af">SecondCachedRequest</span>)obj);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">int</span> GetHashCode()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> Integer;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">SecondCachedResponse</span> : <span
style="color: #2b91af">Response</span> {}</p></div><p>&#160;</p><p>Agatha’s Request Processor should cache responses for requests that are eligible for caching, and when subsequent requests need to be processed which are <em>equal</em> (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.</p><p>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):</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">CacheManagerSpy</span> : <span
style="color: #2b91af">CacheManager</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">List</span>&lt;<span
style="color: #2b91af">CacheEntry</span>&gt; cacheEntries;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">List</span>&lt;<span
style="color: #2b91af">Response</span>&gt; returnedCachedResponses;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: #2b91af">CacheEntry</span>&gt; CacheEntries</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">get</span> { <span
style="color: blue">return</span> cacheEntries; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: #2b91af">Response</span>&gt; ReturnedCachedResponses</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">get</span> { <span
style="color: blue">return</span> returnedCachedResponses; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> CacheManagerSpy(<span
style="color: #2b91af">CacheConfiguration</span> configuration, <span
style="color: #2b91af">ICacheProvider</span> cacheProvider) : <span
style="color: blue">base</span>(configuration, cacheProvider)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Clear();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">void</span> Clear()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cacheEntries = <span
style="color: blue">new</span> <span
style="color: #2b91af">List</span>&lt;<span
style="color: #2b91af">CacheEntry</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; returnedCachedResponses = <span
style="color: blue">new</span> <span
style="color: #2b91af">List</span>&lt;<span
style="color: #2b91af">Response</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">override</span> <span
style="color: #2b91af">Response</span> GetCachedResponseFor(<span
style="color: #2b91af">Request</span> request, <span
style="color: blue">string</span> region)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> cachedResponse = <span
style="color: blue">base</span>.GetCachedResponseFor(request, region);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; returnedCachedResponses.Add(cachedResponse);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> cachedResponse;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">override</span> <span
style="color: blue">void</span> StoreInCache(<span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response, <span
style="color: #2b91af">TimeSpan</span> expiration, <span
style="color: blue">string</span> region)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cacheEntries.Add(<span
style="color: blue">new</span> <span
style="color: #2b91af">CacheEntry</span>(request, response, expiration, region));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">base</span>.StoreInCache(request, response, expiration, region);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">CacheEntry</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Request</span> Request { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Response</span> Response { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">TimeSpan</span> Expiration { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">string</span> Region { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> CacheEntry(<span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response, <span
style="color: #2b91af">TimeSpan</span> expiration, <span
style="color: blue">string</span> region)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Request = request;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Response = response;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Expiration = expiration;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Region = region;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>This Spy basically gives me the ability to see which entries are stored in the cache, and which responses have been returned.</p><p>Now i can create a QuickNet Acid test.&#160; 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.</p><p>First of all, here’s the definition of the test:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">RequestProcessorCachingSpecs</span> : <span
style="color: #2b91af">AcidTest</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> RequestProcessorCachingSpecs() : <span
style="color: blue">base</span>(10, 2000) { }</p></div><p>&#160;</p><p>The 10 means that QuickNet will perform 10 testruns.&#160; The 2000 means that each testrun will contain 2000 executions of the defined transitions.&#160; Don’t worry yet about what a transition is, i’ll get to that later on in the post.</p><p>We’ll also need some fields to access some of the classes that will be used in this test:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">static</span> <span
style="color: #2b91af">IRequestHandler</span>&lt;<span
style="color: #2b91af">FirstCachedRequest</span>&gt; firstCachedRequestHandler;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">static</span> <span
style="color: #2b91af">IRequestHandler</span>&lt;<span
style="color: #2b91af">SecondCachedRequest</span>&gt; secondCachedRequestHandler;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">static</span> <span
style="color: #2b91af">IRequestProcessor</span> requestProcessor;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">static</span> <span
style="color: #2b91af">CacheManagerSpy</span> cacheManager;</p></div><p>&#160;</p><p>Yeah, i know what you’re thinking.&#160; Static is bad right?&#160; 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).&#160; Anyway, forget about the static keyword for a second and keep reading.</p><p>Now we can implement the SetUp of our testrun:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">override</span> <span
style="color: blue">void</span> SetUp()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">IoC</span>.Container = <span
style="color: blue">new</span> Agatha.Castle.<span
style="color: #2b91af">Container</span>();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> serviceLayerConfiguration = <span
style="color: blue">new</span> <span
style="color: #2b91af">ServiceLayerConfiguration</span>(<span
style="color: #2b91af">Assembly</span>.GetExecutingAssembly(),</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Assembly</span>.GetExecutingAssembly(), <span
style="color: #2b91af">IoC</span>.Container)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BusinessExceptionType = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">BusinessException</span>),</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SecurityExceptionType = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">SecurityException</span>),</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CacheManagerImplementation = <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">CacheManagerSpy</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; };</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; serviceLayerConfiguration.Initialize();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// i want to take advantage of the automatic initialization, so i'm just resolving the requestprocessor instead of creating it</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; requestProcessor = <span
style="color: #2b91af">IoC</span>.Container.Resolve&lt;<span
style="color: #2b91af">IRequestProcessor</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// the cache manager is a singleton so i can just resolve it and it'll be the same one the request processor uses</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cacheManager = (<span
style="color: #2b91af">CacheManagerSpy</span>)<span
style="color: #2b91af">IoC</span>.Container.Resolve&lt;<span
style="color: #2b91af">ICacheManager</span>&gt;();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; firstCachedRequestHandler = <span
style="color: #2b91af">MockRepository</span>.GenerateMock&lt;<span
style="color: #2b91af">IRequestHandler</span>&lt;<span
style="color: #2b91af">FirstCachedRequest</span>&gt;&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; secondCachedRequestHandler = <span
style="color: #2b91af">MockRepository</span>.GenerateMock&lt;<span
style="color: #2b91af">IRequestHandler</span>&lt;<span
style="color: #2b91af">SecondCachedRequest</span>&gt;&gt;();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">IoC</span>.Container.RegisterInstance(firstCachedRequestHandler);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">IoC</span>.Container.RegisterInstance(secondCachedRequestHandler);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>This setup code will be executed for each testrun.&#160; 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.&#160;</p><p>So what exactly is a transition? It’s just a piece of code that you want to execute.&#160; That piece of code can receive input and it can return output.&#160; It’s basically the code that you’re testing.&#160; Our transition will simply consist of calling Agatha’s Request Processor and instructing it to process 2 requests.&#160; Those requests would be the two request types shown earlier which are eligible for caching.&#160; After QuickNet executes the transition, it will also verify that our defined specifications for that particular transition are indeed correct.</p><p>Let’s define the input that our transition will receive.&#160; 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.&#160; So we’ll use the following helper class to define this input:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">ProcessInputElement</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IRequestHandler</span> RequestHandler { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Request</span> Request { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Response</span> Response { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> RequestHandlerWasExecuted { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> ProcessInputElement(<span
style="color: #2b91af">IRequestHandler</span> requestHandler, <span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RequestHandler = requestHandler;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Request = request;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Response = response;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">void</span> StubHandler()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RequestHandler</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Stub(r =&gt; r.Handle(<span
style="color: #2b91af">Arg</span>&lt;<span
style="color: #2b91af">Request</span>&gt;.Is.Same(Request))) <span
style="color: green">// WHY: reference check iso equality check</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Return(Response)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .WhenCalled(a =&gt; RequestHandlerWasExecuted = <span
style="color: blue">true</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Repeat.Once();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>An instance of this class basically combines the Request, its Request Handler and the Response that needs to be returned.&#160; 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.&#160; And we’ll also set a simple flag to true if the Request Handler has indeed been called.</p><p>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.&#160; 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.&#160; We first need two generators which are capable of generating random instances of the FirstCachedRequest and SecondCachedRequest types:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">FirstRequestGenerator</span> : <span
style="color: #2b91af">BaseGenerator</span>&lt;<span
style="color: #2b91af">FirstCachedRequest</span>&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> FirstRequestGenerator()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AddGeneratorForProperty(r =&gt; r.String, <span
style="color: blue">new</span> <span
style="color: #2b91af">StringGenerator</span>(1, 1)); <span
style="color: green">// generates a random string of 1 character</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">SecondRequestGenerator</span> : <span
style="color: #2b91af">BaseGenerator</span>&lt;<span
style="color: #2b91af">SecondCachedRequest</span>&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> SecondRequestGenerator()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AddGeneratorForProperty(r =&gt; r.Integer, <span
style="color: blue">new</span> <span
style="color: #2b91af">IntGenerator</span>(0, 5));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>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.&#160;&#160; 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.&#160; 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.&#160; So again, some of the generated instances will be considered as equals, and some won’t.&#160;&#160; The important part to remember is that QuickNet will generate random instances for us and that we don’t have to worry about it.</p><p>Now that we have the generators for the request instances, we can write a generator which can generate random ProcessInputElement instances:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">ProcessInputTupleGenerator</span> : <span
style="color: #2b91af">BaseGenerator</span>&lt;<span
style="color: #2b91af">Tuple</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>, <span
style="color: #2b91af">ProcessInputElement</span>&gt;&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">FirstRequestGenerator</span> firstRequestGenerator = <span
style="color: blue">new</span> <span
style="color: #2b91af">FirstRequestGenerator</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">SecondRequestGenerator</span> secondRequestGenerator = <span
style="color: blue">new</span> <span
style="color: #2b91af">SecondRequestGenerator</span>();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">protected</span> <span
style="color: blue">override</span> <span
style="color: #2b91af">Tuple</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>, <span
style="color: #2b91af">ProcessInputElement</span>&gt; GetDefaultInstance()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> firstElement = <span
style="color: blue">new</span> <span
style="color: #2b91af">ProcessInputElement</span>(firstCachedRequestHandler, firstRequestGenerator.GetRandomValue(),</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> <span
style="color: #2b91af">FirstCachedResponse</span>());</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> secondElement = <span
style="color: blue">new</span> <span
style="color: #2b91af">ProcessInputElement</span>(secondCachedRequestHandler, secondRequestGenerator.GetRandomValue(),</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">new</span> <span
style="color: #2b91af">SecondCachedResponse</span>());</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: #2b91af">Tuple</span>.New(firstElement, secondElement);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>Actually, this generator doesn’t just generate one instance of ProcessInputElement, it generates a tuple consisting of two ProcessInputElement instances.&#160; 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.&#160; 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.</p><p>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.&#160; The generated tuple is then passed into the transition and the transition will be executed.</p><p>Now i can finally show you the transition that we’ll define:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">ProcessRequestsTransition</span> : <span
style="color: #2b91af">MetaTransition</span>&lt;<span
style="color: #2b91af">Tuple</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>, <span
style="color: #2b91af">ProcessInputElement</span>&gt;, <span
style="color: #2b91af">Response</span>[]&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> ProcessRequestsTransition()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Generator = <span
style="color: blue">new</span> <span
style="color: #2b91af">ProcessInputTupleGenerator</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Execute =</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; input =&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cacheManager.Clear(); <span
style="color: green">// clears the spy for every execution of this transition</span></p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; input.First.StubHandler();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; input.Second.StubHandler();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> requestProcessor.Process(<span
style="color: blue">new</span>[] {input.First.Request, input.Second.Request});</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; };</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>As you can see, the ProcessRequestsTransition inherits from the MetaTransition&lt;TInput, TOutput&gt; class.&#160; So we basically just defined that the input of the transition is a Tuple&lt;ProcessInputElement, ProcessInputElement&gt; and the output is an array of Response objects.&#160; In the constructor of the transition, we define that the generator to be used to generate the input values is the ProcessInputTupleGenerator.&#160; And we also define what actually needs to be executed by the transition.&#160; 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.&#160; It’s output (a Response array) will be the output of the transition since that is our return value.</p><p>After all that work, we can finally define our specifications for this transition.&#160; Let’s start with the first one:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; [<span
style="color: #2b91af">SpecFor</span>(<span
style="color: blue">typeof</span>(<span
style="color: #2b91af">ProcessRequestsTransition</span>))]</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Spec</span> ResponsesAreCachedIfTheyArentInTheCacheYet(<span
style="color: #2b91af">Tuple</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>, <span
style="color: #2b91af">ProcessInputElement</span>&gt; input, <span
style="color: #2b91af">Response</span>[] output)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">Spec</span>(() =&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Action</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>&gt; verify =</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; element =&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Ensure</span>.Equal(element.Response, cacheManager.CacheEntries.First(e =&gt; e.Request.Equals(element.Request)).Response);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Ensure</span>.True(output.Contains(element.Response));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Ensure</span>.True(element.RequestHandlerWasExecuted);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; };</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cacheManager.CacheEntries.Any(e =&gt; e.Request.Equals(input.First.Request)))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; verify(input.First);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cacheManager.CacheEntries.Any(e =&gt; e.Request.Equals(input.Second.Request)))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; verify(input.Second);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; })</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .IfAfter(() =&gt; cacheManager.ReturnedCachedResponses.Any(r =&gt; r == <span
style="color: blue">null</span>));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>The SpecFor attribute makes it possible to define which Transition this Spec belongs to.&#160; The method has 2 parameters, which correspond with the input that will be passed into the transition, and the output that the transition returned.&#160; It’s very important to realize that <em>this method</em> 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.&#160; Actually, that block of code will only be executed if the Spec’s precondition and postcondition have been satisfied.&#160; The precondition (which can be defined with the Spec class’ If method) will be evaluated <em>before </em>the transition is executed.&#160; If it evaluates to false, the spec will be ignored for the <em>current</em> execution of the transition.&#160; The postcondition (which can be defined with the Spec class’ IfAfter method) is evaulated <em>after </em>the transition is executed.&#160; If it evaulates to false, the spec will be ignored.&#160; 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.</p><p>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.&#160; If the CacheManager returns a null, it means that there was no cached response for the request it was given.&#160; And that is when we need to verify the following things:</p><ol><li>The request was handled by the Request Handler</li><li>The response that was returned by the Request Handler has been put in the cache</li><li>The response array that was returned by the Request Processor contains the expected response</li></ol><p>We perform this check for both requests, or only one of them, depending on which one was not in the cache yet.&#160; Remember that the transition will be executed 2000 times using <em>the same request processor and the same cache manager.</em>&#160; Which means that cached responses from <em>previous</em> transition executions might still be in the cache.&#160; 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.&#160; All of those cases are now covered with the code in this spec.</p><p>Here’s another spec:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; [<span
style="color: #2b91af">SpecFor</span>(<span
style="color: blue">typeof</span>(<span
style="color: #2b91af">ProcessRequestsTransition</span>))]</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Spec</span> CachedResponsesAreReturnedWhenAvailableInsteadOfCallingTheHandler(<span
style="color: #2b91af">Tuple</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>, <span
style="color: #2b91af">ProcessInputElement</span>&gt; input, <span
style="color: #2b91af">Response</span>[] output)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">Spec</span>(() =&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Action</span>&lt;<span
style="color: #2b91af">ProcessInputElement</span>&gt; verify =</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; element =&gt;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Ensure</span>.False(element.RequestHandlerWasExecuted);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Ensure</span>.True(output.Contains(cacheManager.ReturnedCachedResponses.First(r =&gt; r != <span
style="color: blue">null</span> &amp;&amp; r.GetType() == element.Response.GetType())));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; };</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cacheManager.ReturnedCachedResponses.Any(r =&gt; r != <span
style="color: blue">null</span> &amp;&amp;&#160; r.GetType() == input.First.Response.GetType()))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; verify(input.First);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cacheManager.ReturnedCachedResponses.Any(r =&gt; r != <span
style="color: blue">null</span> &amp;&amp; r.GetType() == input.Second.Response.GetType()))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; verify(input.Second);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; })</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .IfAfter(() =&gt; cacheManager.ReturnedCachedResponses.Any(r =&gt; r != <span
style="color: blue">null</span>));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>Here we verify that when a cached response was returned by the CacheManager:</p><ol><li>The Request Handler was <em>not</em> executed</li><li>The response array returned by the Request Processor contains the cached response</li></ol><p>We again perform this check for both requests, or only one of them depending on which one had a cached response.</p><p>You might think that this was a lot of work, but was it really?&#160; It’s about 160 lines of code, and i’m quite sure that the functionality that i’m testing is covered <em>much more thoroughly </em>than it would’ve been with 160 lines of code for classical unit tests.&#160;&#160; 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.&#160; Also, i can keep adding specs quite easily and those really don’t contain that much code.&#160; But my <em>functional coverage</em> would increase dramatically, much more than it would with classical unit tests.</p><p>Granted, the learning curve is steep as i mentioned already in a previous post.&#160; But once you start to get it, you become pretty productive with it and you’ll catch <em>a lot more bugs</em> before you deliver your software because of it.</p><p>Now, i tried hard to make everything here as clear as possible, so i’d love to hear from you whether or not:</p><ol><li>you understood it</li><li>you like it</li><li>you think it’s way over the top</li><li>you want to start doing this too</li></ol><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Ftesting-agathas-caching-functionality-with-quicknet%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/"  data-text="Testing Agatha&rsquo;s Caching Functionality With QuickNet" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/testing-agathas-caching-functionality-with-quicknet/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>How QuickNet Found 2 Bugs That You And I Didn&#8217;t</title><link>http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/</link> <comments>http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/#comments</comments> <pubDate>Tue, 22 Dec 2009 21:56:48 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category> <category><![CDATA[quicknet]]></category> <category><![CDATA[testing]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2124</guid> <description><![CDATA[I recently posted the first draft of the caching implementation of Agatha.&#160; You might want to take another look at the piece of code that deals with processing requests in the Request Processor.&#160; I thought it was alright.&#160; And if only 10% of my readers actually read that code, then it means that about 200 [...]]]></description> <content:encoded><![CDATA[<p>I recently posted the <a
href="http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/" target="_blank">first draft</a> of the caching implementation of Agatha.&#160; You might want to take another look at the piece of code that deals with processing requests in the Request Processor.&#160; I thought it was alright.&#160; 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.&#160; Today i was adding some cached requests/responses to the RequestProcessor’s <a
href="http://code.google.com/p/quicknet/" target="_blank">QuickNet</a> exception handling test.&#160; And lo and behold, 2 bugs showed up that i hadn’t anticipated.</p><p>Before i discuss the two bugs, i’d like to explain what the exception handling quicknet test does, and how it works.&#160; 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.&#160; 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.&#160; This particular QuickNet test will perform 50 testruns, where each testrun consists of 50 transitions that will be executed.&#160; 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.</p><p>Instead of testing with a mocked caching layer, i used the real thing in the tests.&#160; 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.&#160; 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.&#160;&#160; In the meantime, QuickNet is constantly firing requests at the RequestProcessor, and some of them will randomly fail.&#160; Our specs need to verify that the returned responses always contain the correct exception information for the batch of requests that was processed.</p><p>And here’s the beauty of the whole thing.&#160; I hadn’t even thought about how exception handling also influences how you deal with cached responses.&#160; 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.&#160;&#160; I was suddenly getting error messages from QuickNet that in some cases, the exception information wasn’t correct.&#160;&#160; And it frequently took over 30 executions of the transition, or sometimes multiple testruns before some of those specs would fail.&#160; 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.</p><p>And those are the type of bugs that you typically don’t find with traditional unit tests.&#160; When you write traditional tests that are aimed at asserting correct behavior, you typically only write tests for the problems that <em>you thought about</em>.&#160; Sometimes you’ll get lucky and traditional unit tests will inform you of incorrect behavior that you didn’t think of,&#160; but it rarely happens for the edge-cases.&#160; And those are the bugs that can be really hard and painful to find and fix.</p><p>By now you’re probably wondering what the two bugs are.&#160; 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).&#160; 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.&#160;&#160; Pretty stupid huh?&#160; 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.</p><p>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.&#160; 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.&#160; Granted, the learning curve for writing valuable QuickNet tests is <em>steep</em> (i’m not even halfway there IMO) and it takes a lot of effort when you’re starting out with it.&#160; 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.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Fhow-quicknet-found-2-bugs-that-you-and-i-didnt%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/"  data-text="How QuickNet Found 2 Bugs That You And I Didn&rsquo;t" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/how-quicknet-found-2-bugs-that-you-and-i-didnt/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Open Source Licensing, Copyright Notices, Contributions: What To Do?</title><link>http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/</link> <comments>http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/#comments</comments> <pubDate>Sun, 20 Dec 2009 13:09:30 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2104</guid> <description><![CDATA[There are two interesting problems that i’m facing with open-sourcing Agatha, and i’m not quite sure how to deal with it correctly.&#160; The first is how to apply the license of my choice to the actual code.&#160; I’m using Apache License 2.0, and this is their recommendation (emphasis mine): To apply the Apache License to [...]]]></description> <content:encoded><![CDATA[<p>There are two interesting problems that i’m facing with open-sourcing <a
href="http://code.google.com/p/agatha-rrsl/" target="_blank">Agatha</a>, and i’m not quite sure how to deal with it correctly.&#160; The first is how to apply the license of my choice to the actual code.&#160; I’m using Apache License 2.0, and this is their recommendation (emphasis mine):</p><blockquote><p>To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets &quot;[]&quot; replaced with your own identifying information. (Don't include the brackets!) <strong><em>The text should be enclosed in the appropriate comment syntax for the file format</em></strong>. We also recommend that a file or class name and description of purpose be included on the same &quot;printed page&quot; as the copyright notice for easier identification within third-party archives.</p><p>&#160;</p><p><code></code></p><p>Copyright [yyyy] [name of copyright owner]</p><p>&#160;</p><p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</p><p><em><strong>you may not use this file except in compliance with the License</strong>.</em></p><p>You may obtain a copy of the License at</p><p>&#160;</p><p><a
href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p><p>&#160;</p><p>Unless required by applicable law or agreed to in writing, software</p><p>distributed under the License is distributed on an &quot;AS IS&quot; BASIS,</p><p>WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</p><p>See the License for the specific language governing permissions and</p><p>limitations under the License.</p></blockquote><p>This sort of implies that i’m required to put this boilerplate notice <em>in each file</em>, which is just tedious and the odds are pretty high that you’re going to forget to put this in one (or more) of the files that will be added later on.</p><p>Instead, i put a LICENSE.txt file in the root folder of the project with the following content:</p><blockquote><p>Copyright 2009 Agatha RRSL Project, original authors and contributors</p><p>&#160;</p><p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); <br
/><strong><em>you may not use the files in this directory structure except in compliance with the License. <br
/></em></strong>You may obtain a copy of the License at</p><p>&#160;</p><p><a
href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p><p>&#160;</p><p>Unless required by applicable law or agreed to in writing, software <br
/>distributed under the License is distributed on an &quot;AS IS&quot; BASIS, <br
/>WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br
/>See the License for the specific language governing permissions and <br
/>limitations under the License.</p></blockquote><p>Honestly, i have no idea if i’m allowed to do that.&#160; I can’t think of a reason why i shouldn’t be able to do this since it certainly sounds reasonable to do so, but then again i’m not a lawyer and i wouldn’t be surprised if there are reasons for <em>not</em> doing so.&#160; If anyone can provide advice on this, it would be much appreciated <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>Another thing that left me wondering is the actual copyright notice.&#160; In the 1.0 release, i unfortunately used the following copyright statement for both the LICENSE.txt as well as the copyright information on the assembly level:</p><blockquote><p>Copyright 2009 Davy Brion</p></blockquote><p>Now, i did write most of the code, i did start the project and i do own the project.&#160; But i did not write all of the code as there have been some contributions from other people.&#160; I certainly want to give credit where credit is due, so i’ve changed that copyright notice (both in the LICENSE.txt file and the assembly copyright notices) to:</p><blockquote><p>Copyright 2009 Agatha RRSL Project, original authors and contributors</p></blockquote><p>I then added a CONTRIBUTORS.txt file at the same location of the LICENSE.txt file which contains the names of the contributors and the parts they worked on.&#160; I <em>think</em> that’s all i need to do to to be fair and correct, but again, i’m not entirely sure on this.</p><p>If anyone can provide feedback on these issues, please do so <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Fopen-source-licensing-copyright-notices-contributions-what-to-do%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/"  data-text="Open Source Licensing, Copyright Notices, Contributions: What To Do?" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/open-source-licensing-copyright-notices-contributions-what-to-do/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>Agatha 1.0</title><link>http://davybrion.com/blog/2009/12/agatha-1-0/</link> <comments>http://davybrion.com/blog/2009/12/agatha-1-0/#comments</comments> <pubDate>Sat, 19 Dec 2009 13:40:41 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2009/12/agatha-1-0/</guid> <description><![CDATA[I just released Agatha 1.0 which you can download here.&#160; The biggest changes since the 1.0 beta 2 release is the support for the one-way requests and the ability to easily run the service layer within the same process as your client (if you don’t need or want WCF for example). As for the next [...]]]></description> <content:encoded><![CDATA[<p>I just released Agatha 1.0 which you can download <a
href="http://code.google.com/p/agatha-rrsl/downloads/list" target="_blank">here</a>.&#160; The biggest changes since the 1.0 beta 2 release is the support for the <a
href="http://davybrion.com/blog/2009/12/one-way-or-fire-and-forget-requests-with-agatha/" target="_blank">one-way requests</a> and the ability to easily run the service layer <a
href="http://davybrion.com/blog/2009/12/running-an-agatha-service-layer-in-process-without-wcf/" target="_blank">within the same process as your client</a> (if you don’t need or want WCF for example).</p><p>As for the next version (1.1) the biggest focus will be on the caching layer, and the ability to pick your own error handling strategy.</p><p>I hope the few users that we have will enjoy this <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Fagatha-1-0%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/agatha-1-0/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/agatha-1-0/"  data-text="Agatha 1.0" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/agatha-1-0/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/agatha-1-0/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/agatha-1-0/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Enabling Logging In Your Agatha Service Layer</title><link>http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/</link> <comments>http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/#comments</comments> <pubDate>Sat, 19 Dec 2009 13:05:22 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=1971</guid> <description><![CDATA[As of Agatha 1.0 beta 2, you can now use whatever logging library you prefer.&#160; Agatha now uses the Common.Logging project instead of using a logging library directly.&#160; This means you just need to add a bit of configuration to your service host to enable logging and get that logging information in whatever format or [...]]]></description> <content:encoded><![CDATA[<p>As of Agatha 1.0 beta 2, you can now use whatever logging library you prefer.&#160; Agatha now uses the <a
href="http://netcommon.sourceforge.net/" target="_blank">Common.Logging</a> project instead of using a logging library directly.&#160; This means you just need to add a bit of configuration to your service host to enable logging and get that logging information in whatever format or manner you want.&#160; Enabling this is pretty easy, since you just need to follow the standard approaches for <a
href="http://netcommon.sourceforge.net/docs/2.0.0/reference/html/ch01.html#logging-config" target="_blank">configuring Common.Logging</a>, and obviously also for the logging library that you use.&#160; I’m just going to show a short example of using XML in your web.config (or app.config depending on your service host) to get this working.</p><p>First, you need to add the configuration section for Common.Logging to the &lt;configSections&gt; element:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">sectionGroup</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">common</span>&quot;<span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">section</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">logging</span>&quot;<span
style="color: blue"> </span><span
style="color: red">type</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">Common.Logging.ConfigurationSectionHandler, Common.Logging</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">sectionGroup</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">section</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">log4net</span>&quot;<span
style="color: blue"> </span><span
style="color: red">type</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">log4net.Config.Log4NetConfigurationSectionHandler,Log4net</span>&quot;<span
style="color: blue">/&gt;</span></p></div><p>&#160;</p><p>As you can see, i also included the definition of my preferred logging library (log4net) in this as well.&#160; In this particular case, your service host needs to reference the following assemblies: Common.Logging.dll, Common.Logging.Log4Net.dll and log4net.dll.</p><p>The configuration of the Common.Logging library looks like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px"><span
style="color: blue">&#160; &lt;</span><span
style="color: #a31515">common</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">logging</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">factoryAdapter</span><span
style="color: blue"> </span><span
style="color: red">type</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4net</span>&quot;<span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">arg</span><span
style="color: blue"> </span><span
style="color: red">key</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">configType</span>&quot;<span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">INLINE</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">factoryAdapter</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">logging</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160; &lt;/</span><span
style="color: #a31515">common</span><span
style="color: blue">&gt;</span></p></div><p>&#160;</p><p>You need to specify which factoryAdapter that Common.Logging will use, in our case the one for log4net.&#160; If you then configure the INLINE value for the configType key, Common.Logging will just initialize log4net in a way that it will simply use the XML configuration that is also present in your config file.&#160; Again, i’ll point you to the <a
href="http://netcommon.sourceforge.net/docs/2.0.0/reference/html/ch01.html#logging-config" target="_blank">Common.Logging documentation</a> for configuring it for your specific library if you’re using something else.&#160;</p><p>In my case, my log4net configuration looks like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px"><span
style="color: blue">&#160; &lt;</span><span
style="color: #a31515">log4net</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">logger</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">Agatha</span>&quot;<span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">level</span><span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">ERROR</span>&quot;<span
style="color: blue">/&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">appender-ref</span><span
style="color: blue"> </span><span
style="color: red">ref</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">LogFileAppender</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">logger</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">logger</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">AgathaPerformance</span>&quot;<span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">level</span><span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">WARNING</span>&quot;<span
style="color: blue">/&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">appender-ref</span><span
style="color: blue"> </span><span
style="color: red">ref</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">LogFileAppender</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">logger</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">appender</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">LogFileAppender</span>&quot;<span
style="color: blue"> </span><span
style="color: red">type</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">log4net.Appender.RollingFileAppender</span>&quot;<span
style="color: blue"> &gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">param</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">File</span>&quot;<span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">log.txt</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">param</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">AppendToFile</span>&quot;<span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">true</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">rollingStyle</span><span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">Size</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">maxSizeRollBackups</span><span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">10</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">maximumFileSize</span><span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">10MB</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">staticLogFileName</span><span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">true</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">layout</span><span
style="color: blue"> </span><span
style="color: red">type</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">log4net.Layout.PatternLayout</span>&quot;<span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160;&#160;&#160; &lt;</span><span
style="color: #a31515">param</span><span
style="color: blue"> </span><span
style="color: red">name</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">ConversionPattern</span>&quot;<span
style="color: blue"> </span><span
style="color: red">value</span><span
style="color: blue">=</span>&quot;<span
style="color: blue">%-5p%d{yyyy-MM-dd hh:mm:ss} - %m%n</span>&quot;<span
style="color: blue"> /&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">layout</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160;&#160;&#160; &lt;/</span><span
style="color: #a31515">appender</span><span
style="color: blue">&gt;</span></p><p
style="margin: 0px"><span
style="color: blue">&#160; &lt;/</span><span
style="color: #a31515">log4net</span><span
style="color: blue">&gt;</span></p></div><p>&#160;</p><p>The ‘Agatha’ logger simply logs everything coming from types whose namespace starts with Agatha and that logs at the error level (basically just exceptions caught by the Request Processor) and sends that the LogFileAppender (which simply logs in a log.txt) file.&#160; The ‘AgathaPerformance’ logger specifically logs performance warnings coming from Agatha’s PerformanceLoggingRequestProcessor and also sends it to the LogFileAppender.</p><p>And that’s all there is to it.</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Fenabling-logging-in-your-agatha-service-layer%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/"  data-text="Enabling Logging In Your Agatha Service Layer" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/enabling-logging-in-your-agatha-service-layer/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Agatha&#8217;s Caching Layer Implementation: First Draft</title><link>http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/</link> <comments>http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/#comments</comments> <pubDate>Sun, 13 Dec 2009 19:56:27 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/?p=2049</guid> <description><![CDATA[Well i got a bit carried away and started implementing the caching layer already… i’d like to go over the details of it in this post, but keep in mind that it’s only a first draft and that this will not be in the upcoming 1.0 release.&#160;&#160; In fact, i haven’t even tested this yet… [...]]]></description> <content:encoded><![CDATA[<p>Well i got a bit carried away and started implementing the caching layer already… i’d like to go over the details of it in this post, but keep in mind that it’s only a first draft and that this will <em>not</em> be in the upcoming 1.0 release.&#160;&#160; In fact, i haven’t even tested this yet… i don’t even know if it runs.&#160; This is just to get some feedback on the design.&#160; Once it works, it’ll need some time to mature and to be tested properly so it’ll be in the 1.1 release.&#160; With that out of the way, let’s get started.</p><p>First of all, there’s the following attribute that you can put on your Request types:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; [<span
style="color: #2b91af">AttributeUsage</span>(<span
style="color: #2b91af">AttributeTargets</span>.Class, Inherited = <span
style="color: blue">false</span>, AllowMultiple = <span
style="color: blue">false</span>)]</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">EnableResponseCachingAttribute</span> : <span
style="color: #2b91af">Attribute</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">string</span> Region { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">int</span> Hours { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">int</span> Minutes { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">int</span> Seconds { <span
style="color: blue">get</span>; <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">TimeSpan</span> Expiration</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">get</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (Hours == 0 &amp;&amp; Minutes == 0 &amp;&amp; Seconds == 0)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">throw</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">InvalidOperationException</span>(<span
style="color: #a31515">&quot;You need to specific at least an hour value, a minute value or a second value&quot;</span>);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">TimeSpan</span>(0, Hours, Minutes, Seconds);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>I really want to support both programmatic configuration as well as XML configuration (which would always override any existing programmatic configuration for a particular request) but for now, this attribute is the only way.&#160; Also, everything in this caching layer assumes that your requests which enable response caching <em>must</em> override the Equals and GetHashCode() methods correctly (hint: use Resharper for that).</p><p>When we configure Agatha, we need to transform the caching metadata into objects of the following class:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">RequestCacheConfiguration</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Type</span> RequestType { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">TimeSpan</span> Expiration { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">string</span> Region { <span
style="color: blue">get</span>; <span
style="color: blue">private</span> <span
style="color: blue">set</span>; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> RequestCacheConfiguration(<span
style="color: #2b91af">Type</span> requestType, <span
style="color: #2b91af">TimeSpan</span> expiration, <span
style="color: blue">string</span> region)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RequestType = requestType;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Expiration = expiration;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Region = region;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>And we also need something that contains all of the caching configuration data:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">CacheConfiguration</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: #2b91af">Type</span>, <span
style="color: #2b91af">RequestCacheConfiguration</span>&gt; requestCacheConfigurations;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> CacheConfiguration(<span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: #2b91af">Request</span>&gt; knownRequests)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BuildMapOfConfigurationsForRequestsThatEnabledResponseCaching(knownRequests);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">void</span> BuildMapOfConfigurationsForRequestsThatEnabledResponseCaching(<span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: #2b91af">Request</span>&gt; knownRequests)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; requestCacheConfigurations = <span
style="color: blue">new</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: #2b91af">Type</span>, <span
style="color: #2b91af">RequestCacheConfiguration</span>&gt;();</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">foreach</span> (<span
style="color: blue">var</span> request <span
style="color: blue">in</span> knownRequests)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> requestType = request.GetType();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> attribute = <span
style="color: #2b91af">Attribute</span>.GetCustomAttribute(requestType, <span
style="color: blue">typeof</span>(<span
style="color: #2b91af">EnableResponseCachingAttribute</span>)) <span
style="color: blue">as</span> <span
style="color: #2b91af">EnableResponseCachingAttribute</span>;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (attribute != <span
style="color: blue">null</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; requestCacheConfigurations.Add(requestType, <span
style="color: blue">new</span> <span
style="color: #2b91af">RequestCacheConfiguration</span>(requestType, attribute.Expiration, attribute.Region));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> IsCachingEnabledFor(<span
style="color: #2b91af">Type</span> requestType)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> requestCacheConfigurations.ContainsKey(requestType);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">RequestCacheConfiguration</span> GetConfigurationFor(<span
style="color: #2b91af">Type</span> requestType)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> requestCacheConfigurations[requestType];</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">IEnumerable</span>&lt;<span
style="color: blue">string</span>&gt; GetRegionNames()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">HashSet</span>&lt;<span
style="color: blue">string</span>&gt;(requestCacheConfigurations.Values.Where(v =&gt; !<span
style="color: blue">string</span>.IsNullOrEmpty(v.Region)).Select(v =&gt; v.Region));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">string</span> GetRegionNameFor(<span
style="color: #2b91af">Type</span> requestType)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> requestCacheConfigurations[requestType].Region;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>These classes already give us all we need to know (for now, at least) to set up our cache.&#160; As mentioned previously, i wanted to use a region-based approach like NHibernate’s 2nd Level Cache.&#160; Each region is basically a logical cache (and depending on the caching provider you’ll use, perhaps even a separate physical one) which is separated from the other ones.&#160; It gives us the ability to specifically clear a logical cache.</p><p>So, we need something which can create a cache for a region:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">ICacheProvider</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">ICache</span> BuildCache(<span
style="color: blue">string</span> region);</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>And the cache itself would need to expose the following methods:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">ICache</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Response</span> GetCachedResponseFor(<span
style="color: #2b91af">Request</span> request);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">void</span> Store(<span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response, <span
style="color: #2b91af">TimeSpan</span> expiration);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">void</span> Clear();</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>So now we can write something that manages the whole caching thing.&#160; I couldn’t come up with a good name, so i just named the class CacheManager (i know it sucks, so suggest a better name if you know one):</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">interface</span> <span
style="color: #2b91af">ICacheManager</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">bool</span> IsCachingEnabledFor(<span
style="color: #2b91af">Type</span> requestType);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">Response</span> GetCachedResponseFor(<span
style="color: #2b91af">Request</span> request);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">void</span> StoreInCache(<span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">void</span> Clear(<span
style="color: blue">string</span> region);</p><p
style="margin: 0px">&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">CacheManager</span> : <span
style="color: #2b91af">ICacheManager</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">const</span> <span
style="color: blue">string</span> defaultRegion = <span
style="color: #a31515">&quot;_defaultRegion&quot;</span>;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">readonly</span> <span
style="color: #2b91af">CacheConfiguration</span> configuration;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">readonly</span> <span
style="color: #2b91af">ICacheProvider</span> cacheProvider;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: blue">string</span>, <span
style="color: #2b91af">ICache</span>&gt; caches;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> CacheManager(<span
style="color: #2b91af">CacheConfiguration</span> configuration, <span
style="color: #2b91af">ICacheProvider</span> cacheProvider)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">this</span>.configuration = configuration;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">this</span>.cacheProvider = cacheProvider;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BuildCaches();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">void</span> BuildCaches()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> regions = configuration.GetRegionNames();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; caches = <span
style="color: blue">new</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: blue">string</span>, <span
style="color: #2b91af">ICache</span>&gt;(regions.Count() + 1);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; caches.Add(defaultRegion, cacheProvider.BuildCache(defaultRegion));</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">foreach</span> (<span
style="color: blue">var</span> region <span
style="color: blue">in</span> regions)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; caches.Add(region, cacheProvider.BuildCache(region));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">bool</span> IsCachingEnabledFor(<span
style="color: #2b91af">Type</span> requestType)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> configuration.IsCachingEnabledFor(requestType);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Response</span> GetCachedResponseFor(<span
style="color: #2b91af">Request</span> request)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> caches[configuration.GetRegionNameFor(request.GetType()) ?? defaultRegion].GetCachedResponseFor(request);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">void</span> StoreInCache(<span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> config = configuration.GetConfigurationFor(request.GetType());</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; caches[config.Region ?? defaultRegion].Store(request, response, config.Expiration);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">void</span> Clear(<span
style="color: blue">string</span> region)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; caches[region].Clear();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>The RequestProcessor’s ugly request-processing-loop (i know i need to clean that up) could then look like this:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">foreach</span> (<span
style="color: blue">var</span> request <span
style="color: blue">in</span> requests)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">try</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> cachingIsEnabledForThisRequest = cacheManager.IsCachingEnabledFor(request.GetType());</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cachingIsEnabledForThisRequest)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> cachedResponse = cacheManager.GetCachedResponseFor(request);</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cachedResponse != <span
style="color: blue">null</span>)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; responses.Add(cachedResponse);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">continue</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">using</span> (<span
style="color: blue">var</span> handler = (<span
style="color: #2b91af">IRequestHandler</span>)<span
style="color: #2b91af">IoC</span>.Container.Resolve(GetResponseHandlerTypeFor(request)))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">try</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (!exceptionsPreviouslyOccurred)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> response = GetResponseFromHandler(request, handler);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; exceptionsPreviouslyOccurred = response.ExceptionType != <span
style="color: #2b91af">ExceptionType</span>.None;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; responses.Add(response);</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cachingIsEnabledForThisRequest)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cacheManager.StoreInCache(request, response);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">else</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> response = handler.CreateDefaultResponse();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; response.ExceptionType = <span
style="color: #2b91af">ExceptionType</span>.EarlierRequestAlreadyFailed;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; response.Exception = <span
style="color: blue">new</span> <span
style="color: #2b91af">ExceptionInfo</span>(<span
style="color: blue">new</span> <span
style="color: #2b91af">Exception</span>(<span
style="color: #2b91af">ExceptionType</span>.EarlierRequestAlreadyFailed.ToString()));</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; responses.Add(response);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">finally</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: #2b91af">IoC</span>.Container.Release(handler);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">catch</span> (<span
style="color: #2b91af">Exception</span> e)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; logger.Error(e);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">throw</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p></div><p>&#160;</p><p>And that’s it, so far.&#160;&#160; Obviously, we need ICache and ICacheProvider implementations for the various caching libraries that are already available.&#160; I already wrote an InMemoryCache and InMemoryCacheProvider to facilitate early experimentation/testing of the caching layer:</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">InMemoryCacheProvider</span> : <span
style="color: #2b91af">ICacheProvider</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">ICache</span> BuildCache(<span
style="color: blue">string</span> s)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: blue">new</span> <span
style="color: #2b91af">InMemoryCache</span>();&#160;&#160;&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><div
style="font-family: consolas; background: white; color: black; font-size: 10pt"><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: green">// this class should probably never be used in production, but will be useful for testing <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </span></p><p
style="margin: 0px">&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">class</span> <span
style="color: #2b91af">InMemoryCache</span> : <span
style="color: #2b91af">ICache</span></p><p
style="margin: 0px">&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">readonly</span> <span
style="color: blue">object</span> monitor = <span
style="color: blue">new</span> <span
style="color: blue">object</span>();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: #2b91af">Request</span>, <span
style="color: #2b91af">Response</span>&gt; cachedResponses;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: #2b91af">Timer</span>, <span
style="color: #2b91af">Request</span>&gt; timersToRequests;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> InMemoryCache()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Initialize();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">void</span> Initialize()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cachedResponses = <span
style="color: blue">new</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: #2b91af">Request</span>, <span
style="color: #2b91af">Response</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timersToRequests = <span
style="color: blue">new</span> <span
style="color: #2b91af">Dictionary</span>&lt;<span
style="color: #2b91af">Timer</span>, <span
style="color: #2b91af">Request</span>&gt;();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: #2b91af">Response</span> GetCachedResponseFor(<span
style="color: #2b91af">Request</span> request)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">lock</span>(monitor)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (!cachedResponses.ContainsKey(request))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> <span
style="color: blue">null</span>;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">return</span> cachedResponses[request];</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">void</span> Store(<span
style="color: #2b91af">Request</span> request, <span
style="color: #2b91af">Response</span> response, <span
style="color: #2b91af">TimeSpan</span> expiration)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> timer = <span
style="color: blue">new</span> <span
style="color: #2b91af">Timer</span>(expiration.Milliseconds);</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">lock</span> (monitor)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (cachedResponses.ContainsKey(request))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// another request handler stored a cached response already during the processing of this request...</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// the last one wins, so get rid of the previous one, including its timer</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cachedResponses.Remove(request);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> otherTimer = timersToRequests.First(keyValuePair =&gt; keyValuePair.Value.Equals(request)).Key;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GetRidOfTimer(otherTimer);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timersToRequests.Remove(otherTimer);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cachedResponses[request] = response;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timersToRequests[timer] = request;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timer.Elapsed += timer_Elapsed;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timer.Start();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">void</span> timer_Elapsed(<span
style="color: blue">object</span> sender, <span
style="color: #2b91af">ElapsedEventArgs</span> e)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> timer = (<span
style="color: #2b91af">Timer</span>)sender;</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">lock</span> (monitor)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: green">// if the Clear method has been called before a timer has elapsed, it won't be in the timersToRequest dictionary anymore</span></p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">if</span> (timersToRequests.ContainsKey(timer))</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">var</span> request = timersToRequests[timer];</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; cachedResponses.Remove(request);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timersToRequests.Remove(timer);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timer.Dispose();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">public</span> <span
style="color: blue">void</span> Clear()</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">lock</span>(monitor)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">foreach</span> (<span
style="color: blue">var</span> timer <span
style="color: blue">in</span> timersToRequests.Keys)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; GetRidOfTimer(timer);</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Initialize();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span
style="color: blue">private</span> <span
style="color: blue">void</span> GetRidOfTimer(<span
style="color: #2b91af">Timer</span> timer)</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timer.Elapsed -= timer_Elapsed;</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timer.Stop();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; timer.Dispose();</p><p
style="margin: 0px">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p><p
style="margin: 0px">&#160;&#160;&#160; }</p></div><p>&#160;</p><p>That’s it so far… i probably forgot about a lot of stuff that i really should take into account, but at least it’s something that we can start with.&#160; Or to throw away and start over <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Fagathas-caching-layer-implementation-first-draft%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/"  data-text="Agatha&rsquo;s Caching Layer Implementation: First Draft" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/agathas-caching-layer-implementation-first-draft/feed/</wfw:commentRss> <slash:comments>9</slash:comments> </item> <item><title>Agatha Feature Suggestion: Caching</title><link>http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/</link> <comments>http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/#comments</comments> <pubDate>Sat, 12 Dec 2009 15:16:21 +0000</pubDate> <dc:creator>Davy Brion</dc:creator> <category><![CDATA[agatha]]></category><guid
isPermaLink="false">http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/</guid> <description><![CDATA[Someone recently asked me if it would be possible to cache responses with an Agatha service layer and just send back the cached responses when matching requests are sent to the service layer.&#160; I’ve been thinking about this a bit lately, and i think it would be a tremendous feature.&#160; In this post, i just [...]]]></description> <content:encoded><![CDATA[<p>Someone recently asked me if it would be possible to cache responses with an Agatha service layer and just send back the cached responses when matching requests are sent to the service layer.&#160; I’ve been thinking about this a bit lately, and i think it would be a tremendous feature.&#160; In this post, i just want to list a couple of ideas on how it could work and what we’d need to take into account to make it work.&#160; Please feel free to leave your suggestions/thoughts on this since i can definitely use all of the feedback i can get to implement a feature like this.</p><p>The idea is basically to implement a caching layer which works very similar to NHibernate’s Second Level Cache.&#160; You would need to be able to define which request/response combination is eligible for caching.&#160; When a request/response combination is eligible for caching, Agatha should check to see if a cached response is already available for a particular incoming request.&#160; That would mean that the request type would need to override the Equals method to compare the values.&#160;&#160; If a previous request has already been processed which is equal to the current request, the corresponding cached response could be sent back immediately without having to handle it again.&#160; Obviously, this check would only happen for requests which have been made eligible for caching.</p><p>We’d also need to provide a way to invalidate the cache.&#160; Both time-based expiration and explicit removal from the cache should be possible.&#160; For time-based expiration we could just provide some sort of time-out setting in the same place where you enable the caching for the request.&#160; I’d probably do that through a .NET attribute which you can put on your Request type, and the time-out would simply be a property of the attribute.&#160; For explicit removal, i’d probably go with a ‘region’-approach, similar to the regions in NHibernate’s Second Level Cache.&#160; For instance, when declaring a request to be eligible for caching, one of the properties of the caching attribute could be a region name, and then we’d need to give you the ability to clear a certain region of the cache in your request handlers when it’s necessary to do so.</p><p>That’s pretty much all i can think of for now.&#160; It’s not much yet, but i do think it could really be a tremendous improvement to Agatha.&#160; The performance benefits for requests that deal with mostly static data, or data that doesn’t change frequently could be huge.&#160; And the required coding effort for developers using Agatha would be minimal… simply put the correct attribute on your request type and explicit clearing of the right cache region when necessary would be all there is to it.</p><p>Thoughts?</p><div
class="bottomcontainerBox" style=""><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <iframe
src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fdavybrion.com%2Fblog%2F2009%2F12%2Fagatha-feature-suggestion-caching%2F&amp;layout=button_count&amp;show_faces=false&amp;width=85&amp;action=like&amp;font=verdana&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width=85px; height:21px;" allowTransparency="true"></iframe></div><div
style="float:left; width:80px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <g:plusone size="medium" href="http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/"></g:plusone></div><div
style="float:left; width:95px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"> <a
href="http://twitter.com/share" class="twitter-share-button" data-url="http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/"  data-text="Agatha Feature Suggestion: Caching" data-count="horizontal" data-via="davybrion">Tweet</a></div><div
style="float:left; width:105px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script type="in/share" data-url="http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/" data-counter="right"></script></div><div
style="float:left; width:85px;padding-right:10px; margin:4px 4px 4px 4px;height:30px;"><script src="http://www.stumbleupon.com/hostedbadge.php?s=1&amp;r=http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/"></script></div></div><div
style="clear:both"></div><div
style="padding-bottom:4px;"></div>]]></content:encoded> <wfw:commentRss>http://davybrion.com/blog/2009/12/agatha-feature-suggestion-caching/feed/</wfw:commentRss> <slash:comments>8</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 2/83 queries in 0.061 seconds using disk: basic
Object Caching 1583/1754 objects using disk: basic
Content Delivery Network via Amazon Web Services: CloudFront: d18sni7re4ly7f.cloudfront.net

Served from: davybrion.com @ 2012-02-07 08:05:42 -->
