Pergunta

Eu tenho meu sistema dividido em 2 partes.Ambas as partes se comunicam com cada outro usando Rhino Service Bus. Não há problema no Windows 7, mas se eu iniciá-lo em qualquer outro lugar (WinXP, Server 2003, ...) Recebo a seguinte exceção quando eu chamo Rhino.ServiceBus.Hosting.DefaultHost.Start(..):

System.NullReferenceException: Object reference not set to an instance of an object.
   at Spring.Objects.Factory.Support.AbstractObjectFactory.GetObjectFromFactoryObject(IFactoryObject factory, String objectName, RootObjectDefinition rod)
   at Spring.Objects.Factory.Support.AbstractObjectFactory.GetObjectForInstance(Object instance, String name, String canonicalName, RootObjectDefinition rod)
   at Spring.Objects.Factory.Support.AbstractObjectFactory.GetObjectInternal(String name, Type requiredType, Object[] arguments, Boolean suppressConfigure)
   at Spring.Objects.Factory.Support.AbstractObjectFactory.GetObject(String name)
   at Spring.Context.Support.AbstractApplicationContext.GetObject(String name)
   at Rhino.ServiceBus.Spring.ApplicationContextExtensions.Get(IApplicationContext context, Type type)
   at Rhino.ServiceBus.Spring.ApplicationContextExtensions.Get[T](IConfigurableApplicationContext context)
   at Rhino.ServiceBus.Spring.SpringBootStrapper.GetInstance[T]()
   at Rhino.ServiceBus.Hosting.DefaultHost.InitailizeBus(String asmName)
   at Rhino.ServiceBus.Hosting.DefaultHost.Start(String asmName)

Aqui está o fragmento do Spring log:

2012-01-14 13:25:01,084 DEBUG Spring.Objects.Factory.Support.DefaultListableObjectFactory - Invoking IObjectPostProcessors after initialization of object '351a5f07-e33d-4be0-84cf-1738a8feba24'
2012-01-14 13:25:01,084 DEBUG Spring.Objects.Factory.Support.DefaultListableObjectFactory -          GetObjectInternal: returning instance for objectname 351a5f07-e33d-4be0-84cf-1738a8feba24
2012-01-14 13:25:01,084 ERROR Spring.Objects.Factory.Support.DefaultListableObjectFactory -       GetObjectInternal: error obtaining object Rhino.ServiceBus.Msmq.FlatQueueStrategy
2012-01-14 13:25:01,084 ERROR Spring.Objects.Factory.Support.DefaultListableObjectFactory -    GetObjectInternal: error obtaining object Rhino.ServiceBus.Msmq.MsmqTransport
2012-01-14 13:25:01,084 ERROR Spring.Objects.Factory.Support.DefaultListableObjectFactory - GetObjectInternal: error obtaining object 1a769f24-5410-4cee-8d7a-76c3a91b1ce1
Foi útil?

Solução

Problema resolvido: No MSMQ versão 3 ou inferior (em sistemas como Windows XP, Windows Server 2003), as subfilas não são suportadas e, portanto, Rhino SB usa FlatQueueStrategy para gerenciar as filas. Ocorrem problemas quando o contêiner de objeto Spring é configurado. Concretamente, existem dois lugares na classe Rhino.ServiceBus.Spring.SpringBuilder onde as modificações precisam ser feitas.

1) método RegisterMsmqTransport :

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

a segunda parte da instrução if é sempre chamada, porque FlatQueueStrategy não tem construtor com parâmetros do tipo IQueueStrategy e Uri. Mas não tem nem o construtor sem parâmetros. Portanto, FlatQueueStrategy não está registrado corretamente no contêiner de objetos. A modificação para esta parte seria:

if (queueStrategyType.GetConstructor(new[] { typeof(IEndpointRouter), typeof(Uri) }) != null)
{
    applicationContext.RegisterSingleton(queueStrategyType, typeof (IQueueStrategy).FullName, applicationContext.Get<IEndpointRouter>(), config.Endpoint);
}
else
{
    // use default
    applicationContext.RegisterSingleton(queueStrategyType);
}

2) método RegisterDefaultServices

O próximo problema está no método RegisterDefaultServices:

    applicationContext.RegisterSingleton<IServiceLocator>(() => new SpringServiceLocator(applicationContext));
    applicationContext.RegisterSingletons<IBusConfigurationAware>(typeof(IServiceBus).Assembly);

    foreach (var busConfigurationAware in applicationContext.GetAll<IBusConfigurationAware>())
    {
        busConfigurationAware.Configure(config, this);  // here is the method RegisterMsmqTransport called
    }

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

o método RegisterMsmqTransport é chamado antes de IEndpointRouter ser registrado no contêiner de objeto. IEndpointRouter é usado no método RegisterMsmqTransport (ver 1) e, portanto, chamada de método

    applicationContext.Get<IEndpointRouter>()

produz uma exceção. A modificação aqui seria:

    applicationContext.RegisterSingleton<IServiceLocator>(() => new SpringServiceLocator(applicationContext));
    applicationContext.RegisterSingletons<IBusConfigurationAware>(typeof(IServiceBus).Assembly);
    applicationContext.RegisterSingleton<IReflection>(() => new DefaultReflection());
    applicationContext.RegisterSingleton<IEndpointRouter>(() => new EndpointRouter());

    foreach (var busConfigurationAware in applicationContext.GetAll<IBusConfigurationAware>())
    {
        busConfigurationAware.Configure(config, this);
    }

    foreach (var module in config.MessageModules)
    {
        applicationContext.RegisterSingleton(module, module.FullName);
    }

    applicationContext.RegisterSingleton(config.SerializerType);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top