agatha

Agatha 1.3 Is Out

5 commentsWritten on July 16th, 2011 by
Categories: agatha

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 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 here and you can find some real examples here.

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 here.

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 here, i ended up with 8 nuget packages:

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 Google Code or on Github. I didn't create another binary package since i figured that most people who want that will be using Nuget anyway.

The two other changes are:

  • now possible to POST to the IWcfRestJsonRequestProcessor (contributed by Andrew Rea)
  • our container abstraction allows key-based resolving (contributed by Nikos Baxevanis)

My favorite part about this release is that all of the new code has been contributed by other people :)

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 :)

A Nuget Packaging Dilemma

26 commentsWritten on March 27th, 2011 by
Categories: agatha

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 use the container you prefer. I've talked before about the loyalty 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.

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:

  • I don't want the package to include something that the user might not want.
  • I don't want to force a particular container on users
  • I don't want to ILMerge any container assemblies because that would cause problems if users themselves make use of a container already.
  • I don't want to do it like the current NHibernate 3.1 package because that pretty much guarantees nobody will install it. NHibernate can get away with something like that because it's already an established project.

Ideally, i'd be able to define the following package structure:

  • Agatha-RRSL, requires one of the following packages to be installed (if no selection is made, go with Agatha-Windsor by default):
    • Agatha-Windsor, depends on Agatha-RRSL and Castle Windsor
    • Agatha-StructureMap, depends on Agatha-RRSL and StructureMap
    • Agatha-NInject, depends on Agatha-RRSL and NInject
    • ... (one for each supported container)

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.

As for how it should be packaged for now, i still have no idea. Suggestions are welcome :)

Using Distributed Caching With Agatha

7 commentsWritten on February 27th, 2011 by
Categories: agatha

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.

This week i was introduced to Membase, 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 Enyim Membase client, 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:

    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<Response>(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("{0}_{1}", request.GetType().FullName, request.GetHashCode());
        }
    }

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.

Then you'll need an ICacheProvider implementation:

    public class MembaseCacheProvider : ICacheProvider
    {
        public ICache BuildCache(string region)
        {
            return new MembaseCache(region);
        }
    }

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:

    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<byte>(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);
            }
        }
    }

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:

  <membase>
    <servers bucket="_defaultRegion">
      <add uri="http://localhost:8091/pools/default" />
    </servers>
    <transcoder type="Agatha.Common.Caching.MembaseTranscoder, Agatha.Common" />
  </membase>

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 ;)

You'd also need to configure Agatha to use the MembaseCacheProvider implemention:

            var config = new ServiceLayerConfiguration(Assembly.GetExecutingAssembly(), 
                typeof(HelloWorldRequest).Assembly, typeof(Agatha.Castle.Container))
                            {
                                CacheProviderImplementation = typeof(MembaseCacheProvider)
                            };
            config.Initialize();

And that's it... distributed caching of service-layer responses has never been this easy ;)

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.

First NuGet Experience

5 commentsWritten on January 6th, 2011 by
Categories: agatha, Software Development

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:

first look at Nuget

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 :)

Agatha 1.2 Is Available

9 commentsWritten on September 28th, 2010 by
Categories: agatha

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: EnableResponseCachingAttribute no longer exists, use the EnableServiceResponseCachingAttribute instead) -> this is not supported in the in-process model
  • RequestProcessor now has an AfterHandle(request, response) virtual method which is called after the request has been handled by the handler
  • ReceivedResponses now has a Responses property which returns all of the retrieved responses
  • 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)
  • Agatha.Spring has been included (thanks to a patch from Jernej Logar)
  • 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)
  • Added BeforeResolvingRequestHandler virtual method to the RequestProcessor which gets called right before a RequestHandler is resolved through the container
  • Fixed logging of WCF messages where some requests were logged as "... stream ..." (thanks to patch by Bart Deleye)
  • Added Agatha.Ninject.Silveright (thanks to patch by Bart Deleye)
  • Updated Agatha.Unity and Agatha.Unity.Silverlight to use the 2.0 version of Unity
  • Applied patch from Andrew Rea to improve REST support (xml and json)

Thanks to everyone who contributed to this release. It's very nice to see the list of contributors growing with each release :)

You can download the source code or the binaries here.