Here’s something that bit me, maybe you can add a note to the docs on the wiki (https://github.com/ServiceStack/ServiceStack/wiki/Messaging)
The example looks like this:
public class AppHost : AppSelfHostBase
{
public override void Configure(Container container)
{
//Register to use a Rabbit MQ Server
container.Register<IMessageService>(c => new RabbitMqServer());
var mqServer = container.Resolve<IMessageService>();
//Register message handlers here...
mqServer.RegisterHandler<HandleExampleMessageRequest>(ServiceController.ExecuteMessage);
//Start the Rabbit MQ Server listening for incoming MQ Requests
mqServer.Start();
}
}
However, if your message handler calls a service, which publishes a new message, you could get a NullReferenceException on the first message or two (depending how busy the queue is).
public class ExampleService : Service
{
public void Post(HandleExampleMessageRequest request)
{
//Do stuff here
//This throws NRE on the first call if the MQ service is started in AppHost.Configure
PublishMessage(new DoNextStep
{
Id = request.Id
});
}
}
Stack trace
System.NullReferenceException: Object reference not set to an instance of an object.
at ServiceStack.ServiceStackHost.GetMessageProducer(IRequest req)
at ServiceStack.Service.get_MessageProducer()
at ServiceStack.Service.PublishMessage[T](T message)
at ServiceInterface.ExampleService.Post(HandleExampleMessageRequest request) in ExampleService.cs:line 10
at lambda_method(Closure , Object , Object )
at ServiceStack.Host.ServiceExec`1.<>c__DisplayClass6.<CreateExecFn>b__5(Object service, Object request)
at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)
This is because the IMessageFactory
(which is automatically registered in ServiceStackHost.OnAfterInit
) is not available until the AppHost has completed initializing.
To avoid this problem, the MQ service should be started in an AfterInitCallback.
public class AppHost : AppSelfHostBase
{
public AppHost()
: base("My Services", new[] { typeof(HandleExampleMessageRequest).Assembly })
{
AfterInitCallbacks.Add(StartMqServer);
}
private void StartMqServer(IAppHost appHost)
{
//Start MQ consumers
appHost.GetContainer().Resolve<IMessageService>().Start();
}
}