Permalink
Browse files

Initial working Spring.NET integration

  • Loading branch information...
1 parent 584a125 commit e94c6235219b402d9e9dba012f62c25b659ee8dc @lahma lahma committed Jul 10, 2011
View
120 Rhino.ServiceBus.Spring/ApplicationContextExtensions.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+using Spring.Context;
+using Spring.Objects.Factory;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Rhino.ServiceBus.Spring
+{
+ [CLSCompliant(false)]
+ public static class ApplicationContextExtensions
+ {
+ public static T Get<T>(this IConfigurableApplicationContext context)
+ {
+ return (T) Get(context, typeof(T));
+ }
+
+ public static IEnumerable<T> GetAll<T>(this IConfigurableApplicationContext context)
+ {
+ IDictionary objectsOfType = context.GetObjectsOfType(typeof(T));
+ return objectsOfType.Values.Cast<T>();
+ }
+
+ public static object Get(this IApplicationContext context, Type type)
+ {
+ string[] objectNamesForType = context.GetObjectNamesForType(type);
+ if ((objectNamesForType == null) || (objectNamesForType.Length == 0))
+ {
+ throw new NoSuchObjectDefinitionException(type.FullName, "Requested Type not defined in the context.");
+ }
+ return context.GetObject(objectNamesForType[0]);
+ }
+
+ public static T Get<T>(this IApplicationContext context, string name)
+ {
+ return (T) context.GetObject(name);
+ }
+
+ public static void RegisterPrototype<T>(this IConfigurableApplicationContext context)
+ {
+ ObjectDefinitionBuilder definitionBuilder = ObjectDefinitionBuilder.RootObjectDefinition(new DefaultObjectDefinitionFactory(), typeof(T))
+ .SetAutowireMode(AutoWiringMode.AutoDetect)
+ .SetSingleton(false);
+ context.ObjectFactory.RegisterObjectDefinition(Guid.NewGuid().ToString(), definitionBuilder.ObjectDefinition);
+ }
+
+ public static void RegisterSingletons<TBasedOn>(this IConfigurableApplicationContext context, Assembly assembly)
+ {
+ assembly.GetTypes()
+ .Where(t => typeof (TBasedOn).IsAssignableFrom(t)
+ && !t.IsInterface
+ && !t.IsAbstract)
+ .ToList()
+ .ForEach(type => RegisterSingleton(context, type));
+ }
+
+ public static void RegisterSingleton(this IConfigurableApplicationContext context, Type type)
+ {
+ ObjectDefinitionBuilder definitionBuilder = ObjectDefinitionBuilder.RootObjectDefinition(new DefaultObjectDefinitionFactory(), type)
+ .SetAutowireMode(AutoWiringMode.AutoDetect)
+ .SetSingleton(true);
+ context.ObjectFactory.RegisterObjectDefinition(type.FullName, definitionBuilder.ObjectDefinition);
+ }
+
+ public static void RegisterSingleton(this IConfigurableApplicationContext context, Type type, string name, params object[] constructorArguments)
+ {
+ ObjectDefinitionBuilder definitionBuilder = ObjectDefinitionBuilder.RootObjectDefinition(new DefaultObjectDefinitionFactory(), type)
+ .SetAutowireMode(AutoWiringMode.AutoDetect)
+ .SetSingleton(true);
+ if (constructorArguments != null && constructorArguments.Length > 0)
+ {
+ foreach (object argument in constructorArguments)
+ {
+ definitionBuilder.AddConstructorArg(argument);
+ }
+ }
+
+ context.ObjectFactory.RegisterObjectDefinition(name, definitionBuilder.ObjectDefinition);
+ }
+
+ public static void RegisterSingleton<T>(this IConfigurableApplicationContext context, Func<T> creator)
+ {
+ RegisterSingleton(context, Guid.NewGuid().ToString(), creator);
+ }
+
+ public static void RegisterSingleton<T>(this IConfigurableApplicationContext context, string name, Func<T> creator)
+ {
+ context.ObjectFactory.RegisterSingleton(name, new FuncBasedObjectCreator<T>(creator));
+ }
+
+ private class FuncBasedObjectCreator<T> : IFactoryObject
+ {
+ private readonly Func<T> creator;
+
+ public FuncBasedObjectCreator(Func<T> creator)
+ {
+ this.creator = creator;
+ }
+
+ public object GetObject()
+ {
+ return creator();
+ }
+
+ public Type ObjectType
+ {
+ get { return typeof(T); }
+ }
+
+ public bool IsSingleton
+ {
+ get { return true; }
+ }
+ }
+ }
+}
View
39 Rhino.ServiceBus.Spring/ConsumerInterceptor.cs
@@ -0,0 +1,39 @@
+using System;
+
+using Rhino.ServiceBus.Config;
+using Rhino.ServiceBus.Internal;
+
+using Spring.Context;
+using Spring.Objects.Factory.Config;
+
+namespace Rhino.ServiceBus.Spring
+{
+ [CLSCompliant(false)]
+ public class ConsumerInterceptor : IObjectPostProcessor
+ {
+ private readonly IConsumerInterceptor interceptor;
+ private readonly IConfigurableApplicationContext applicationContext;
+
+ public ConsumerInterceptor(IConsumerInterceptor interceptor, IConfigurableApplicationContext applicationContext)
+ {
+ this.interceptor = interceptor;
+ this.applicationContext = applicationContext;
+ }
+
+ public object PostProcessBeforeInitialization(object instance, string name)
+ {
+ return instance;
+ }
+
+ public object PostProcessAfterInitialization(object instance, string objectName)
+ {
+ var type = instance.GetType();
+ if (typeof(IMessageConsumer).IsAssignableFrom(type))
+ {
+ var transient = !applicationContext.ObjectFactory.GetObjectDefinition(objectName).IsSingleton;
+ interceptor.ItemCreated(type, transient);
+ }
+ return instance;
+ }
+ }
+}
View
24 Rhino.ServiceBus.Spring/Extensions.cs
@@ -0,0 +1,24 @@
+using System;
+using Rhino.ServiceBus.Impl;
+using Rhino.ServiceBus.Spring;
+
+using Spring.Context;
+using Spring.Context.Support;
+
+namespace Rhino.ServiceBus
+{
+ public static class Extensions
+ {
+ public static AbstractRhinoServiceBusConfiguration UseSpring(this AbstractRhinoServiceBusConfiguration configuration)
+ {
+ return UseSpring(configuration, new StaticApplicationContext());
+ }
+
+ [CLSCompliant(false)]
+ public static AbstractRhinoServiceBusConfiguration UseSpring(this AbstractRhinoServiceBusConfiguration configuration, IConfigurableApplicationContext container)
+ {
+ new SpringBuilder(configuration, container);
+ return configuration;
+ }
+ }
+}
View
82 Rhino.ServiceBus.Spring/Rhino.ServiceBus.Spring.csproj
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Rhino.ServiceBus.Spring</RootNamespace>
+ <AssemblyName>Rhino.ServiceBus.Spring</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\ayende-open-source.snk</AssemblyOriginatorKeyFile>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(LibDir)' == '' ">
+ <LibDir>..\SharedLibs\4.0\</LibDir>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Common.Logging">
+ <HintPath>..\SharedLibs\Common.Logging.dll</HintPath>
+ </Reference>
+ <Reference Include="Rhino.Queues, Version=1.2.0.0, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
+ <HintPath>$(LibDir)Rhino.Queues.dll</HintPath>
+ <SpecificVersion>False</SpecificVersion>
+ </Reference>
+ <Reference Include="Spring.Core">
+ <HintPath>$(LibDir)Spring.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Messaging" />
+ <Reference Include="System.Transactions" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ApplicationContextExtensions.cs" />
+ <Compile Include="ConsumerInterceptor.cs" />
+ <Compile Include="SpringBootStrapper.cs" />
+ <Compile Include="SpringBuilder.cs" />
+ <Compile Include="SpringLoadBalancerBootStrapper.cs" />
+ <Compile Include="SpringServiceLocator.cs" />
+ <Compile Include="Extensions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Rhino.ServiceBus\Rhino.ServiceBus.csproj">
+ <Project>{1B21C8A5-5E0E-412B-A7F4-9F28B4427F21}</Project>
+ <Name>Rhino.ServiceBus</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
101 Rhino.ServiceBus.Spring/SpringBootStrapper.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Linq;
+
+using Rhino.ServiceBus.Actions;
+using Rhino.ServiceBus.Hosting;
+using Rhino.ServiceBus.Impl;
+using Rhino.ServiceBus.Internal;
+
+using Spring.Context;
+using Spring.Context.Support;
+using Spring.Objects.Factory.Config;
+using Spring.Objects.Factory.Support;
+
+namespace Rhino.ServiceBus.Spring
+{
+ [CLSCompliant(false)]
+ public abstract class SpringBootStrapper : AbstractBootStrapper
+ {
+ private IConfigurableApplicationContext applicationContext;
+
+ public SpringBootStrapper()
+ {
+ }
+
+ public SpringBootStrapper(IConfigurableApplicationContext applicationContext)
+ {
+ this.applicationContext = applicationContext;
+ }
+
+ protected IConfigurableApplicationContext ApplicationContext
+ {
+ get { return applicationContext; }
+ }
+
+ protected override void ConfigureBusFacility(AbstractRhinoServiceBusConfiguration configuration)
+ {
+ configuration.UseSpring(applicationContext);
+ }
+
+ public override void ExecuteDeploymentActions(string user)
+ {
+ foreach (IDeploymentAction action in applicationContext.GetAll<IDeploymentAction>())
+ {
+ action.Execute(user);
+ }
+ }
+
+ public override void ExecuteEnvironmentValidationActions()
+ {
+ foreach (IEnvironmentValidationAction action in applicationContext.GetAll<IEnvironmentValidationAction>())
+ {
+ action.Execute();
+ }
+ }
+
+ public override T GetInstance<T>()
+ {
+ return applicationContext.Get<T>();
+ }
+
+ public override void Dispose()
+ {
+ applicationContext.Dispose();
+ }
+
+ public override void CreateContainer()
+ {
+ if (applicationContext == null)
+ applicationContext = new StaticApplicationContext();
+
+ ConfigureContainer();
+ }
+
+ protected virtual void ConfigureContainer()
+ {
+ applicationContext.RegisterSingletons<IDeploymentAction>(Assembly);
+ applicationContext.RegisterSingletons<IEnvironmentValidationAction>(Assembly);
+ RegisterConsumers();
+ }
+
+ protected virtual void RegisterConsumers()
+ {
+ Assembly.GetTypes()
+ .Where(t => typeof (IMessageConsumer).IsAssignableFrom(t)
+ && !typeof (IOccasionalMessageConsumer).IsAssignableFrom(t)
+ && IsTypeAcceptableForThisBootStrapper(t)
+ && !t.IsInterface
+ && !t.IsAbstract)
+ .ToList()
+ .ForEach(type =>
+ {
+ ObjectDefinitionBuilder definitionBuilder = ObjectDefinitionBuilder
+ .RootObjectDefinition(new DefaultObjectDefinitionFactory(), type)
+ .SetAutowireMode(AutoWiringMode.Constructor)
+ .SetSingleton(false);
+ applicationContext.ObjectFactory.RegisterObjectDefinition(type.FullName, definitionBuilder.ObjectDefinition);
+ }
+ );
+ }
+ }
+}
View
247 Rhino.ServiceBus.Spring/SpringBuilder.cs
@@ -0,0 +1,247 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Messaging;
+
+using Rhino.Queues;
+using Rhino.ServiceBus.Actions;
+using Rhino.ServiceBus.Config;
+using Rhino.ServiceBus.Convertors;
+using Rhino.ServiceBus.DataStructures;
+using Rhino.ServiceBus.Impl;
+using Rhino.ServiceBus.Internal;
+using Rhino.ServiceBus.LoadBalancer;
+using Rhino.ServiceBus.MessageModules;
+using Rhino.ServiceBus.Msmq;
+using Rhino.ServiceBus.Msmq.TransportActions;
+using Rhino.ServiceBus.RhinoQueues;
+
+using Spring.Context;
+
+using ErrorAction = Rhino.ServiceBus.Msmq.TransportActions.ErrorAction;
+using LoadBalancerConfiguration = Rhino.ServiceBus.LoadBalancer.LoadBalancerConfiguration;
+
+namespace Rhino.ServiceBus.Spring
+{
+ [CLSCompliant(false)]
+ public class SpringBuilder : IBusContainerBuilder
+ {
+ private readonly AbstractRhinoServiceBusConfiguration config;
+ private readonly IConfigurableApplicationContext applicationContext;
+
+ public SpringBuilder(AbstractRhinoServiceBusConfiguration config, IConfigurableApplicationContext applicationContext)
+ {
+ this.config = config;
+ this.applicationContext = applicationContext;
+ config.BuildWith(this);
+ }
+
+ public void WithInterceptor(IConsumerInterceptor interceptor)
+ {
+ applicationContext.ObjectFactory.AddObjectPostProcessor(new ConsumerInterceptor(interceptor, applicationContext));
+ }
+
+ public void RegisterDefaultServices()
+ {
+ applicationContext.RegisterSingleton<IServiceLocator>(() => new SpringServiceLocator(applicationContext));
+ applicationContext.RegisterSingletons<IBusConfigurationAware>(typeof(IServiceBus).Assembly);
+
+ foreach (var busConfigurationAware in applicationContext.GetAll<IBusConfigurationAware>())
+ {
+ busConfigurationAware.Configure(config, this);
+ }
+
+ foreach (var module in config.MessageModules)
+ {
+ applicationContext.RegisterSingleton(module, module.FullName);
+ }
+
+
+ applicationContext.RegisterSingleton<IReflection>(() => new DefaultReflection());
+ applicationContext.RegisterSingleton(config.SerializerType);
+ applicationContext.RegisterSingleton<IEndpointRouter>(() => new EndpointRouter());
+ }
+
+ public void RegisterBus()
+ {
+ var busConfig = (RhinoServiceBusConfiguration) config;
+
+ applicationContext.RegisterSingleton<IStartableServiceBus>(() => new DefaultServiceBus(applicationContext.Get<IServiceLocator>(),
+ applicationContext.Get<ITransport>(),
+ applicationContext.Get<ISubscriptionStorage>(),
+ applicationContext.Get<IReflection>(),
+ applicationContext.GetAll<IMessageModule>().ToArray(),
+ busConfig.MessageOwners.ToArray(),
+ applicationContext.Get<IEndpointRouter>()));
+
+ applicationContext.RegisterSingleton(() => new CreateQueuesAction(applicationContext.Get<IQueueStrategy>(), applicationContext.Get<IServiceBus>()));
+ }
+
+ public void RegisterPrimaryLoadBalancer()
+ {
+ var loadBalancerConfig = (LoadBalancerConfiguration) config;
+
+ applicationContext.RegisterSingleton(() =>
+ {
+ MsmqLoadBalancer balancer = new MsmqLoadBalancer(applicationContext.Get<IMessageSerializer>(),
+ applicationContext.Get<IQueueStrategy>(),
+ applicationContext.Get<IEndpointRouter>(),
+ loadBalancerConfig.Endpoint,
+ loadBalancerConfig.ThreadCount,
+ loadBalancerConfig.Transactional,
+ applicationContext.Get<IMessageBuilder<Message>>());
+ balancer.ReadyForWorkListener = applicationContext.Get<MsmqReadyForWorkListener>();
+ return balancer;
+ });
+
+ applicationContext.RegisterSingleton<IDeploymentAction>(() => new CreateLoadBalancerQueuesAction(applicationContext.Get<IQueueStrategy>(), applicationContext.Get<MsmqLoadBalancer>()));
+ }
+
+ public void RegisterSecondaryLoadBalancer()
+ {
+ var loadBalancerConfig = (LoadBalancerConfiguration) config;
+
+ applicationContext.RegisterSingleton<MsmqLoadBalancer>(() =>
+ {
+ MsmqSecondaryLoadBalancer balancer = new MsmqSecondaryLoadBalancer(applicationContext.Get<IMessageSerializer>(),
+ applicationContext.Get<IQueueStrategy>(),
+ applicationContext.Get<IEndpointRouter>(),
+ loadBalancerConfig.Endpoint,
+ loadBalancerConfig.PrimaryLoadBalancer,
+ loadBalancerConfig.ThreadCount,
+ loadBalancerConfig.Transactional,
+ applicationContext.Get<IMessageBuilder<Message>>());
+ balancer.ReadyForWorkListener = applicationContext.Get<MsmqReadyForWorkListener>();
+ return balancer;
+ });
+
+ applicationContext.RegisterSingleton<IDeploymentAction>(() => new CreateLoadBalancerQueuesAction(applicationContext.Get<IQueueStrategy>(), applicationContext.Get<MsmqLoadBalancer>()));
+ }
+
+ public void RegisterReadyForWork()
+ {
+ var loadBalancerConfig = (LoadBalancerConfiguration) config;
+
+ applicationContext.RegisterSingleton(() => new MsmqReadyForWorkListener(applicationContext.Get<IQueueStrategy>(),
+ loadBalancerConfig.ReadyForWork,
+ loadBalancerConfig.ThreadCount,
+ applicationContext.Get<IMessageSerializer>(),
+ applicationContext.Get<IEndpointRouter>(),
+ loadBalancerConfig.Transactional,
+ applicationContext.Get<IMessageBuilder<Message>>()));
+
+ applicationContext.RegisterSingleton<IDeploymentAction>(() => new CreateReadyForWorkQueuesAction(applicationContext.Get<IQueueStrategy>(), applicationContext.Get<MsmqReadyForWorkListener>()));
+ }
+
+ public void RegisterLoadBalancerEndpoint(Uri loadBalancerEndpoint)
+ {
+ applicationContext.RegisterSingleton(typeof (LoadBalancerMessageModule).FullName, () => new LoadBalancerMessageModule(
+ loadBalancerEndpoint,
+ applicationContext.Get<IEndpointRouter>()));
+ }
+
+ public void RegisterLoggingEndpoint(Uri logEndpoint)
+ {
+ applicationContext.RegisterSingleton(typeof (MessageLoggingModule).FullName, () => new MessageLoggingModule(applicationContext.Get<IEndpointRouter>(), logEndpoint));
+ applicationContext.RegisterSingleton<IDeploymentAction>(() => new CreateLogQueueAction(applicationContext.Get<MessageLoggingModule>(), applicationContext.Get<ITransport>()));
+ }
+
+ public void RegisterMsmqTransport(Type queueStrategyType)
+ {
+ if (queueStrategyType.GetConstructor(new[] {typeof (IQueueStrategy), typeof (Uri)}) != null)
+ {
+ applicationContext.RegisterSingleton(queueStrategyType, typeof (IQueueStrategy).FullName, applicationContext.Get<IEndpointRouter>(), config.Endpoint);
+ }
+ else
+ {
+ // use default
+ applicationContext.RegisterSingleton(queueStrategyType);
+ }
+
+ applicationContext.RegisterSingleton<IMessageBuilder<Message>>(() => new MsmqMessageBuilder(
+ applicationContext.Get<IMessageSerializer>(),
+ applicationContext.Get<IServiceLocator>()));
+
+ applicationContext.RegisterSingleton<IMsmqTransportAction>(() => new ErrorAction(
+ config.NumberOfRetries,
+ applicationContext.Get<IQueueStrategy>()));
+
+ applicationContext.RegisterSingleton<ISubscriptionStorage>(() => new MsmqSubscriptionStorage(
+ applicationContext.Get<IReflection>(),
+ applicationContext.Get<IMessageSerializer>(),
+ config.Endpoint,
+ applicationContext.Get<IEndpointRouter>(),
+ applicationContext.Get<IQueueStrategy>()));
+
+ applicationContext.RegisterSingleton<ITransport>(typeof (MsmqTransport).FullName, () => new MsmqTransport(
+ applicationContext.Get<IMessageSerializer>(),
+ applicationContext.Get<IQueueStrategy>(),
+ config.Endpoint,
+ config.ThreadCount,
+ applicationContext.GetAll<IMsmqTransportAction>().ToArray(),
+ applicationContext.Get<IEndpointRouter>(),
+ config.IsolationLevel,
+ config.Transactional,
+ config.ConsumeInTransaction,
+ applicationContext.Get<IMessageBuilder<Message>>()));
+
+ typeof (IMsmqTransportAction).Assembly.GetTypes()
+ .Where(x => typeof (IMsmqTransportAction).IsAssignableFrom(x) && x != typeof (ErrorAction) && !x.IsAbstract && !x.IsInterface)
+ .ToList()
+ .ForEach(x => applicationContext.RegisterSingleton(x, x.FullName));
+ }
+
+ public void RegisterQueueCreation()
+ {
+ applicationContext.RegisterSingleton(() => new QueueCreationModule(applicationContext.Get<IQueueStrategy>()));
+ }
+
+ public void RegisterMsmqOneWay()
+ {
+ var oneWayConfig = (OnewayRhinoServiceBusConfiguration) config;
+
+ applicationContext.RegisterSingleton<IMessageBuilder<Message>>(() => new MsmqMessageBuilder(applicationContext.Get<IMessageSerializer>(), applicationContext.Get<IServiceLocator>()));
+ applicationContext.RegisterSingleton<IOnewayBus>(() => new MsmqOnewayBus(oneWayConfig.MessageOwners, applicationContext.Get<IMessageBuilder<Message>>()));
+ }
+
+ public void RegisterRhinoQueuesTransport(string path, string name, bool enablePerformanceCounters)
+ {
+ applicationContext.RegisterSingleton<ISubscriptionStorage>(() => new PhtSubscriptionStorage(Path.Combine(path, name + "_subscriptions.esent"),
+ applicationContext.Get<IMessageSerializer>(),
+ applicationContext.Get<IReflection>()));
+
+ applicationContext.RegisterSingleton<ITransport>(typeof (RhinoQueuesTransport).FullName, () => new RhinoQueuesTransport(config.Endpoint,
+ applicationContext.Get<IEndpointRouter>(),
+ applicationContext.Get<IMessageSerializer>(),
+ config.ThreadCount,
+ Path.Combine(path, name + ".esent"),
+ config.IsolationLevel,
+ config.NumberOfRetries,
+ enablePerformanceCounters,
+ applicationContext.Get<IMessageBuilder<MessagePayload>>()));
+
+ applicationContext.RegisterSingleton<IMessageBuilder<MessagePayload>>(() => new RhinoQueuesMessageBuilder(applicationContext.Get<IMessageSerializer>()));
+ }
+
+ public void RegisterRhinoQueuesOneWay()
+ {
+ var oneWayConfig = (OnewayRhinoServiceBusConfiguration) config;
+
+ applicationContext.RegisterSingleton<IMessageBuilder<MessagePayload>>(() => new RhinoQueuesMessageBuilder(applicationContext.Get<IMessageSerializer>()));
+ applicationContext.RegisterSingleton<IOnewayBus>(() => new RhinoQueuesOneWayBus(oneWayConfig.MessageOwners, applicationContext.Get<IMessageSerializer>(), applicationContext.Get<IMessageBuilder<MessagePayload>>()));
+ }
+
+ public void RegisterSecurity(byte[] key)
+ {
+ applicationContext.RegisterSingleton<IEncryptionService>(() => new RijndaelEncryptionService(key));
+ applicationContext.RegisterSingleton<IValueConvertor<WireEcryptedString>>(() => new WireEcryptedStringConvertor(applicationContext.Get<IEncryptionService>()));
+ applicationContext.RegisterSingleton<IElementSerializationBehavior>(() => new WireEncryptedMessageConvertor(applicationContext.Get<IEncryptionService>()));
+ }
+
+ public void RegisterNoSecurity()
+ {
+ applicationContext.RegisterSingleton<IValueConvertor<WireEcryptedString>>(() => new ThrowingWireEcryptedStringConvertor());
+ applicationContext.RegisterSingleton<IElementSerializationBehavior>(() => new ThrowingWireEncryptedMessageConvertor());
+ }
+ }
+}
View
14 Rhino.ServiceBus.Spring/SpringLoadBalancerBootStrapper.cs
@@ -0,0 +1,14 @@
+using System;
+using Rhino.ServiceBus.LoadBalancer;
+
+namespace Rhino.ServiceBus.Spring
+{
+ [CLSCompliant(false)]
+ public sealed class SpringLoadBalancerBootStrapper : SpringBootStrapper
+ {
+ protected override Impl.AbstractRhinoServiceBusConfiguration CreateConfiguration()
+ {
+ return new LoadBalancerConfiguration();
+ }
+ }
+}
View
63 Rhino.ServiceBus.Spring/SpringServiceLocator.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using Rhino.ServiceBus.Impl;
+using Rhino.ServiceBus.Internal;
+using Rhino.ServiceBus.Spring;
+
+using Spring.Context;
+using Spring.Objects.Factory.Config;
+
+namespace Rhino.ServiceBus
+{
+ [CLSCompliant(false)]
+ public class SpringServiceLocator : IServiceLocator
+ {
+ private readonly IConfigurableApplicationContext applicationContext;
+
+ public SpringServiceLocator(IConfigurableApplicationContext applicationContext)
+ {
+ this.applicationContext = applicationContext;
+ }
+
+ public T Resolve<T>()
+ {
+ return applicationContext.Get<T>();
+ }
+
+ public object Resolve(Type type)
+ {
+ return applicationContext.Get(type);
+ }
+
+ public bool CanResolve(Type type)
+ {
+ return applicationContext.GetObjectsOfType(type).Count > 0;
+ }
+
+ public IEnumerable<T> ResolveAll<T>()
+ {
+ return applicationContext.GetAll<T>();
+ }
+
+ public IEnumerable<IHandler> GetAllHandlersFor(Type type)
+ {
+ IDictionary objectsOfType = applicationContext.GetObjectsOfType(type);
+ List<IHandler> handlers = new List<IHandler>();
+ foreach (DictionaryEntry dictionaryEntry in objectsOfType)
+ {
+ string objectName = (string) dictionaryEntry.Key;
+ IObjectDefinition objectDefinition = applicationContext.ObjectFactory.GetObjectDefinition(objectName);
+ handlers.Add(new DefaultHandler(objectDefinition.ObjectType, objectDefinition.ObjectType, () => applicationContext.GetObject(objectName)));
+ }
+
+ return handlers;
+ }
+
+ public void Release(object item)
+ {
+ // no need for spring
+ }
+ }
+}
View
113 Rhino.ServiceBus.Tests/Containers/Spring/Can_host_in_another_app_domain.cs
@@ -0,0 +1,113 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading;
+
+using Rhino.ServiceBus.Hosting;
+using Rhino.ServiceBus.Impl;
+using Rhino.ServiceBus.Spring;
+
+using Spring.Context;
+using Spring.Context.Support;
+
+using Xunit;
+
+namespace Rhino.ServiceBus.Tests.Containers.Spring
+{
+ public class Can_host_in_another_app_domain : MsmqTestBase, OccasionalConsumerOf<StringMsg>
+ {
+ private readonly RemoteAppDomainHost host = new RemoteAppDomainHost(
+ Path.Combine(Environment.CurrentDirectory, "Rhino.ServiceBus.Tests.dll"), typeof (TestBootStrapper));
+
+ private string reply;
+
+ private readonly ManualResetEvent resetEvent = new ManualResetEvent(false);
+
+ private readonly IConfigurableApplicationContext applicationContext;
+
+ public Can_host_in_another_app_domain()
+ {
+ applicationContext = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(applicationContext)
+ .UseStandaloneConfigurationFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AnotherBus.config"))
+ .Configure();
+ }
+
+ [Fact]
+ public void And_accept_messages_from_there()
+ {
+ host.Start();
+
+ using (var bus = applicationContext.Get<IStartableServiceBus>())
+ {
+ bus.Start();
+
+ using (bus.AddInstanceSubscription(this))
+ {
+ bus.Send(new Uri("msmq://localhost/test_queue").ToEndpoint(), new StringMsg
+ {
+ Value = "hello"
+ });
+
+ Assert.True(resetEvent.WaitOne(TimeSpan.FromSeconds(10), false));
+
+ Assert.Equal("olleh", reply);
+ }
+ }
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ host.Close();
+ }
+
+ public void Consume(StringMsg message)
+ {
+ reply = message.Value;
+ resetEvent.Set();
+ }
+ }
+
+ [CLSCompliant(false)]
+ public class SimpleBootStrapper : SpringBootStrapper
+ {
+ public SimpleBootStrapper(IConfigurableApplicationContext container)
+ : base(container)
+ {
+ }
+ }
+
+ [CLSCompliant(false)]
+ public class TestBootStrapper : SpringBootStrapper
+ {
+ protected override void ConfigureContainer()
+ {
+ ApplicationContext.RegisterPrototype<TestRemoteHandler>();
+ }
+ }
+
+ public class TestRemoteHandler : ConsumerOf<StringMsg>
+ {
+ private readonly IServiceBus bus;
+
+ public TestRemoteHandler(IServiceBus bus)
+ {
+ this.bus = bus;
+ }
+
+ public void Consume(StringMsg message)
+ {
+ bus.Reply(new StringMsg
+ {
+ Value = new String(message.Value.Reverse().ToArray())
+ });
+ }
+ }
+
+ public class StringMsg
+ {
+ public string Value { get; set; }
+ }
+}
View
152 Rhino.ServiceBus.Tests/Containers/Spring/ContainerTests.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Linq;
+
+using Rhino.ServiceBus.Actions;
+using Rhino.ServiceBus.Exceptions;
+using Rhino.ServiceBus.Impl;
+using Rhino.ServiceBus.Internal;
+using Rhino.ServiceBus.LoadBalancer;
+using Rhino.ServiceBus.MessageModules;
+using Rhino.ServiceBus.Msmq;
+using Rhino.ServiceBus.Spring;
+
+using Spring.Context.Support;
+
+using Xunit;
+
+namespace Rhino.ServiceBus.Tests.Containers.Spring
+{
+ public class ContainerTests
+ {
+ [Fact]
+ public void Consumer_must_be_transient()
+ {
+ StaticApplicationContext container = new StaticApplicationContext();
+ container.RegisterPrototype<TestConsumer>();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .Configure();
+
+ try
+ {
+ container.Get<TestConsumer>();
+ }
+ catch (Exception ex)
+ {
+ Assert.True(null != ex.InnerException as InvalidUsageException);
+ }
+ }
+
+ [Fact]
+ public void Bus_instance_is_singleton()
+ {
+ var container = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .Configure();
+
+ var startable = container.Get<IStartableServiceBus>();
+ var bus = container.Get<IServiceBus>();
+ Assert.Same(startable, bus);
+ }
+
+ [Fact]
+ public void Oneway_bus_is_singleton()
+ {
+ var container = new StaticApplicationContext();
+ new OnewayRhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .Configure();
+
+ var oneWayBus = container.Get<IOnewayBus>();
+ var second = container.Get<IOnewayBus>();
+ Assert.Same(oneWayBus, second);
+ }
+
+ [Fact]
+ public void RhinoQueues_bus_is_registered()
+ {
+ var container = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .UseStandaloneConfigurationFile("RhinoQueues/RhinoQueues.config")
+ .Configure();
+
+ var bus = container.Get<IServiceBus>();
+ Assert.NotNull(bus);
+ }
+
+ [Fact]
+ public void LoadBalancer_is_singleton()
+ {
+ var container = new StaticApplicationContext();
+ new LoadBalancerConfiguration()
+ .UseSpring(container)
+ .UseStandaloneConfigurationFile("LoadBalancer.config")
+ .Configure();
+
+ var startable = container.Get<IStartable>();
+ var loadBalancer = container.Get<MsmqLoadBalancer>();
+ Assert.Same(startable, loadBalancer);
+ }
+
+ [Fact]
+ public void Registers_logging_module()
+ {
+ var container = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .UseStandaloneConfigurationFile("BusWithLogging.config")
+ .Configure();
+
+ var loggingModule = container.Get<MessageLoggingModule>(typeof (MessageLoggingModule).FullName);
+ Assert.NotNull(loggingModule);
+ }
+
+ [Fact]
+ public void Registers_load_balancer_module()
+ {
+ var container = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .UseStandaloneConfigurationFile("LoadBalancer/BusWithLoadBalancer.config")
+ .Configure();
+
+ var loadBalancerMessageModule = container.Get<LoadBalancerMessageModule>(typeof (LoadBalancerMessageModule).FullName);
+ Assert.NotNull(loadBalancerMessageModule);
+ }
+
+ [Fact]
+ public void QueueCreationModule_can_be_resolved()
+ {
+ var container = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .Configure();
+
+ var allBusAware = container.GetAll<IServiceBusAware>().ToList();
+ Assert.NotEmpty(allBusAware);
+ Assert.IsType<QueueCreationModule>(allBusAware.First());
+ }
+
+ [Fact]
+ public void DeploymentActions_can_be_resolved()
+ {
+ var container = new StaticApplicationContext();
+ new RhinoServiceBusConfiguration()
+ .UseSpring(container)
+ .UseStandaloneConfigurationFile("BusWithLogging.config")
+ .Configure();
+
+ var actions = container.GetAll<IDeploymentAction>().ToList();
+ Assert.True(actions.Count >= 2);
+ }
+ }
+
+ public class TestConsumer : ConsumerOf<string>
+ {
+ public void Consume(string message)
+ {
+ }
+ }
+}
View
12 Rhino.ServiceBus.Tests/Rhino.ServiceBus.Tests.csproj
@@ -46,6 +46,9 @@
<Reference Include="Castle.Windsor">
<HintPath>$(LibDir)Castle.Windsor.dll</HintPath>
</Reference>
+ <Reference Include="Common.Logging">
+ <HintPath>..\SharedLibs\Common.Logging.dll</HintPath>
+ </Reference>
<Reference Include="log4net">
<HintPath>..\SharedLibs\log4net.dll</HintPath>
</Reference>
@@ -76,6 +79,9 @@
<Reference Include="Rhino.Queues">
<HintPath>$(LibDir)Rhino.Queues.dll</HintPath>
</Reference>
+ <Reference Include="Spring.Core">
+ <HintPath>..\SharedLibs\4.0\Spring.Core.dll</HintPath>
+ </Reference>
<Reference Include="StructureMap">
<HintPath>..\SharedLibs\StructureMap.dll</HintPath>
</Reference>
@@ -130,6 +136,8 @@
<Compile Include="CanCustomizeHeadersWithMsmq.cs" />
<Compile Include="Containers\Autofac\Can_host_in_another_app_domain.cs" />
<Compile Include="Containers\Autofac\ContainerTests.cs" />
+ <Compile Include="Containers\Spring\Can_host_in_another_app_domain.cs" />
+ <Compile Include="Containers\Spring\ContainerTests.cs" />
<Compile Include="Containers\StructureMap\Can_host_in_another_app_domain.cs" />
<Compile Include="Containers\StructureMap\ContainerTests.cs" />
<Compile Include="Containers\Unity\Can_host_in_another_app_domain.cs" />
@@ -200,6 +208,10 @@
<Project>{4D65E756-C0C9-42AA-9B73-75E85E77EA7B}</Project>
<Name>Rhino.ServiceBus.Castle</Name>
</ProjectReference>
+ <ProjectReference Include="..\Rhino.ServiceBus.Spring\Rhino.ServiceBus.Spring.csproj">
+ <Project>{E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}</Project>
+ <Name>Rhino.ServiceBus.Spring</Name>
+ </ProjectReference>
<ProjectReference Include="..\Rhino.ServiceBus.StructureMap\Rhino.ServiceBus.StructureMap.csproj">
<Project>{C0B1E3BD-3481-4E0E-866F-5BEC471C2F4C}</Project>
<Name>Rhino.ServiceBus.StructureMap</Name>
View
10 Rhino.ServiceBus.sln
@@ -1,4 +1,5 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
+
+Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Starbucks", "Starbucks", "{64DC50EF-F634-4E75-8375-ACC6D42E2DB4}"
EndProject
@@ -22,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhino.ServiceBus.Autofac",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhino.ServiceBus.Unity", "Rhino.ServiceBus.Unity\Rhino.ServiceBus.Unity.csproj", "{DB720C4D-1508-4510-AED4-80C905095CE5}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhino.ServiceBus.Spring", "Rhino.ServiceBus.Spring\Rhino.ServiceBus.Spring.csproj", "{E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -64,6 +67,10 @@ Global
{DB720C4D-1508-4510-AED4-80C905095CE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB720C4D-1508-4510-AED4-80C905095CE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB720C4D-1508-4510-AED4-80C905095CE5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -75,5 +82,6 @@ Global
{4D65E756-C0C9-42AA-9B73-75E85E77EA7B} = {2271E8BF-21FF-40B1-A284-F707951F5EA2}
{E18B8442-40AF-4FA2-9FB0-FC05FC994CEA} = {2271E8BF-21FF-40B1-A284-F707951F5EA2}
{DB720C4D-1508-4510-AED4-80C905095CE5} = {2271E8BF-21FF-40B1-A284-F707951F5EA2}
+ {E18B8442-40AF-F3A1-9FB0-F1C5FC994CEA} = {2271E8BF-21FF-40B1-A284-F707951F5EA2}
EndGlobalSection
EndGlobal
View
BIN SharedLibs/3.5/Spring.Core.dll
Binary file not shown.
View
BIN SharedLibs/3.5/Spring.Core.pdb
Binary file not shown.
View
49,235 SharedLibs/3.5/Spring.Core.xml
49,235 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
BIN SharedLibs/4.0/Spring.Core.dll
Binary file not shown.
View
BIN SharedLibs/4.0/Spring.Core.pdb
Binary file not shown.
View
49,235 SharedLibs/4.0/Spring.Core.xml
49,235 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
BIN SharedLibs/Common.Logging.dll
Binary file not shown.
View
10 default.ps1
@@ -32,7 +32,8 @@ task Init -depends Clean {
"$base_dir\Rhino.ServiceBus.Castle\Properties\AssemblyInfo.cs",
"$base_dir\Rhino.ServiceBus.StructureMap\Properties\AssemblyInfo.cs",
"$base_dir\Rhino.ServiceBus.Autofac\Properties\AssemblyInfo.cs",
- "$base_dir\Rhino.ServiceBus.Unity\Properties\AssemblyInfo.cs"
+ "$base_dir\Rhino.ServiceBus.Unity\Properties\AssemblyInfo.cs",
+ "$base_dir\Rhino.ServiceBus.Spring\Properties\AssemblyInfo.cs"
);
$infos | foreach { Generate-Assembly-Info `
@@ -101,6 +102,13 @@ task Release -depends Test {
*\Microsoft.Practices.Unity.Interception.dll `
*\Rhino.ServiceBus.Unity.dll `
*\Rhino.ServiceBus.Unity.pdb `
+ *\Common.Logging.dll `
+ *\Spring.Core.dll `
+ *\Spring.Core.pdb `
+ *\Spring.Core.xml `
+ *\Common.Logging.dll `
+ *\Rhino.ServiceBus.Spring.dll `
+ *\Rhino.ServiceBus.Spring.pdb `
*\Rhino.ServiceBus.Host.exe `
*\Rhino.ServiceBus.Host.pdb `
*\Wintellect.Threading.dll `

0 comments on commit e94c623

Please sign in to comment.