I have a XMS MQ Client app that is pulling off messages from a series of MQ endpoints. There are certain reason codes for which the process can continue, and for some that it should abort. For example a MQRC_Q_MGR_NOT_AVAILABLE 2059 for one endpoint shouldn't abort the whole process. Consequently I would like to check for this reason code.
cf = factoryFactory.CreateConnectionFactory();
foreach (Endpoint e in env.GetEndpoints())
{
Console.WriteLine("Consuming messages from endpoint {0}({1})", e.host, e.port);
// Set the properties
SetConnectionProperties(cf, e);
try
{
ReceiveMessagesFromEndpoint(cf);
}
catch (XMSException ex)
{
Console.WriteLine("XMSException caught: {0}", ex);
Console.WriteLine("Error Code: {0}", ex.ErrorCode);
Console.WriteLine("Error Message: {0}", ex.Message);
}
}
Problem is that the only attributes available on the XMSException to examine are ex.ErrorCode and ex.Message, which are respectively:
Error Code: CWSMQ0006
and
Error Message: CWSMQ0006E: An exception was received during the call to the method ConnectionFactory.CreateConnection: CompCode: 2, Reason: 2059.
I can see the Reason in the Message, but can't find a method or attribute to retrieve it.
There are probably 2 ways to do it
1) You can use the LinkedException
Something like the following
try
{
}
catch (XMSException e)
{
if(e.LinkedException!=null)
Console.WriteLine(e.LinkedException.Message);
else
Console.WriteLine(e);
}
2) Reference amqmdnet.dll as well to the project and use MQException.Something like
try
{
}
catch (XMSException e)
{
if(e.LinkedException!=null)
{
IBM.WMQ.MQException inner = (IBM.WMQ.MQException)e.LinkedException;
Console.WriteLine("Reason:"+ inner.ReasonCode);
}
else
Console.WriteLine(e);
}
Solution by OP
Based on accepted answer, a 'working' code is:
cf = factoryFactory.CreateConnectionFactory();
foreach (Endpoint e in env.GetEndpoints())
{
Console.WriteLine("Consuming messages from endpoint {0}({1})", e.host, e.port);
// Set the properties
SetConnectionProperties(cf, e);
try
{
ReceiveMessagesFromEndpoint(cf);
}
catch (XMSException ex)
{
Console.WriteLine("XMSException caught: {0}", ex);
Console.WriteLine("Error Code: {0}", ex.ErrorCode);
Console.WriteLine("Error Message: {0}", ex.Message);
if (ex.LinkedException != null &&
IBM.XMS.MQC.MQRC_Q_MGR_NOT_AVAILABLE.ToString().Equals(ex.LinkedException.Message))
{
Console.WriteLine("Queue Manager on this endpoint is not available");
Console.WriteLine("Moving onto next endpoint");
continue;
}
Console.WriteLine("Unexpected Error - Aborting");
throw;
}
}
Related
In SignalR v2, I used code like this (below) to handle exceptions that happened when my connections failed. What is the equivalent in SignalR v3? Does SendAsync or SendAsyncCore throw some exception should connections fail or serialization fail?
private async void ManagerOnUserRemoved(UserDto userDto)
{
try
{
await Context.Clients.All.MyFunc(userDto);
}
catch (InvalidOperationException) { }
catch (AggregateException) { }
}
I didn't see any exceptions listed here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.client.hubconnectionextensions.sendasync?view=aspnetcore-3.0
Update: I have the same question for the calls from the client-side (to InvokeCoreAsync et al).
In SignalR V3 use HubException to capture exceptions that contain sensitive information, such as connection information.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.hubexception?view=aspnetcore-3.1
private async void ManagerOnUserRemoved(UserDto userDto)
{
try
{
await Context.Clients.All.MyFunc(userDto);
}
catch(Exception ex) {
//Now check exceptions what you want by exception message or exception code
}
}
With this code you can handle all exceptions, or you can do this:
hubConnection.Error += ex => Console.WriteLine("Error: {0}", ex.Message);
I think it will be help
I am trying to simply get a list of all the Private Queues on the Server from my PC.
The error I am getting is "Access to Message Queuing system is denied."
I have given full access to (Everyone, NETWORK SERVICE and Anonymous Logon) the queue on the as there is only 1 queue....
Please see attached error and code below:-
try
{
MessageQueue[] queueList =
MessageQueue.GetPrivateQueuesByMachine("xxx.xxx.x.xxx");//Error
occurs here
foreach (MessageQueue queueItem in queueList)
{
Console.WriteLine(queueItem.Path);
}
return created;
}
catch (MessageQueueException m)
{
Console.WriteLine(m.Message + m.MessageQueueErrorCode);
}
catch (SystemException s)
{
Console.WriteLine(s.Message + s.StackTrace);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
On the computer manager of the target machine ("xxx.xxx.x.xxx" in your example) select "Services and applications" and then "Message Queuing". Right click on "Message Queuing", go to secuirty tab and add your account with full control. Thsi should give you access to the private queues on that machine
I'm currently working with some code that is used in client server communication.
I has a lot (around 50) of the following try-catch blocks
try
{
return GetLogFiles(date);
}
catch (TimeoutException ex)
{
this.GetLogger("GetAllLogs").Error("C is not answering!", ex);
}
catch (ConnectionInterruptedException ex)
{
this.GetLogger("GetAllLogs").Error("Connection interrupted", ex);
}
catch (ActionNotSupportedException ex)
{
this.GetLogger().Error("Software-version not comaptible!", ex);
throw new VersionNotCompatibleException();
}
catch (EndpointNotFoundException ex)
{
this.GetLogger().Error("Problem with network, connection to core is lost!", ex);
}
catch (CommunicationException ex)
{
this.GetLogger().Error("Not expected communication-exception was thrown:", ex);
}
This makes for a LOT of code that is more or less always the same.
Now I thought about refactoring all the catch blocks into a method and just call it. Like
try
{
return GetLogFiles(date);
}
catch(Exception ex)
{
ExceptionHandling(string operation, Exception ex)
}
private void ExceptionHandling(string operation, Exception ex)
{
if (ex is TimeoutException)
{
this.GetLogger(operation).Error("C is not answering!", ex);
}
else if (ex is ConnectionInterruptedException)
{
this.GetLogger(operation).Error("Connection interrupted", ex);
}
else if (ex is CommunicationObjectFaultedException)
{
this.GetLogger(operation).Error("Core is not answering!", ex);
}
else if (ex is FaultException)
{
this.GetLogger(operation).Error("C is not answering!", ex);
}
else if (ex is ActionNotSupportedException)
{
this.GetLogger().Error("Software-version not comaptible!", ex);
throw new VersionNotCompatibleException();
}
else if (ex is EndpointNotFoundException)
{
this.GetLogger().Error("Problem with network, connection is lost!", ex);
}
else if (ex is CommunicationException)
{
this.GetLogger().Error("Not expected communication-exception was thrown:", ex);
}
else
{
this.GetLogger().Error("Unknown exception was thrown:", ex);
throw new Exception("Unknown exception occured during request handling", ex);
}
}
None of the codeparts does any ordinary handling in case of an exception, i.e. they get logged and that's it.
What problems do you see with extracting the exception part into its own method?
The main problem I see is that you're rethrowing the exception if it isn't one you expect, making you lose the real stack trace, plus using Exception in your catch is a very broad thing to do.
Lines of code isn't the real issue, and yes making things DRY is a good thing to do but its more likely that the thing that needs making dry is the GetLogFiles function to include the error handling inside of that, not the exception handler.
it's better to do that like this:
public class MyException : Exception
{
public MyException(Exception ex)
{
// handle exception
}
}
and
try
{
}
catch(Exception ex)
{
throw new MyException(ex)
}
In the following code I have a nested Try Catch. In the case where my nested catch fails I want to just to the parent catch statement and execute that code. How can i do this?
try
{
try
{ // build and send invoice lines
ReadInvLinesToArray(row["ID_INVOICE"].ToString());
}
catch (Exception e)
{
writeToEventLog(e.ToString(), true, false);
SendErrorEmail("Failed to send Invoice Lines to NAV. The following system error was generated: \n" + e.ToString());
}
// send invoice header if lines have been sent
bool result = navInvoices.SendInvoicesToNAV(navImportInvoices);
// update the retrieved records, marking QB Status as value N, passing in the sql dataset as a list
UpdateQBStatusInvoiceSent(ref idInvoicesSent);
}
catch (Exception e)
{
// remove Invoice from list to ensure its status is not updated.
idInvoicesSent.Remove(Convert.ToInt32(row["ID_INVOICE"]));
WriteToEventLog(e.ToString(), true, false);
SendErrorEmail("Failed to send Invoices to NAV. The following system error was generated: \n" + e.ToString());
}
You CAUGHT the exception with that "inner" catch, so the exception has been deal with it. If you want the "outer" catch to trigger as well, you'd have to RE-THROW the exception:
try {
try {
...
} catch (Exception e) {
... do stuff
throw e; // you need this
}
} catch (Exception e) {
... catch the re-thrown "e"
}
I have a windows service that is attempting to consume messages from some activemq queue's. However, it is only getting some of the messages and others are getting stuck in 'messages pending' in the queue. ActiveMQ tells me it has enqueued lets say 500 messages to the consumer but only 300 were dequeued. There is more than one listener being set up in the service. Here's the important part of the code:
private void setupListener(string queue, string brokerUri)
{
try
{
ISession session = connectionConsumers[brokerUri].CreateSession();
session.CreateConsumer(session.GetQueue(queue))
.Listener += new MessageListener(consumer_Listener);
}
catch (Exception ex)
{
Log.Error("An exception has occured setting up listener for " + queue + " on " + brokerUri + ": {0}, {1}", ex, ex.Message);
}
}
void consumer_Listener(IMessage message)
{
try
{
processLog((message as ITextMessage).Text);
message.Acknowledge();
}
catch (NMSException ex)
{
Log.Error("ActiveMQ Connection Failure: {0}, {1}", ex, ex.Message);
}
catch (Exception ex)
{
Log.Error("An exception has occured trying to process a message: {0}, {1}", ex, ex.Message);
}
}
Is there something wrong with the way I'm acknowledging messages that would cause certain ones to not be acknowledged? Is it a concurrency issue? I'm not sure if they are all still going through the processLog function (added to my database).
EDIT: I think it has more to do with acknowledgements not happening properly (for some reason). I am not getting exceptions thrown in my logs. However, activemq shows the following:
From what I've read, the dispatch queue is being filled with messages that were sent to the consumer but not acknowledged. Why could this be?
The problem had to do with our queues being virtual destinations.