Remove/Override RabbitMq TopologyRecoveryException logs in .NET - c#

As per the RabbitMq java client API, https://www.rabbitmq.com/api-guide.html#recovery
Unhandled exceptions related to connection, channel, recovery and
consumer lifecycle are delegated to the exception handler. Exception
handler is any object that implements the ExceptionHandler interface.
By default, an instance of DefaultExceptionHandler is used. It prints
exception details to the standard output.
It is possible to override the handler using
ConnectionFactory#setExceptionHandler. It will be used for all
connections created by the factory:
we have
ConnectionFactory factory = new ConnectionFactory();
cf.setExceptionHandler(customHandler);
What is the same implementation for .NET RabbitMq client? Adding this code is still writing console logs and not executing my logic and How do I remove the existing event handler?
var factory = new ConnectionFactory() { HostName = "localhost" };
var connection = factory.CreateConnection();
connection.CallbackException += (x, y) => {
Console.WriteLine("Handled"); // not printing
};
I would like to override/remove the logs which are printing to console because of topologyrecoveryexception.
Could anyone help me on how to override this default behavior of logs to console by RabbitMq.Client using v4.1. Any help is greatly appreciated.

First you should upgrade to the latest 5.X .NET client.
Then, notice in the ChangeLog file that console logging was replaced by event source (link).
CallbackException is used when one of your callbacks raises an exception, I believe. It has nothing to do with exceptions generated by the library.
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.

Related

IBMMQDotnetClient vs IBMXMSDotnetClient

I am working on a project, which needs to connect to IBM MQ using c#, and considering which NuGet package is the best one.
However, there are 2 NuGet packages IBMMQDotnetClient and IBMXMSDotnetClient and both of them are provided by the official (IBM).
After reading a few references,
Difference between nuget packages IBMMQDotnetClient and IBMXMSDotnetClient (IBM MQ support for .Net Core)
https://www.ibm.com/support/pages/xms-net-%E2%80%93-overview
It looks like that me that there are 2 main differences between these 2 API.
IBMXMSDotnetClient provides more functionalities
IBMXMSDotnetClient provides JMS-like API. If someone is using Java before, it is more easier to port the Java code to .Net
Another difference I noticed is that the way they are connecting to the MQ server (QueueManager vs Connection and Session). But it is not really a problem, just different styles as far as I can see.
IBMMQDotnetClient
MQEnvironment.Hostname = hostName;
MQEnvironment.Channel = channel;
// Queue Manager object
MQQueueManager queueManager = new MQQueueManager(queueManagerName);
int openOptions = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT;
MQQueue system_default_local_queue = queueManager .AccessQueue(queueName, openOptions);
IBMXMSDotnetClient
XMSFactoryFactory factoryFactory;
IConnectionFactory cf;
IDestination destination;
factoryFactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
cf = factoryFactory.CreateConnectionFactory();
cf.SetStringProperty(XMSC.WMQ_HOST_NAME, hostName);
cf.SetIntProperty(XMSC.WMQ_PORT, port);
cf.SetStringProperty(XMSC.WMQ_CHANNEL, channel);
cf.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT);
// Queue Manager just as an simple string property here
cf.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, queueManagerName);
If it is the case, I cannot see any reason why I do not choose IBMXMSDotnetClient.
But the weird thing is that there are 327K downloads for IBMMQDotnetClient while there are only 160k downloads for IBMXMSDotnetClient.
Or there are some key advantages of IBMMQDotnetClient I missed?
IBMMQDotNet provides MQ native APIs in .NET language while IBMXMSDotNet provides JMS style of APIs in .NET. However there is one major difference between the two APIs: IBMXMSDotNet provides asynchronous message consumer while IBMMQDotNet does not. Asynchronous message consumption is a type of consuming messages where IBMXMSDotNet automatically calls application registered callback method whenever a message arrives in MQ queue. With IBMMQDotNet, you will need to do a synchronous Get call (with or without timeout) to receive messages.
Hope this helps
Update: 16th May 2022
One example: In case of MQDotNet, you can change selection criteria to read messages matching another criteria without reopening a queue. For example you can say "select message matching groupId x" first from the queue to read messages matching the given groupId. Then you can say "select message matching groupId y" from the same queue without reopening queue. In case of XMSDotNet, the selection createria is specified while creating the consumer (which internally opens a MQ queue). Consumer must be recreated if you want to change selection criteria to consume messages with another criteria

Azure TopicClient.Send() never sends a message and it hangs

I am attempting to follow a Windows Azure tutorial to send a message to a topic on Microsoft's Azure service bus. I have created the namespace and the topic. I then set up ACS and grabbed my connection string. My connection string allows Manage, Listen, Send. When I execute my code, the Send(message) just hangs. It never times-out nor does it continue. The CPU is not maxed and I can break out of the code and close the program. No message arrives in Azure. When I watch my network traffic in fiddler, it looks to me like it is never finishing the authentication negotiations. I see a post to my namespace .servicebus.windows.net that returns a 201 then a post and a get at an IP address that belongs to Azure service bus with a /$servicebus/webstring/{guid}. Neither of these web request ever get a response back from the server. Here is my code. It stops running on client.Send(message);
static void Main(string[] args)
{
ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;
string connectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"];
var client = TopicClient.CreateFromConnectionString(connectionString, "clients");
Console.WriteLine(client.IsClosed);
var message = new BrokeredMessage("Test message.") {TimeToLive = TimeSpan.FromMinutes(15)};
client.Send(message);
Console.WriteLine("Done");
Console.ReadKey();
}
Any ideas on how to get this code to post a message to Azure service bus?
I'm also seeing this behavior when using this code and it appears to be linked to the ServiceBusEnvironment.SystemConnectivity.Mode you have set. If you comment that out it goes through. That mode isn't mentioned in the tutorial. The default the mode is Auto and it detects if it can send via TCP first.
With that said, I'd like to suggest you use the following code instead:
string connectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"];
MessagingFactory factory = MessagingFactory.CreateFromConnectionString(connectionString);
MessageSender testQueue = factory.CreateMessageSender("TestTopic");
BrokeredMessage message = new BrokeredMessage("Test message ");
testQueue.Send(message);
One of the benefits of using the MessageSender instead of the TopicClient or QueueClient directly is that your code doesn't care if the destination is a Topic or a Queue. If you later needed to change from one to another your code here wouldn't have to change. Likewise, using a MessageReceiver on the consuming code is better as well.
I dont see that issue, I can post the message on a topic with same code and receive it via a subscription as well. The SAS key I use is generated on Topic itself. My the issue you had was temporary issue?
It appears to be our corporate firewall. It is actively refusing connections on unknown ports (9354) instead of passively. This seems to keep the Microsoft library for Azure from auto-detecting the connection and switching to https. It appears that with an active refusal of the connection at 9354 an exception get thrown in the library instead of trying http. Likewise, if I set the mode to just Http, it hangs, but when I am outside the corporate firewall it does not hang. It would be nice if this library worked with an active refusal on port 9354.

How to use SubscriptionClient.OnMessage for a subscription that requires a session

I've been looking at the new message pump available with version 2.0 of the azure service bus. In particular, I'm using topics and subscriptions (and not the queues).
I can get the message pump to work with a non-session subscription and it raises the Message event whenever a brokeredMessage is available. However, when I try to use a subscription that requires a session, I get the following error...
InvalidOperationException: It is not possible for an entity that requires sessions to create a non-sessionful message receiver
Does anyone have a way to use the new OnMessage event with a subscription that requires a session?
This feature is not yet available, we are working on adding support for OnMessage API on the MessageSession class and that will show up in a future SDK release. We will however add OnMessage support to the MessageReciever class in this SDK update.

CommunicationState listener?

Does anyone know of a way to create a listener for a proxy so that when the CommunicationState has changed I can invoke an action or a method?
An example, I want to update my WCF service for a code change. Since the application is in its early development code changes are very frequent. However, instead of annoying my employees with an email tell them that hey they need to restart their application. I would rather avoid them having to restart the app and having to send them an email. I would rather write a listener that looks at the communication state of a service and if it has changed to a faulted stated then attempt to reconnect.
Edit
Maybe some more context here.
InstanceContext context = new InstanceContext(this);
Subscriber = new SubscriptionService.MySubscriptionServiceClient(context);
Subscriber.Subscribe("");
So basically I want to know when the subscription service has stopped so that I can attempt to reconnect every 60 seconds or so. I tried looking for an event in the Subscriber service but I didn't see anything. Would I need to implement something on the service end?
Thanks
You can use the Faulted event available on the InnerChannel property of your generated client class. The State property of the client class is just a wrapper for InnerChannel.State, so this should work as you desire.
(For reference, you can also use the similarly named event on ChannelFactory<TChannel> if you are creating communication channels in code rather than using generated proxies.)

.Net 2.0: How to subscribe to a event publisher on a remote computer using transient subscriptions?

My problem is that I want to have a server application (on a remote computer) to publish certain events to several client computers. The server and client communicate using .Net-Remoting so currently I am using remoted .Net-Events to get the functionality. But there is one drawback: when the server (the event publisher) comes offline and is restarted, the clients lose the connection since the remote object references become invalid.
I am looking into Loosely Coupled Events and Transient COM Subscriptions to solve this issue. I put together a small demo application with one publisher and two subscribers. It works beautifully on one computer.
I am using the COMAdmin-Libraries to create a transient subscription for the event subscribers. The code looks like this:
MyEventHandler handler = new MyEventHandler();
ICOMAdminCatalog catalog;
ICatalogCollection transientCollection;
ICatalogObject subscription;
catalog = (ICOMAdminCatalog)new COMAdminCatalog();
transientCollection = (ICatalogCollection)catalog.GetCollection("TransientSubscriptions");
subscription = (ICatalogObject)transientCollection.Add();
subscription.set_Value("Name", "SubTrans");
subscription.set_Value("SubscriberInterface", handler);
string eventClassString = "{B57E128F-DB28-451b-99D3-0F81DA487EDE}";
subscription.set_Value("EventCLSID", eventClassString);
string sinkString = "{9A616A06-4F8D-4fbc-B47F-482C24A04F35}";
subscription.set_Value("InterfaceID", sinkString);
subscription.set_Value("FilterCriteria", "");
subscription.set_Value("PublisherID", "");
transientCollection.SaveChanges();
handler.Event1 += OnEvent1;
handler.Event2 += OnEvent2;
My question now is: what do I have to change in the subscription to make this work over a network? Is it even possible?
What about MSMQ? It seems perfect for what you are trying to achieve? You can use a traditional publish/subscribe model or multicast the messages.
This might be a step too far, but have you considered using WCF and the callback element of WCF?
Callback effectively turns the what was client into a server. To be honest, I don't know a great deal about callback and have only experimented. Perhaps worth a 10 minute google though.
If your server comes offline every once and a while I cannot see how you can avoid to poll it to check that it is alive.
As you are talking about COM and remote computers, I suspect you'll have to do some DCOM security configuration.

Categories

Resources