RabbitMQ Errors AlreadyClosedException - c#

I have a .Net 6 microservice application which is receiving occasional RabbitMQ errors although there doesn't appear to be an excessive rate of messages on the queue it is trying to write to.
The error returned looks like
RabbitMQ.Client.Exceptions.AlreadyClosedException: Already closed: The
AMQP operation was interrupted: AMQP close-reason, initiated by
Library, code=541, text='Unexpected Exception', classId=0, methodId=0,
cause=System.IO.IOException: Unable to read data from the transport
connection: Connection reset by peer.\n --->
System.Net.Sockets.SocketException (104): Connection reset by peer\n
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset,
Int32 count)\n --- End of inner exception stack trace ---\n at
RabbitMQ.Client.Impl.InboundFrame.ReadFrom(NetworkBinaryReader
reader)\n at
RabbitMQ.Client.Framing.Impl.Connection.MainLoopIteration()\n at
RabbitMQ.Client.Framing.Impl.Connection.MainLoop()\n at
RabbitMQ.Client.Framing.Impl.Connection.EnsureIsOpen()\n at
RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.CreateModel()\n
at ServiceStack.RabbitMq.RabbitMqExtensions.OpenChannel(IConnection
connection) in
/home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.RabbitMq/RabbitMqExtensions.cs:line
18\n at ServiceStack.RabbitMq.RabbitMqProducer.get_Channel() in
/home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.RabbitMq/RabbitMqProducer.cs:line
47\n at ServiceStack.RabbitMq.RabbitMqProducer.Publish(String
queueName, IMessage message, String exchange) in
/home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.RabbitMq/RabbitMqProducer.cs:line
99\n at
ASM.Helios.ServiceHosting.RabbitMqServiceRequestLogger.Log(IRequest
request, Object requestDto, Object response, TimeSpan
requestDuration)\n at
ServiceStack.Host.ServiceRunner`1.LogRequest(IRequest req, Object
requestDto, Object response) in
/home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Host/ServiceRunner.cs:line
233
We have found that increasing the number of service instances does seem to help reduce the frequency of the errors, but they will still occur.
I was wondering if it is a similar issue to this stackoverflow question, in which case maybe setting the prefetch count to a lower value would help.
The code for setting up our rabbitMQ connection using the serviceStack implementation of rabbit looks like:
private static void SetUpRabbitMqConnection(IServiceDiscovery serviceDiscovery)
{
MessageService = RabbitMqServerFactory.GetRabbitMqServer(serviceDiscovery).Result;
MessageService.ConnectionFactory.SocketReadTimeout = 1000;
MessageService.ConnectionFactory.SocketWriteTimeout = 1000;
MessageService.ConnectionFactory.RequestedHeartbeat = 3;
MessageService.RetryCount = 0;
MqClient = (RabbitMqQueueClient)MessageService.MessageFactory.CreateMessageQueueClient();
ResponseQueueName = MqClient.GetTempQueueName(); //This creates a temp queue which gets auto deleted when nothing is connected to it
RabbitMqConsumer = new EventingBasicConsumer(MqClient.Channel);
MqClient.Channel.BasicConsume(queue: ResponseQueueName, consumer: RabbitMqConsumer, noLocal: true);
Console.WriteLine(" [x] Awaiting RPC requests");
RabbitMqConsumer.Received -= RabbitMqConsumerOnReceived;
RabbitMqConsumer.Received += RabbitMqConsumerOnReceived;
Disconnected = false;
}
Would adding a line like: MqClient.Channel.BasicQos(prefetchSize, prefetchCount,global); help?
What are sensible values for the 3 parameters? I think the defaults are 0, 20, and false.
Or is there a different configuration change that might help?

Related

Socket is Connected or not in dealing with EASYMODBUS in C# [duplicate]

I'm working on a client/server relationship that is meant to push data back and forth for an indeterminate amount of time.
The problem I'm attempting to overcome is on the client side, being that I cannot manage to find a way to detect a disconnect.
I've taken a couple of passes at other peoples solutions, ranging from just catching IO Exceptions, to polling the socket on all three SelectModes. I've also tried using a combination of a poll, with a check on the 'Available' field of the socket.
// Something like this
Boolean IsConnected()
{
try
{
bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead);
bool part2 = (this.Connection.Client.Available == 0);
if (part1 & part2)
{
// Never Occurs
//connection is closed
return false;
}
return true;
}
catch( IOException e )
{
// Never Occurs Either
}
}
On the server side, an attempt to write an 'empty' character ( \0 ) to the client forces an IO Exception and the server can detect that the client has disconnected ( pretty easy gig ).
On the client side, the same operation yields no exception.
// Something like this
Boolean IsConnected( )
{
try
{
this.WriteHandle.WriteLine("\0");
this.WriteHandle.Flush();
return true;
}
catch( IOException e )
{
// Never occurs
this.OnClosed("Yo socket sux");
return false;
}
}
A problem that I believe I am having in detecting a disconnect via a poll, is that I can fairly easily encounter a false on a SelectRead, if my server hasn't yet written anything back to the client since the last check... Not sure what to do here, I've chased down every option to make this detection that I can find and nothing has been 100% for me, and ultimately my goal here is to detect a server (or connection) failure, inform the client, wait to reconnect, etc. So I am sure you can imagine that this is an integral piece.
Appreciate anyone's suggestions.
Thanks ahead of time.
EDIT: Anyone viewing this question should note the answer below, and my FINAL Comments on it. I've elaborated on how I overcame this problem, but have yet to make a 'Q&A' style post.
One option is to use TCP keep alive packets. You turn them on with a call to Socket.IOControl(). Only annoying bit is that it takes a byte array as input, so you have to convert your data to an array of bytes to pass in. Here's an example using a 10000ms keep alive with a 1000ms retry:
Socket socket; //Make a good socket before calling the rest of the code.
int size = sizeof(UInt32);
UInt32 on = 1;
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds.
UInt32 retryInterval = 1000; //If no response, resend every second.
byte[] inArray = new byte[size * 3];
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size);
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size);
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size);
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null);
Keep alive packets are sent only when you aren't sending other data, so every time you send data, the 10000ms timer is reset.

System.ObjectDisposedException throwed on WebSocket communication

I'm trying to communicate between a web browser client and an ASP.NET server using WebSockets.
I make a set of requests, of different sizes and with some seconds of elapsed time between each of them. The three first ones pass correctly, but a precise one, with nothing in particular from the other, close the WebSocket connection, throw an exception on server side.
The error message and stack trace of this exception look like this :
FATAL ERROR: Cannot access a disposed object.
Object name: 'System.Web.WebSockets.AspNetWebSocket'.
at System.Web.WebSockets.AspNetWebSocket.ThrowIfDisposed()
at System.Web.WebSockets.AspNetWebSocket.SendAsyncImpl(ArraySegment 1 buffer, WebSocketMessageType messageType, Boolean endOfMessage, CancellationToken cancellationToken, Boolean performValidation)
at System.Web.WebSockets.AspNetWebSocket.SendAsync(ArraySegment 1 buffer, WebSocketMessageType messageType, Boolean endOfMessage, CancellationToken cancellationToken)
at [my code path here...]
It may be a threading problem, because I'm using async methods everywhere from functions that communicate with websockets.
I know the exception is throwed from this code (at socket.SendAsync):
public class SocketTranslater
{
private WebSocket socket;
private JavaScriptSerializer serializer;
// [...]
private ArraySegment<byte> Encode(Object data)
{
string json = serializer.Serialize(data);
return (new ArraySegment<byte>(Encoding.UTF8.GetBytes(json)));
}
public async Task Send(Object packet)
{
ArraySegment<byte> encoded = this.Encode(packet);
await socket.SendAsync(encoded, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
The socket is created from another class :
public class EventSender : IHttpHandler
{
private static List<SocketTranslater> socketTranslaters = new List<SocketTranslater>();
public void ProcessRequest(HttpContext context)
{
this.id = context.Request.UserHostName + ":" + context.Request.UserAgent;
if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(ProcessSocket);
}
}
private async Task ManageSocket(AspNetWebSocketContext context)
{
WebSocket socket = context.WebSocket;
SocketTranslater translater = new SocketTranslater(socket);
translaters.add(translater);
while (true)
{
// Manage messages, using the other class to send responses.
translater.Send(/* Any struct here */);
}
}
Unhopefully, my project is too big to put all the code here.
Any idea of error source, or additional information that you would require ?
UPDATE:
After some more tests, I don't have this exception from time to time. I always do the same thing, but the server seems to have a random comportment.
That makes my problem even weirder...
Finally, after some more tests and interesting questions and answer from here (like this one), I understood:
My problem was that I was stocking WebSockets in a Dictionary linked with hostnames. So on the first connection of a client on my server, everything worked correctly. But if I refresh the page, the websocket was closed by the server (because there was no chance to use it again) et another one was created.
But as I used the same key for both sockets, the deprecated and the new one, I was trying to answer to the new client with the previous socket, that was closed. (disposed = closed for ASP.NET).
So the only thing that I had to do is to remove a socket from the list on the client disconnection (at the end of ManageSocket). And forbid a client to connect twice with the same hostname.
I didn't mention the part where I was linking sockets with hostnames, so I admit you couldn't really help me... I apologize.

WCF Streaming File Upload 300MB +

I'm having a little trouble with WCF streaming a file. I am able to stream files to the server that are less than 300 MB, but when I try a file 300 MB or more, I get an error around 60% in saying "An established connection was aborted by the software in your host machine". This error sounds like I'm closing the connection before the file is finished, but I can't find it.
The client code I have opens the connection, calls the Upload Method, waits for the return, then closes the connection. This works fine for small files.
The WCF server is hosted in a Windows Service, using the net.tcp binding. I've tried changing the buffer sizes etc, but still no luck.
I'm looking for some assistance in tracking down this issue.
Server Side Binding:
NetTcpBinding tcp = new NetTcpBinding(SecurityMode.None);
tcp.SendTimeout = TimeSpan.FromMinutes(10);
tcp.ReceiveTimeout = TimeSpan.FromMinutes(10);
tcp.MaxBufferSize = 65536; // 16384;
tcp.MaxBufferPoolSize = 204003200; // 655360;
tcp.MaxReceivedMessageSize = 204003200; // 2147483647;
tcp.TransferMode = TransferMode.Streamed;
tcp.ReaderQuotas = new XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647
};
Client Side Binding:
NetTcpBinding tcp = new NetTcpBinding(SecurityMode.None);
tcp.SendTimeout = TimeSpan.FromMinutes(10);
tcp.ReceiveTimeout = TimeSpan.FromMinutes(10);
tcp.MaxBufferSize = 65536; // 16384;
tcp.MaxBufferPoolSize = 204003200; // 655360;
tcp.MaxReceivedMessageSize = 204003200; // 2147483647;
tcp.TransferMode = TransferMode.Streamed;
tcp.ReaderQuotas = new XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647
};
Class I use for the File Stream:
[MessageContract]
public class DataFileStream
{
[MessageHeader(MustUnderstand = true)]
public String ID { get; set; }
[MessageHeader(MustUnderstand = true)]
public String FileName { get; set; }
[MessageHeader(MustUnderstand = true)]
public long FileSize { get; set; }
[MessageBodyMember(Order = 1)]
public Stream StreamData { get; set; }
}
And the errors I receive:
Exception: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:48:35.9230000'
Inner Exception: The write operation failed, see inner exception.
Inner Exception: The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:48:35.9230000'.
Inner Exception: An established connection was aborted by the software in your host machine
Thanks for the help in advance.
I think it's because you have your MaxReceivedMessageSize (and possibly MaxBufferPoolSize) set to about 194 megabytes. Try doubling it to 408006400 (about 400mb).
Change it to this:
tcp.MaxBufferPoolSize = 408006400;
tcp.MaxReceivedMessageSize = 408006400;
Reading the MSDN, I don't think the MaxBufferPoolSize will be the issue (but worthwhile increasing it just to make sure). If this works, reset it to your 200mb limit and test again.
The reason for this happening is once the server has reached 204003200 bytes (194mb) transferred, the server aborts the transfer because you indicated that's the maximum expected size. This is by design to prevent malicious use where somebody uploads an extremely large file to clog the server or to prevent excessive use by users.

No matter what I try: The I/O operation has been aborted because of either a thread exit or an application request

I try to build a simple async net tcp wcf tool which will open connection, send command, receive answer (a List with 0-10 string sentences), close connection.
The problem is, I get on (self-hosted) service side always - no matter what I try - "The I/O operation has been aborted because of either a thread exit or an application request", on client side of course the corresponding errors like "Existing connection was closed by remote host" and timeouts and so on.
I tried alot for the past days but I can't get rid of it.
Client Side (running on .NET 4.0, called around once a sec):
void callservice(string mykey) {
ServiceReference1.Client c = new ServiceReference1.Client();
c.GetDataCompleted += c_GetDataCompleted;
try {
c.GetDataAsync(mykey);
}
catch (FaultException aa)
{
c.Abort();
}
}
private void c_GetDataCompleted(object sender, ServiceReference1.GetDataCompletedEventArgs e)
{
ServiceReference1.Client c = (ServiceReference1.Client)sender;
c.GetDataCompleted -= c_GetDataCompleted;
try
{
if (e.Result != null && e.Result.Length > 0)
{
... }
c.Close();
}
catch (Exception) {
c.Abort();
}
}
Server Side (running on .NET4.5):
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple,
InstanceContextMode=InstanceContextMode.PerCall,IncludeExceptionDetailInFaults=true)]
public class Service1 : IMyService
{
public async Task<List<string>> GetData(string whatkey)
{
List<string> mydatalist = new List<string>();
mydatalist= await Task.Run<List<string>>(() =>
{
...
});
return mydatalist;
}
What is going wrong there? Could it be that it is something not having to do with WCF at all? What could it be?
Server Side Exception:
System.Net.Sockets.SocketException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
The I/O operation has been aborted because of either a thread exit or an application request
at System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted()
at System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs)
at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncFailure(SocketError socketError, Int32 bytesTransferred, SocketFlags flags)
at System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
System.Net.Sockets.SocketException (0x80004005): The I/O operation has been aborted because of either a thread exit or an application request
3E3
One more interesting fact:
SVCLogs show me that the I/O Exeption occurs after a timespan I can define in the
<connectionPoolSettings groupName="default" leaseTimeout="00:03:00"
idleTimeout="00:02:39" maxOutboundConnectionsPerEndpoint="20" />
settings.
In this example it will occur the first time after 00:02:39.
My interpretation: It closes open connections due to the settings there and that causes the Exception since the ReceiveAsync operation i.ex. was still open.
My question is so far why does client.close() not close it completely and why isn't it finished yet when it is calling the c_getdatacompleted-event? Why does the operation "hang out" for 02:39 minutes and does not come to an end?
(If I would not force the close down via the connectionpool settings I end up with hundreds of open operations if I use netstat i.ex. to display)
Async WCF operations (AsyncPattern=true) are implemented with the Asynchronous Programming Model. That is, you implement an operation ("Operation") with two asynchronous operations ("BeginOperation" and "EndOeration"). The client can wrap those operations with a Task (presumably with the FromAsync overload)
For example:
[ServiceContract]
public interface ISampleTaskAsync
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginDoWork(int count, AsyncCallback callback, object state);
int EndDoWork(IAsyncResult result);
}
The WCF contract does not return a Task<T>
Then, on the client you could do something like:
var proxy = new Services.SampleTaskAsyncClient();
object state = "This can be whatever you want it to be";
var task = Task<int>.Factory.FromAsync(proxy.BeginDoWork,
proxy.EndDoWork, 10, state);
For more information see:
http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.asyncpattern.aspx
http://blogs.msdn.com/b/rjacobs/archive/2011/06/30/how-to-implement-a-wcf-asynchronous-service-operation-with-task-lt-t-gt.aspx
If you want to use Task<T>, I believe you don't need AsyncPattern=true.

XMS.Net 2.1.0.0/1 CWSMQ0282E

We're using XMS.Net to connect to a WebSphere MQ server V7; this has always worked fine with a V6 server but since the "other party" has upgraded to V7 we expierienced some trouble. Most of it has been fixed but now I've stumbled upon an error that I can't explain, nor find anything about:
CWSMQ0282E: A null value has been used for argument BUFFER = <> NULL within method ImportMQMDMesageBuffer(WmqSession, WmqDestination, MQMD,byte[],int,int).
The preceding method detected an invalid null argument.
If necessary, recode the application to avoid the error condition.
Stacktrace: at IBM.XMS.Client.WMQ.WmqReceiveMarshal.ImportMQMDMesageBuffer(MQMessageDescriptor mqmd, Byte[] buffer, Int32 dataStart, Int32 dataEnd)
at IBM.XMS.Client.WMQ.WmqAsyncConsumerShadow.Consumer(Phconn hconn, MQMessageDescriptor mqmd, MQGetMessageOptions mqgmo, Byte[] pBuffer, MQCBC mqcbc)
at IBM.WMQ.Nmqi.UnmanagedNmqiMQ.NmqiConsumerMethodUM(Int32 hconn, IntPtr structMqmd, IntPtr structMqgmo, IntPtr buffer, IntPtr structMqcbc)
The only thing I think I know about the cause of this error is that we sent a message and I'm expecting the CoA and CoD messages; I'm expecting these to be in the queue and when I shut down my consumer listening for these messages the rest works fine.
I have absolutely no idea what is going on...
EDIT
This is the minimum testcase:
using System;
using System.Configuration;
using System.Text;
using IBM.XMS;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
//Setup unhandled exception "logging"
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
//Change this to your own needs!
string QueueManager = "CONTOSO";
string Channel = "MYCOMPANY.CONTOSO.TCP";
string Queue = "MYCOMPANY.REPORTQ";
string HostIP = "192.168.1.29"
int Port = 1416;
//Create connection
var factoryfactory = XMSFactoryFactory.GetInstance(XMSC.CT_WMQ);
var connectionfactory = factoryfactory.CreateConnectionFactory();
connectionfactory.SetStringProperty(XMSC.WMQ_QUEUE_MANAGER, QueueManager);
connectionfactory.SetStringProperty(XMSC.WMQ_HOST_NAME, HostIP);
connectionfactory.SetIntProperty(XMSC.WMQ_PORT, Port);
connectionfactory.SetStringProperty(XMSC.WMQ_CHANNEL, Channel);
connectionfactory.SetIntProperty(XMSC.WMQ_BROKER_VERSION, XMSC.WMQ_BROKER_V2);
connectionfactory.SetIntProperty(XMSC.WMQ_CONNECTION_MODE, XMSC.WMQ_CM_CLIENT_UNMANAGED);
var connection = connectionfactory.CreateConnection();
connection.ExceptionListener = new ExceptionListener(OnXMSExceptionReceived);
//Create session
var session = connection.CreateSession(false, AcknowledgeMode.ClientAcknowledge);
//Create consumer
var queue = session.CreateQueue(string.Format("queue://{0}/{1}", QueueManager, Queue));
queue.SetIntProperty(XMSC.WMQ_TARGET_CLIENT, XMSC.WMQ_TARGET_DEST_MQ); //Prevent automatic RFH (or JMS) headers in messages...
var consumer = session.CreateConsumer(queue);
consumer.MessageListener = new MessageListener(OnMessageReceived); //Messages received will be handled by OnMessageReceived
//Start the connection (which starts the consumer to listen etc.)
Console.WriteLine("Starting");
connection.Start();
Console.WriteLine("Started; press any key to stop");
//Now we wait...
Console.ReadKey();
//Tear down the connection
Console.WriteLine("Stopping");
connection.Stop();
Console.WriteLine("Stopped; press any key to end application");
//Keep the console around
Console.ReadKey();
}
private static void OnMessageReceived(IMessage message)
{
Console.WriteLine("Message received");
if (message is IBytesMessage)
{
var bytesmsg = (IBytesMessage)message;
var data = new byte[bytesmsg.BodyLength];
Console.WriteLine(Encoding.UTF8.GetString(data));
}
else
{
//The message is not an IBytesMessage, check to see if it is a Feedback-type message
if (message.PropertyExists(XMSC.JMS_IBM_FEEDBACK))
{
//Figure out which type of feedback message this is
int feedback = message.GetIntProperty(XMSC.JMS_IBM_FEEDBACK);
switch (feedback)
{
case MQC.MQFB_COA:
Console.WriteLine("COA received");
break;
case MQC.MQFB_COD:
Console.WriteLine("COD received");
break;
default:
//Unknown feedback type
Console.WriteLine("Unknown feedback");
break;
}
}
else
{
//The message is not a feedback message; we don't know what this is so it's unexpected.
Console.WriteLine("Unexpected message received");
}
}
Console.WriteLine("Acknowledging");
message.Acknowledge();
Console.WriteLine("Acknowledged");
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
//Uh oh
Console.WriteLine("*** UnhandledException ***");
Console.WriteLine((e.ExceptionObject as Exception).Message);
Console.WriteLine("******************************");
}
private static void OnXMSExceptionReceived(Exception ex)
{
//Uh oh
Console.WriteLine("*** OnXMSExceptionReceived ***");
Console.WriteLine(ex.Message);
Console.WriteLine("******************************");
}
}
}
Create a new (console)project, add a reference to IBM.XMS.dll (C:\Program Files (x86)\IBM\WebSphere MQ\Tools\Lib\IBM.XMS.dll) and run the project. Put any message in the report queue and see what happens.
When connected to a V6 server everything is fine, V7 results in the exception being thrown.
Also we tried updating to 2.1.0.1 but to no avail...
EDIT
Here's what I'm seeing:
This is my trace log (Sorry, can't add it here since my message will be >30000 chars long) and here is an even more detailed log (traceSpecification "all" instead of "debug").
I also tried switching the (test)application to .Net V2.0.50727.5456 but that doesn't help either.
EDIT
I seem to have narrowed it down to "empty" CoA's and CoD's; when messages are sent with the MQRO_COA_WITH_DATA or MQRO_COA_WITH_FULL_DATA (same for CoD) as opposed to MQRO_COA then the CWSMQ0282E error doesn't occur. So XMS.Net seems to crash on empty bodies for CoA's and CoD's. I need to confirm some things to ensure it's not caused by other stuff in my project interfering but I'm quite sure this is the cause.
The exception appears to be because the received message does not have message body. If the message received is because of either MQRO_COD or MQRC_COA option (set when the original message was sent) would not have any message body. When XMS tries to process messages without any body, it's getting into trouble.
I am puzzled as to how this was working when using MQ v6. You may want to check if the application that's sending the original message has been changed off late.
Also for XMS to process any message, the incoming message must contain required JMS headers. MQRO_COD/MQRO_COA are automatically generated by the queue manager and will not contain JMS headers.
Few other suggestions on the code snippet above:
1) An instance of IPEndpoint is not really required. You can simply set hostname or IP address as a string and port number as integer.
2) XMSC.RTT_BROKER_PING_INTERVAL need not be set when connecting WMQ.
3) Since you have usedAcknowledgeMode.AutoAcknowledgewhile creating a session, no need to call message.Acknowledge() in OnMessageReceivedmethod.
As far as I can determine this exception, indeed, occurs on "empty" CoA's en CoD's. When messages are sent with the MQRO_COA_WITH_DATA / MQRO_COD_WITH_DATA (or even bulkier MQRO_COA_WITH_FULL_DATA / MQRO_COD_WITH_FULL_DATA) the exception doesn't occur. We will file a "PMR" with IBM to confirm.

Categories