Friday, January 14, 2011

Rhino ESB for Dummies

This will document my “dummy” experience. I’ve been using NServiceBus for a while, but the license model changed out from under us so we’ve been investigating alternatives. A fellow in the office pointed us to Rhino ESB (he had pointed us to NServiceBus earlier).

Immediate Impressions

C:\Source\external\rhino-esb>powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Source\external\rhino-esb> .\psake.ps1 .\default.ps1
So, that appears to be all there is to it.

Upsides/Downsides

  • We’ve been making extensive use of Autofac as our container and Rhino has a predisposition for Castle Windsor. We’ll just use Windsor in the handlers for now and leave other areas (i.e. ASP.NET MVC 2) to use Autofac. I’m told that a container agnostic version of Rhino ESB is in the works.
  • Testing with NServiceBus was pretty straightforward as it provided mocks of our handlers and also setup the expect portions. I’m told that with Rhino Mocks we don’t need to worry about that and we just test our handler’s independently from the ‘service bus’.
  • No more need to adorn our message classes with IMessage.
UPDATE

I had to enter Set-ExecutionPolicy Unrestricted to run the psake script.

Wednesday, January 5, 2011

Separating Integration Tests from Unit Tests with xUnit

How often do you find that you’ve written a very useful test that crosses a process boundary, or makes changes to another system (file system, database) which by definition of a Unit Test shouldn’t be tested as part of your code coverage, but its highly useful.

Here are some attributes that you can use to mark up your (these are inspired by several other posts out there on the internet).

public sealed class IntegrationFactAttribute : FactAttribute
{
protected override IEnumerable EnumerateTestCommands(IMethodInfo method)
{
var attrs = method.MethodInfo.GetCustomAttributes(typeof(IntegrationAttribute), true).Cast();

if (Skip == null && attrs.Any(x => x.ShouldRunTest))
{
return base.EnumerateTestCommands(method);
}

return new[] { new SkipCommand(method, method.Name, "Integration method skipped") };
}
}
The abstract class below defines a simple Boolean property in which we can define the circumstances under which we want to execute the method.
public abstract class IntegrationAttribute : Attribute
{
public abstract bool ShouldRunTest { get; }
}
Below is an example class that tests to see if there is a debugger attached, and if so, it returns true for the ‘ShouldRunTest’ property. When this is evaluated in the EnumerateTestCommands in the IntegrationFactAttribute it will run the marked test method.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class WhenInDebuggerAttribute : IntegrationAttribute
{
public override bool ShouldRunTest
{
get { return System.Diagnostics.Debugger.IsAttached; }
}
}
Example using both attributes. This test which tests through to the database will only be run if it was executing inside of the debugger. If you are using Resharper or TestDriven.NET then you can execute the test while debugging but no longer need to worry need to be concerned that your continuous build environment will be testing code depends on a shared resource.
[IntegrationFact, WhenInDebugger]
public void CheckLiveRepositoryOnClinicianByOrganizationID()
{
const int idToMatch = 1;

// Create LS2 Repository
var repository = CreateRepository();

// Use a Specification to retrieve results
var clinicians = repository.Find(ClinicianSpecs.ByOrganizationID(idToMatch)).ToList();

// Assert valid
clinicians.Should().Not.Be.Null();
}
Note that I’m using the Should Assertion Library instead of the Assert.NotNull(). If you’re interested in more behavior driven development then this library makes your assertions read well.

Sunday, July 18, 2010

CVS, CruiseControl.NET and mysterious errors

After many days of head scratching and trying to come up with the correct google phrase to find a solution to the infamous:
cvs checkout: move away xxx; it is in the way
I finally determined the cause and was then able to identify a post with a solution:

Switching CVS servers easily

It turns out that this error has two likely causes:

  • If you're on Windows then someone might have the same file named with different case. Our CVS server is hosted on a linux platform so that it is possible to store ThisFile.txt and THISFILE.TXT in the same directory. Upon cvs update, windows will try to overwrite the file and complain that the file is already there. This can be more evil if it was at the directory level!
  • The second cause, and the one that I wasn't aware of, is that the value contained in the hidden CVS\Root file must be the same as the CVSROOT value of your client (or environment variable if your client is aware of the %CVSROOT% variable.)


Our problem was that we routinely use multiple clients to access CVS (command line, TortoiseCVS, WinCVS and finally CC.NET as well). Whenever I saw this problem, I would usually log in to the build server and delete the offending directory. That usually works. However, since we had a different CVSROOT value specified in the TortoiseCVS than the one in the CC.NET configuration file, it was possible that the value stored in CVS\Root would be different.

The key is either to make sure that you're CVSROOT file is always the same one, or alternatively, if you suspect this is the issue, then check the CVS\Root file to make sure that it matches up to the one your client is using.

UPDATE

After several attempts I was able to identify yet another cause for the 'cvs checkout: move away xxx; it is in the way' message. Check to make sure that any 'Entries.log' files were removed by your build scripts. In our case we use NAnt and we had a clean target which removed all *.log files and in addition we had specifically ignored the default excludes. The default excludes has a pattern to exclude the hidden CVS directory and any contents of that directory.

So to sum it up, just keep in mind that the single 'cvs checkout: move away xxx; it is in the way' can occur for any of the following reasons:
  1. $CVSROOT (or %CVSROOT%) is different than the value found in the CVS/Root directory. This could also be an issue if you supply the -d {cvsroot} option to the cvs executable.
  2. If your CVS server is located on a case sensitive O/S (Linux for example) and your client is on a case insensitive O/S (Windows), then make sure some has not committed a similarly named directory or file.
  3. Check the Entries and Entries.log files in the hidden CVS directory to make sure that it matches what files are in the corresponding directory. If they don't then it's possible some other process has removed the Entries.log file!

Thursday, April 29, 2010

Netbook and Windows Anytime Upgrade

I mentioned in a previous post that I struggled with how to access my creative juices while on vacation while not toting around an extra ten pounds of gear. I settled on a HP Mini 210, it's a little underpowered, but it weighs in around 3 pounds which isn't too bad as extra weight. It has 1 GB memory (nothing like my Dell Quad Core with 8GB!) and it is limited in disk space. I left my 500GB hard drive at home as I didn't want to cart that around as well. I've got quite a bit of things on this laptop even so.

  • Visual Studio 2010
  • SQL Server 2008 Express
  • Mercurial plus all of the devs tools I could think of - WinMerge, e, nant... I did miss TestDriven.NET, so I'll have to figure how that works into writing code.

After rushing to install everything I thought I'd need I decided at 2.30 am (with a 4.45 wake up forthcoming!) to try an upgrade from Starter edition to Home Professional. Don't be fooled, it says that the upgrade will take 10 minutes or so, unless there are Windows Updates! Doh! I think I finished out with a workable system again more than an hour later! I recommend if you're going to do an Anytime Upgrade on your system to do it with time to spare. I was wondering if I had bricked my new system right before the trip! It all worked out and went smoothly, but not without some minutes of stress in the wee hours.

HG Walkabout

Just prior to taking a three week vacation to Europe I splurged and purchased a Netbook (HP Mini 210-1032CL). I don't recommend doing this at the very last minute, but sometimes...

I have a copy of O'Reilly's Mercurial book and I spent time looking around for a digital copy of the book. I didn't find it on the 'net. I finally located it while I was sitting at the gate in SFO in the TortoiseHG docs directory *sweet*!

I discovered that it was quite easy to use the great 'hg help' command. I found out that first I need to remove the chaff from CVS (CVS artifacts.) I also was scratching my head for a bit trying to figure out how to ignore files that I did not want added to the repository.

Directly from the hg help init:

hg init [-e CMD] [--remotecmd CMD] [DEST]

create a new repository in the given directory

    Initialize a new repository in the given directory. If the given directory
    does not exist, it will be created.

    If no directory is given, the current directory is used.

    It is possible to specify an "ssh://" URL as the destination. See 'hg help
    urls' for more information.

Now that I had a repository built I knew that I needed to tell Mercurial what files were in it. I forged ahead and did a 'hg add' only to discover that I'd inadvertently added all of the CVS directories as well as the files that typically end up in our .cvsignore files. So that lead me to discover both 'hg remove' and 'hg forget', all three commands are described below:

hg add [OPTION]... [FILE]...

add the specified files on the next commit

    Schedule files to be version controlled and added to the repository.

    The files will be added to the repository at the next commit. To undo an
    add before that, see hg forget.

    If no names are given, add all files to the repository.

hg remove [OPTION]... FILE...

aliases: rm

remove the specified files on the next commit

    Schedule the indicated files for removal from the repository.

    This only removes files from the current branch, not from the entire
    project history. -A/--after can be used to remove only files that have
    already been deleted, -f/--force can be used to force deletion, and -Af
    can be used to remove files from the next revision without deleting them
    from the working directory.

hg forget [OPTION]... FILE...

forget the specified files on the next commit

    Mark the specified files so they will no longer be tracked after the next
    commit.

    This only removes files from the current branch, not from the entire
    project history, and it does not delete them from the working directory.

To undo a forget before the next commit, see hg add.
I think I've figured out that there are multiple ways to save yourself with Mercurial. I thought I had to do a 'hg remove' and a 'hg forget', but I believe that could have been avoided by supplying an option to the remove command - 'hg remove --force' which says remove (and delete) file even if added or modified.

Sidebar: I'm flying at 573mph ground speed at 35000 feet somewhere over Lake Michigan right now. Yes I know in the first paragraph I said that I was sitting in the San Francisco airport at the gate, but I was interrupted when I had to get on the plane, a lunch/dinner and subsequent knap. My clock says its just after midnight in London, I'm not ready to give into the sleep and change time zones just yet :)

Using e-TextEditor now and you get the Mercurial icons in the Project viewer. Nice!

snap-20100429-0029

Friday, April 23, 2010

IIS7 CryptographicException - The system cannot find the file specified.

I found a strange error while getting my application to run on Server 2008 R2. Below is a description of a similar problem and the resolution. Its duplicated here in case the other blog disappears in the future.

From blog - MaeSitus-Sitecore

CryptographicException file not found in Sitecore
Today I came across issue with CryptographicException file not found in Sitecore. See below

Server Error in '/' Application.

THE SYSTEM CANNOT FIND THE FILE SPECIFIED.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Security.Cryptography.CryptographicException: The system cannot find the file specified.


Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


Stack Trace:

[CryptographicException: The system cannot find the file specified. ] System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) +7715070 System.Security.Cryptography.DSACryptoServiceProvider.ImportParameters(DSAParameters parameters) +258 System.Security.Cryptography.DSA.FromXmlString(String xmlString) +501 Sitecore.Nexus.Licensing.NexusLicenseApi. (String xml, Guid instance) +138 Sitecore.Nexus.Licensing.NexusLicenseApi.GetSnapShot(Guid instance) +764 Sitecore.SecurityModel.License.LicenseManager.GetSnapshotData(Guid instance) +59 Sitecore.SecurityModel.License.LicenseManager.UpdateSnapshot() +103 Sitecore.SecurityModel.License.LicenseManager.Initialize() +8 Sitecore.Nexus.Web.HttpModule.Application_Start() +76 Sitecore.Nexus.Web.HttpModule.Init(HttpApplication app) +435 System.Web.HttpApplication.InitModulesCommon() +65 System.Web.HttpApplication.InitModules() +43 System.Web.HttpApplication.InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers) +729 System.Web.HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context) +298 System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context) +107 System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +289


Version Information: Microsoft .NET Framework Version:2.0.50727.4927; ASP.NET Version:2.0.50727.4927

After consulting with my colleague, the solution is to do with IIS settings.

To resolve this,

1. go to IIS Manager
2. go to the application pool instance
3. click advanced settings
4. Under Process model, set Load User Profile to true

Saturday, December 12, 2009

Getting Fluent NHibernate running under Windows 7

I just finished wiping my development box and going from Vista to Windows 7. Overall it wasn’t too bad. I did encounter two problems trying to get our unit tests (xUnit) running again.

The first problem was that I had copied the Source directory from my Vista install to the Windows 7 install. Almost everything was good until I run two tests that were getting a ReflectionTypeLoadException. That exception tells you to take a look at the LoaderExceptions property. When I did that I noticed that it was complaining about the fact that some of the DLLs that were being loaded (specifically FluentNHibernate.dll) was from a different machine. To fix this, I removed the copied Libraries folder and updated again from CVS. That problem then went away.