I have a bus endpoint that processes a message, however I now want to put another message back on to the bus inside this handler.
To do this I need to get a reference to the bus.
However if I try the following:
public class ServerEndpoint: IWantToRunAtStartup
{
public static IBus Bus { get; set; }
public void Run()
{
int x = 5;
Bus = NServiceBus.Configure.With()
.DisableTimeoutManager()
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(false)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();
}
public void Stop()
{
}
}
Then I get all sort of config errors, even if I put the Unicast and Msmq Configs in the app.config.
Could anyone provide me with pointers, I'm hoping this is a fairly straightforward mistake!!
Thanks
Duncan
EDIT: This is on the server. The thing that is confusing me is that the bus gets configured on the web app using the above code, in the global.asax App_Start() method. But when trying to do this in the ServerEndpoint (the actual 'bus' dll, run inside the host) this doesn't work.
You use Dependency Injection for that, see http://support.nservicebus.com/customer/portal/articles/862398-how-do-i-get-a-reference-to-ibus-in-my-message-handler-
Thanks for all the feedback - I was trying to run before I could walk.
By the looks of things, to send a message to another endpoint, I need to set up a different assembly (ServiceBus.Host).
The Bus is created automatically using DI, so this wasn't the problem after all.
I watched the excellent Pluralsight videos by Andreas Ohlund (http://pluralsight.com/training/Courses/TableOfContents/nservicebus) and followed the examples he built here (See BusStop - Billing Take 2)
Related
I am new to Rebus.
There are one questions i want to ask:
It is a good idea to make web app publish message and subscribe to message. And does Rebus support this features.
I test Server mode , however it does not work. It handles the message only one message(from pubsubsample.websubscriber1.input queue) when web app starts.
BTW,It works well on One-way client mode.(Send message only)
Here is my code segment for server modeļ¼
public class CheckStatus : IHandleMessages<NewTradeRecorded>
{
readonly IBus bus;
public CheckStatus(IBus bus)
{
this.bus = bus;
}
public void Handle(NewTradeRecorded message)
{
}
}
Asp.net MVC
protected void Application_Start()
{
using (var adapter = new BuiltinContainerAdapter())
{
adapter.Register(() => new CheckStatus(adapter.Bus));
Configure.With(adapter)
.Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
.MessageOwnership(o => o.FromRebusConfigurationSection())
.CreateBus()
.Start();
adapter.Bus.Subscribe<NewTradeRecorded>();
}
}
web.config
<rebus inputQueue="pubsubsample.websubscriber1.input" errorQueue="pubsubsample.websubscriber1.error" workers="1" maxRetries="5">
<endpoints>
<add messages="Trading.Messages" endpoint="trading.input"/>
</endpoints>
To answer your first question, whether Rebus supports publishing and subscribing from the same process, the answer is yes - there's no technical reason why you cannot subscribe to messages and publish the same messages from the same process, and that includes your web application.
Whether you should is another thing :)
Web applications in .NET are kind of transient in nature, i.e. they're recycled when IIS decides that it's time to recycle, and then it's usually not the best idea to subscribe to messages, because your application might not be running when an event is published, so it's not around to handle it.
And then, when it wakes up because IIS dispatches a web request to it, you might have 1,000,000 events waiting to be handled by your application, which will take quite a while to chew through.
In some cases, I've heard of people wanting to use Rebus pub/sub in web applications to keep a cache updated in the web app - but then they had severe issues, coming from the fact that IIS supports overlapping two instances of the same web application - iow, suddenly, for a short while, two instances of the same web applications were running, thus allowing a web application about to shut down to snatch a few events that should have been handled by the new instance.
For these reasons, in general I would not recomment doing pub/sub in web applications.
So, why doesn't your pub/sub thing work? Well - first thing: Don't dispose the container adapter immediately after creating it! :)
Do this instead:
static readonly _stuffToDispose = new List<IDisposable>();
protected void Application_Start()
{
var adapter = new BuiltinContainerAdapter();
_stuffToDispose.Add(adapter);
adapter.Register(() => new CheckStatus(adapter.Bus));
Configure.With(adapter)
.Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
.MessageOwnership(o => o.FromRebusConfigurationSection())
.CreateBus()
.Start();
adapter.Bus.Subscribe<NewTradeRecorded>();
}
protected void Application_End()
{
_stuffToDispose.ForEach(d => d.Dispose());
}
This way, you bus will not stop handling messages immediately after your web app has started.
So I'm trying to send a simple message from a SharePoint webpart to an endpoint. For now, i'm setting the bus in a simple static class use in the webpart. The class gets called and the bus seems to be working, but when i try to send the message, i get:
No destination specified for message SharePointMessages.CreateProject. Message cannot be sent. Check the UnicastBusConfig section in your config file and ensure that a MessageEndpointMapping exists for the message type.
The class looks like this:
public static class Infrastructure
{
public static IBus Bus { get; private set; }
static Infrastructure()
{
var mappings = new MessageEndpointMappingCollection();
mappings.Add(new MessageEndpointMapping()
{
Messages = "SharePointMessages.CreateProject",
Endpoint = "SharePointProxy"
});
Configure config = Configure.WithWeb();
config
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.UnicastBus()
.Configurer.ConfigureComponent<UnicastBusConfig>(ComponentCallModelEnum.None)
.ConfigureProperty(x => x.MessageEndpointMappings, mappings);
Bus = config.CreateBus().Start();
}
}
The SharePointMessages.CreateProject class implements IMessage and has two properties.
The queues get created properly if they are not there. So it seems like everything is working but for some reason the mappings are not there. Can anyone see what I'm doing wrong?
Cheers
You have to use a custom configuration source - http://docs.particular.net/nservicebus/messaging/message-owner
After adding section for SQL Database to handle subscriptions, My subscriber config looks like this
;initial catalog=NServiceBus;Integrated Security=SSPI"/>
I changed the endpoint class as follows
class EndpointConfig : IConfigureThisEndpoint, AsA_Server , IWantCustomInitialization
{
public void Init()
{
NServiceBus.Configure.With()
.Log4Net()
.DefaultBuilder()
.XmlSerializer()
.UnicastBus()
.ImpersonateSender(false)
.DBSubcriptionStorage();
}
}
When I fire up the application, where subscribers automatically subscribe, I don't see any entries in the subscription DB. Also I don't see any error reported by the application... Anything I am missing in the config file...
Appreciate any help...
When using the builtin roles like As_aServer the role config takes precedence. So in your case the db sub.storage will only be used if you use As_aPublisher + run in the "production" profile.
I'm getting started with NServiceBus and have a question about the Pubsub sample.
My intention was to have multiple instances of Publisher1 running and receiving the message sent from the publisher. I also hacked the Publisher to only send messages of the eventMessage type.
But if I start the publisher and three instances of Subscriber1, only one of them gets the message at a time.
why is that? Is it a config setting or something else?
This is what I've tried which returns an exception "Exception when starting endpoint, error has been logged. Reason: Cannot configure property before the component has been configured. Please call 'Configure' first.":
using NServiceBus;
namespace Subscriber1
{
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
{
}
public class OverrideInputQueue : IWantCustomInitialization
{
public void Init()
{
Configure
.Instance
.Configurer
.ConfigureProperty<NServiceBus.Config.MsmqTransportConfig>(t => t.InputQueue, "testQueue");
}
}
}
/J
NServiceBus assumes that you have one input queue per process. Make sure that each of your subscribers are configured with a unique input queue. If not all three will be polling the same queue producing the behavior you're describing.
To do this you would probably have to copy paste sub1 to 3 different folders, modfying the app.config and start them up.
Hope this helps!
You should use this-
Configure.Instance.Configurer.ConfigureProperty<NServiceBus.Unicast.Transport.Msmq.MsmqTransport>(msmq => msmq.InputQueue, "SomeQueueHere");
Make sure you use MsmqTransport and not MsmqTransportConfig as you mentioned.
I am just starting to play with nservice bus and am trying to get publishing working. I have a listener which seems to be missing some messages. It is configured with
<MsmqTransportConfig
InputQueue="InformMessages"
ErrorQueue="error"
NumberOfWorkerThreads="5"
MaxRetries="5"
/>
Interestingly if I set NumberOfWorkerThreads to 1 it consistently misses every other message. For larger values it seems less determinate. In my message handler I have
class MessageHandler : IMessageHandler<ICourseRegister>
{
public void Handle(ICourseRegister message)
{
Console.WriteLine("Message dun got gotted");
Console.WriteLine("Course name is: " + message.CourseName);
}
private IBus bus;
public IBus Bus
{
set { this.bus = value; }
}
}
and the bus is configured with
var bus = NServiceBus.Configure.With()
.SpringBuilder()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.LoadMessageHandlers()
.CreateBus()
.Start();
Is there something I need to do and the end of Handler such that it is freed ready to receive the next message or some configuration I need to do so that there is a client side queue to retain messages if the handler is busy. The time between sending messages doesn't seem to matter, it could be 20 seconds and the listener still doesn't get all the messages.
After taking a look at the solution you sent over, I see what the problem is.
You've specified the same input queue for both processes - the publisher and the subscriber. As a result, you have both processes fighting over the messages which (I think) you intend to be going only to the subscriber.
Give each process its own input queue and everything should be right with the world :-)
If you're working similar to the pub/sub sample, what you could be seeing is "polymorphic subscriptions".
In the pub/sub sample, the publisher alternately publishes an interface IEvent and a concrete class EventMessage (which inherits IEvent).
If a subscriber is subscribed to the concrete class, then it won't receive the interface messages. This is true for all kinds of hierarchies, if you subscribe to the specific class, and the publisher publishes a message of the type of its base class, the message won't be dispatched.
The polymorphic subscriptions works the other way around. If you subscribe to the base, any subclass that the publisher publishes will arrive.
This has nothing to do with threading.
Hope that helps.