REQUEST A DEMO

Creating Your First Carrier Extension

Extensions are the heart of Dovetail Carrier. The application itself does nothing unless there is an extension present. This makes it important to understand how to create your own extensions. This guide will take you through creating a brand new extension and having it subscribe to one of the core Carrier messages IncomingEmailMessage.

 

Create The Extension Project

 

imageThe first thing we are going to do is add a project to the extensions solution included with Carrier. Before you can do this you’ll need to unzip the\developer\extensions-source.zip file shipped with Dovetail Carrier into a directory on a development machine which has Visual Studio 2008 installed.

 

Next open the extension solution (carrier-extensions.sln) and add a new project to the solution.

 

  • File -> Add -> New Project
  • Select a C# Class Library and give it a name. I’ll use MyFirstExtension
  • Add a reference to the following Carrier assemblies found in this path relative to the solution ..\..\tools\Carrier-Core
    • Dovetail.Commons
    • Dovetail.Carrier.Core
    • Dovetail.Carrier.Messages
    • StructureMap
  • Remove the Class1.cs file. We won’t be using it.

Mark the Project As A Carrier Extension

 

When Carrier is starting up it needs a way to determine which assemblies are extensions. The way to do this is to mark your assembly with the CarrierExtension attribute. Add the assembly attribute to the end of your AssemblyInfo.cs file.

 

using Dovetail.Carrier.Core;
 
...
 
[assembly: CarrierExtension]

 

 

Don’t forget to add the using statement to the top of the file.

 

Messaging?

 

Dovetail Carrier is basically super simple turnkey Enterprise Service Bus. This means that it is message oriented. Things publish messages and things subscribe to them. The behavior of the system evolves from the exchange of these messages and how the system responds to them.

 

Email Publisher

 

Carrier has an email services library which provides a message publisher which can connect to one or more POP3 email accounts. This publishing service produces messages of the type IncomingEmailMessage. Carrier is smart enough to only start this publisher up if there are subscribers present for the messages it produces.

 

Incoming Email Message

 

The messages produced by the email services publisher looks like this:

 

public interface IncomingEmailMessage 
{
  string Id { get; set; }
  string Pop3UserName { get; set; }
  string Pop3HostName { get; set; }
  string[] To { get; set; }
  string[] CC { get; set; }
  string[] BCC { get; set; }
  string From { get; set; }
  string Subject { get; set; }
  string Body { get; set; }
  DateTime DateReceived { get; set; }
  bool HasAttachments { get; set; }
  bool HasBouncedDeliveryStatusNotification { get; set; }
}

 

 

Note: Messages should be immutable so down the road we’ll likely be removing the property setters.

 

To do something with this message we need some code that subscribes to these messages.

 

Using RuleSets To Subscribe To Messages

 

Carrier has a construct called RuleSets which help organize how your extensions behave when receiving messages. You organize your business behaviors into named RuleSets each having one or more rules executed one after another. Every time a message is received Carrier creates new instances of all the RuleSets defined for that type of message executes them.

 

Add the following file to your project named MyFirstRulesRegistry.cs.

 

using System;
using Dovetail.Carrier.Core.RulesEngine;
using Dovetail.Carrier.Messages;
 
namespace MyFirstExtension
{
  public class MyFirstRulesRegistry : RulesRegistry
  {
    public MyFirstRulesRegistry()
    {
      DefineRuleSetFor<IncomingEmailMessage>()
        .Named("My first rule set")
        .WithRules( rule =>
        {
          rule.When<OnBreak>().Do<ComeBackLater>();
          rule.Unless<OnBreak>().Do<Respond>();
        });
    }
  }
}

 

 

The RulesRegistry above defines a single RuleSet consisting of two rules. Take a look at DefineRuleSetFor. This is the start of a RuleSet subscribing to IncomingEmailMessages having two rules.

Read the rules aloud to yourself and you’ll hopefully understand their behavior. We want rules to read a bit like English. Take a look at the first rule.

 

rule.When<OnBreak>().Do<ComeBackLater>()

 

When the OnBreak condition is true. The ComeBackLater action will be executed. Conditions and actions are implemented as classes in code which implement the meaning behind the language.

 

Intellisense

 

Go try editing or adding a rule in Visual Studio. You will get Intellisense assisting you with what your potential options are. It will also help you out by filling in those icky yet required angle brackets and parenthesis.

 

Intellisense helps a lot during rule creation.

What‘s In A Rule?

 

Each rule defined in the RuleSet has a condition class which controls whether an action class will get executed. You can think of the rule as outlining a message processing step. The rules in your RuleSet composing a desired business behavior.

 

The meat of each rule is the condition and action classes implementing the behavior behind the language of the rule. Let’s implement the condition and actions in play in this RuleSet.

 

public class OnBreak : ICondition<IncomingEmailMessage>
{
  public bool IsSatisfied(IRuleContext<IncomingEmailMessage> context)
  {
    var hourOfTheDay = DateTime.Now.Hour;
 
    var areWeAtLunch = (hourOfTheDay > 11) && (hourOfTheDay < 13);
 
    return areWeAtLunch;
  }
}
 
public class ComeBackLater : IAction<IncomingEmailMessage>
{
  public void Execute(IRuleContext<IncomingEmailMessage> context)
  {
    //call the customer back later.
  }
}
 
public class Respond : IAction<IncomingEmailMessage>
{
  public void Execute(IRuleContext<IncomingEmailMessage> context)
  {
    //respond to the email.
  }
}

 

 

Take a look at the OnBreak class it has an IsSatisfied method which will get executed during rule evaluation. The rule’s action will get executed When this condition returns true. OnBreak condition will return true when the current time of day is around noon.

 

Conditions are technically optional as you can define an AlwaysDo action by itself.

 

Each rule can also end with an Exit() command which will also stop execution of the ruleset when the condition is satisfied.

 

These actions and conditions don’t really do much take a look at my other Carrier posts for more complex actions and conditions.

 

Testing Your Extension

 

Well the best way to make sure everything is working well is to test. Here at Dovetail we are really into automated testing. We like to write unit tests using NUnit and automate their execution. Included with your extension source are many examples of testing conditions and actions.

 

We have included the test suites used in developing all of our shipping extensions. You can run these tests from a command line by running the build-extensions.bat batch file found in your extensions source directory. If you want to learn more about the automation behind build-extensions.bat please read up on the excellent build automation toolNAnt.

 

Deploying Your Extension

 

It should be clear to you that this extension does not really do anything useful. It is more of an outline bootstrap your understanding of Carrier’s extensibility. For a more complete example demonstrating producing as well as consuming messages please check out my Clock – A Super Simple Carrier Extension post.

 

If you wish to see this extension in action.

 

  • I recommend removing any of the other extensions you may have installed. Carrier.Extensions.*.dll.
  • Next build your project and copy the resulting .Net assembly, MyFirstExtension.dll, into the Carrier service application directory.
  • Make sure your pop3-accounts.config is configured with a valid email account. I highly recommend hMailServerwhen testing email sending and receiving.
  • Run carrier from a command line. DovetailCarrierService.exe
  • You’ll likely not see much as the conditions and actions we created above have no logging going on and don’t really do anything.

 

Conclusion

 

I’ve taken you through a start to finish creation of an essentially do nothing extension. My goal was to introduce you to the basic developer facing concepts you’ll run into creating and customizing Dovetail Carrier. Please do let me know what you want to know more about. I’ll be happy to help.