Domanda

Ho il mio sistema diviso in 2 parti.Entrambe le parti comunicano tra loro altro utilizzando Rhino Service Bus. Non ci sono problemi su Windows 7, ma se lo avvio da qualche altra parte (WinXP, Server 2003, ...) Ottengo la seguente eccezione quando chiamo 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)

Ecco il frammento del registro di primavera:

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
È stato utile?

Soluzione

Problema risolto: Nella versione 3 di MSMQ o inferiore (su sistemi come Windows XP, Windows Server 2003), le sottocodette non sono supportate e quindi Rhino SB utilizza FlatQueueStrategy per la gestione delle code. Si verificano problemi quando viene configurato il contenitore di oggetti Spring. In concreto, ci sono due posti nella classe Rhino.ServiceBus.Spring.SpringBuilder in cui è necessario apportare modifiche.

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

la seconda parte dell'istruzione if viene sempre chiamata, perché FlatQueueStrategy non ha un costruttore con parametri di tipo IQueueStrategy e Uri. Ma non ha nemmeno il costruttore senza parametri. Quindi FlatQueueStrategy non è registrato correttamente nel contenitore di oggetti. La modifica per questa parte sarebbe:

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) metodo RegisterDefaultServices

Il problema successivo è nel metodo 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());

il metodo RegisterMsmqTransport viene chiamato prima che IEndpointRouter venga registrato nel contenitore di oggetti. IEndpointRouter viene utilizzato nel metodo RegisterMsmqTransport (vedere 1) e quindi nella chiamata al metodo

    applicationContext.Get<IEndpointRouter>()

produce un'eccezione. La modifica qui sarebbe:

    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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top