Author |
Message
|
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 7:17 am Post subject: iMessageConsumer - how does one reply to the message |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
I am missing something obvious (obviously).
I have created an application that posts messages to a queue, and I have a Windows service that uses the iMessageConsumer interface (and a call to .ReceiveNoWait) to "catch" the message. That part works great... but once I have the received the message, I can't see anything anywhere about how I send to back a reply.
The application that posted the message with a call to IBM.XMS.Requestor.Request method just sits there and twists waiting for a reply that never comes.  |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 7:21 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
Hopefully my name implied it, but I'm using the ia9h support pack in .NET for this project. |
|
Back to top |
|
 |
Vitor |
Posted: Fri Aug 21, 2009 7:25 am Post subject: Re: iMessageConsumer - how does one reply to the message |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
JeffTheDotNetGuy wrote: |
I can't see anything anywhere about how I send to back a reply. |
Send a message that's configured as a reply? Using the details from the request? _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 7:26 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
Additional details:
after I have received the message in the Windows service, if I .Acknowledge it, I watch my "Open Output Count" in the queue go up by 1, as though it's starting to reply or something.
So close... yet so far.
Shutting down my solution, all "Open Input Count"s zero out, but Open Output Counts stay. When I "Browse" the messages with the MQ Explorer, there are none. |
|
Back to top |
|
 |
Vitor |
Posted: Fri Aug 21, 2009 7:31 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
Ok, so my .NET is only slightly better than my Java, but AFAIK the .Acknowledge is not doing what you think it is. If you're trying to send a reply in the WMQ sense then it's actually a separate message. I don't think you actually want to be fiddling with the auto response.
Also is ReceiveNoWait the right choice? Why that method? _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
Vitor |
Posted: Fri Aug 21, 2009 7:33 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
JeffTheDotNetGuy wrote: |
Shutting down my solution, all "Open Input Count"s zero out, but Open Output Counts stay. When I "Browse" the messages with the MQ Explorer, there are none. |
That just means the queue isn't being closed properly, because you're using .Acknowledge incorrectly. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 7:34 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
Thanks, Vitor.
Let me try your suggestion again, but I thought I did that, and the attempt to send the return message hung on the Windows Service side... of all things, waiting for a response.
.ReceiveNoWait is the correct call, since that method simply pulls the next available message from the queue, or returns Nothing if there is nothing there.
The other methods involve setting timeouts which won't be necessary in this case. |
|
Back to top |
|
 |
Vitor |
Posted: Fri Aug 21, 2009 7:39 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
JeffTheDotNetGuy wrote: |
.ReceiveNoWait is the correct call, since that method simply pulls the next available message from the queue, or returns Nothing if there is nothing there.
The other methods involve setting timeouts which won't be necessary in this case. |
I do know that. It's just unusual to be able to be so black & white on message availability. Typically applications have some lattitude.
But it's your solution. I applaude your ability to be certain a message will be available, or not. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 7:44 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
OK... well... second time is the charm.
It might help if I posted the code.
I tried something different this time... I took the original message I received, and just changed it into a reply message, and sent it, and the client did unlock and "catch" my reply.
However, the Windows Service locks on that call waiting for a reply of it's own (even though the type is being set to Response Message). See below:
Code: |
Public Sub ProcessQueueMessages()
Try
If oFactory Is Nothing Then
oFactory = IBM.XMS.XMSFactoryFactory.GetInstance(IBM.XMS.XMSC.CT_WMQ)
End If
If oConnectionFactory Is Nothing Then
oConnectionFactory = oFactory.CreateConnectionFactory
oConnectionFactory.SetStringProperty(IBM.XMS.XMSC.WMQ_HOST_NAME, "TX-JCPC691")
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_PORT, 1414)
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_CONNECTION_MODE, 1)
oConnectionFactory.SetStringProperty(IBM.XMS.XMSC.WMQ_QUEUE_MANAGER, "TestQueueManager")
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_BROKER_VERSION, 0)
End If
If oConnection Is Nothing Then
oConnection = oConnectionFactory.CreateConnection
oConnection.Start()
End If
If oTopic Is Nothing Then
oTopic = oFactory.CreateQueue("TestQueue")
End If
Dim oSession As IBM.XMS.ISession = oConnection.CreateSession(False, IBM.XMS.AcknowledgeMode.AutoAcknowledge)
Dim oProcessor As IBM.XMS.IMessageConsumer
oProcessor = oSession.CreateConsumer(oTopic)
Dim oCurrMessage As IBM.XMS.IMessage
oCurrMessage = oProcessor.ReceiveNoWait
While Not oCurrMessage Is Nothing
Dim oReplier As New IBM.XMS.Requestor(oSession, oCurrMessage.JMSReplyTo)
With CType(oCurrMessage, IBM.XMS.ITextMessage)
.JMSType = IBM.XMS.MQC.MQMT_REPLY
.JMSDestination = oCurrMessage.JMSReplyTo
.JMSReplyTo = Nothing
.ClearBody()
.Text = "Yo back at you!"
End With
oReplier.Request(oCurrMessage)
CloseAndDispose(oReplier)
oCurrMessage = oProcessor.ReceiveNoWait
End While
CloseAndDispose(oProcessor)
oProcessor = Nothing
CloseAndDispose(oSession)
oSession = Nothing
Catch ex As Exception
Dispose(oTopic)
oTopic = Nothing
CloseAndDispose(oConnection)
oConnection = Nothing
oConnectionFactory = Nothing
oFactory = Nothing
End Try
End Sub
|
Last edited by JeffTheDotNetGuy on Fri Aug 21, 2009 11:36 am; edited 1 time in total |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 7:47 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
This function (above) is called by an exclusive timer that has a 100 millisecond interval, so if there is ever any error, all of the objects get destroyed and recreated 100 milliseconds later.
Do I have to .Acknowledge the reply? |
|
Back to top |
|
 |
Vitor |
Posted: Fri Aug 21, 2009 8:01 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
JeffTheDotNetGuy wrote: |
This function (above) is called by an exclusive timer that has a 100 millisecond interval, so if there is ever any error, all of the objects get destroyed and recreated 100 milliseconds later. |
At the risk of sounding like a cracked record, why are you using ReceiveNoWait and a timer rather than the more efficient ReceiveWait?
JeffTheDotNetGuy wrote: |
Do I have to .Acknowledge the reply? |
Not if the client has responded to the reply. Sounds like something else is going on with the service. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 8:08 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
What is the difference? Either way, don't I get a message that I need to reply to? |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 8:19 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
OK, Vitor.
I changed the function to wait indefinitely for a message. The resulting behavior was the same.
The client is catching the response, but the server hangs waiting for a response to it's response.
I wish the API exposed more than this one way of sending a message, because it's behaving exactly like the documentation says (sending a message and waiting for a response).
I'm starting to think IBM did not intend for people to use this library to create server-side queue processors.
Code: |
Public Sub ProcessQueueMessages2()
Try
If oFactory Is Nothing Then
oFactory = IBM.XMS.XMSFactoryFactory.GetInstance(IBM.XMS.XMSC.CT_WMQ)
End If
If oConnectionFactory Is Nothing Then
oConnectionFactory = oFactory.CreateConnectionFactory
oConnectionFactory.SetStringProperty(IBM.XMS.XMSC.WMQ_HOST_NAME, "TX-JCPC691")
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_PORT, 1414)
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_CONNECTION_MODE, 1)
oConnectionFactory.SetStringProperty(IBM.XMS.XMSC.WMQ_QUEUE_MANAGER, "TestQueueManager")
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_BROKER_VERSION, 0)
End If
If oConnection Is Nothing Then
oConnection = oConnectionFactory.CreateConnection
oConnection.Start()
End If
If oTopic Is Nothing Then
oTopic = oFactory.CreateQueue("TestQueue")
End If
Dim oSession As IBM.XMS.ISession = oConnection.CreateSession(False, IBM.XMS.AcknowledgeMode.AutoAcknowledge)
Dim oProcessor As IBM.XMS.IMessageConsumer
oProcessor = oSession.CreateConsumer(oTopic)
Dim oCurrMessage As IBM.XMS.IMessage
oCurrMessage = oProcessor.Receive(0)
While Not oCurrMessage Is Nothing
Dim oReplier As New IBM.XMS.Requestor(oSession, oCurrMessage.JMSReplyTo)
With CType(oCurrMessage, IBM.XMS.ITextMessage)
.ClearBody()
.JMSType = IBM.XMS.MQC.MQMT_REPLY
.JMSDestination = oCurrMessage.JMSReplyTo
.JMSReplyTo = Nothing
.Text = "Yo back at you!"
End With
oReplier.Request(oCurrMessage)
CloseAndDispose(oReplier)
oCurrMessage = oProcessor.ReceiveNoWait
End While
CloseAndDispose(oProcessor)
oProcessor = Nothing
CloseAndDispose(oSession)
oSession = Nothing
Catch ex As Exception
Dispose(oTopic)
oTopic = Nothing
CloseAndDispose(oConnection)
oConnection = Nothing
oConnectionFactory = Nothing
oFactory = Nothing
End Try
End Sub
|
[/code]
Last edited by JeffTheDotNetGuy on Fri Aug 21, 2009 11:35 am; edited 1 time in total |
|
Back to top |
|
 |
JeffTheDotNetGuy |
Posted: Fri Aug 21, 2009 11:05 am Post subject: |
|
|
Novice
Joined: 21 Aug 2009 Posts: 10
|
OK... I just wanted to come back and update this thread in case any other newb (like me) might stumble across this.
It took cracking the library open with .NET Reflector to understand what was happening.
Under the hood, what the Requester object does is actually create a temporary queue, and it is that queue that you must return the reply on. My problem in my previous examples was that I was creating my return message from the wrong queue (it needs to be that temporary queue).
I did eventually find the oSession.CreateProducer (and that's where you want to slap yourself because it's right there in the sample projects). Vitor's advance was also correct (of course) (except for the part about *how* I was getting the message): a reply to a message is actually a separate message.
So newbs, notice below that I build my producer object off of the message's.JSFReplyTo object, and all is well with the world.
Code: |
Public Sub ProcessQueueMessages()
Try
If oFactory Is Nothing Then
oFactory = IBM.XMS.XMSFactoryFactory.GetInstance(IBM.XMS.XMSC.CT_WMQ)
End If
If oConnectionFactory Is Nothing Then
oConnectionFactory = oFactory.CreateConnectionFactory
oConnectionFactory.SetStringProperty(IBM.XMS.XMSC.WMQ_HOST_NAME, "TX-JCPC691")
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_PORT, 1414)
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_CONNECTION_MODE, 1)
oConnectionFactory.SetStringProperty(IBM.XMS.XMSC.WMQ_QUEUE_MANAGER, "TestQueueManager")
oConnectionFactory.SetIntProperty(IBM.XMS.XMSC.WMQ_BROKER_VERSION, 0)
End If
If oConnection Is Nothing Then
oConnection = oConnectionFactory.CreateConnection
oConnection.Start()
End If
If oTopic Is Nothing Then
oTopic = oFactory.CreateQueue("TestQueue")
End If
Dim oSession As IBM.XMS.ISession = oConnection.CreateSession(False, IBM.XMS.AcknowledgeMode.AutoAcknowledge)
Dim oProcessor As IBM.XMS.IMessageConsumer
oProcessor = oSession.CreateConsumer(oTopic)
Dim oCurrMessage As IBM.XMS.IMessage
oCurrMessage = oProcessor.ReceiveNoWait
While Not oCurrMessage Is Nothing
With CType(oCurrMessage, IBM.XMS.ITextMessage)
.JMSType = IBM.XMS.MQC.MQMT_REPLY
.ClearBody()
.Text = "Yo! Back at you!"
End With
Dim oReplier As IBM.XMS.IMessageProducer = oSession.CreateProducer(oCurrMessage.JMSReplyTo)
oCurrMessage.JMSDestination = oCurrMessage.JMSReplyTo
oReplier.DeliveryMode = IBM.XMS.DeliveryMode.NonPersistent
Try
oReplier.Send(oCurrMessage)
Catch ex As Exception
Throw ex
Finally
CloseAndDispose(oReplier)
End Try
oCurrMessage = oProcessor.ReceiveNoWait
End While
CloseAndDispose(oProcessor)
oProcessor = Nothing
CloseAndDispose(oSession)
oSession = Nothing
Catch ex As Exception
Dispose(oTopic)
oTopic = Nothing
CloseAndDispose(oConnection)
oConnection = Nothing
oConnectionFactory = Nothing
oFactory = Nothing
End Try
End Sub
|
[/code] |
|
Back to top |
|
 |
Vitor |
Posted: Fri Aug 21, 2009 12:05 pm Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
Thank you for posting the solution for the benefit of others!
In defence, I never said receive was wrong, just unusual. If it works and performs to your satisfaction then go in peace. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
|