Skip to content

Commit 5eb5e7d

Browse files
authored
Merge pull request #47 from matrober-uk/getbymsgid
Support for get by JMSMessageID
2 parents e84ce0e + 93b0220 commit 5eb5e7d

File tree

4 files changed

+201
-13
lines changed

4 files changed

+201
-13
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ your own error handling or logging.
119119
* Send a message as Persistent or NonPersistent - [deliverymode_test.go](deliverymode_test.go)
120120
* Set a message property of type string, int, double or boolean - [messageproperties_test.go](messageproperties_test.go)
121121
* Get by CorrelationID - [getbycorrelid_test.go](getbycorrelid_test.go)
122+
* Get by JMSMessageID - [getbymsgid_test.go](getbymsgid_test.go)
122123
* Request/reply messaging pattern - [requestreply_test.go](requestreply_test.go)
123124
* Send and receive under a local transaction - [local_transaction_test.go](local_transaction_test.go)
124125
* Sending a message that expires after a period of time - [timetolive_test.go](timetolive_test.go)

getbycorrelid_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,15 @@ func TestSelectorParsing(t *testing.T) {
125125
assert.Nil(t, correlIDErr)
126126
assert.NotNil(t, correlIDConsumer)
127127

128-
// Check that we get an appropriate error when trying to create a consumer with
129-
// a selector that is not (yet) supported.
128+
// JMSMessageID selectors are now supported.
130129
msgIDConsumer, msgIDErr := context.CreateConsumerWithSelector(queue, "JMSMessageID = 'ID:1234'")
131-
assert.NotNil(t, msgIDErr)
132-
assert.Nil(t, msgIDConsumer)
130+
assert.Nil(t, msgIDErr)
131+
assert.NotNil(t, msgIDConsumer)
132+
133+
// MessageID selector that has an empty ID
134+
failMsgIDConsumer, failMsgIDErr := context.CreateConsumerWithSelector(queue, "JMSMessageID = 'ID:'")
135+
assert.NotNil(t, failMsgIDErr)
136+
assert.Nil(t, failMsgIDConsumer)
133137

134138
// Check that we get an appropriate error when trying to create a consumer with
135139
// a malformed selector.

getbymsgid_test.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright (c) IBM Corporation 2022
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*/
10+
package main
11+
12+
import (
13+
"fmt"
14+
"reflect"
15+
"testing"
16+
17+
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
18+
"github.com/ibm-messaging/mq-golang-jms20/mqjms"
19+
"github.com/stretchr/testify/assert"
20+
)
21+
22+
/*
23+
* Test receiving a specific message from a queue using its JMSMessageID
24+
*/
25+
func TestGetByMsgID(t *testing.T) {
26+
27+
// Loads CF parameters from connection_info.json and applicationApiKey.json in the Downloads directory
28+
cf, cfErr := mqjms.CreateConnectionFactoryFromDefaultJSONFiles()
29+
assert.Nil(t, cfErr)
30+
31+
// Creates a connection to the queue manager, using defer to close it automatically
32+
// at the end of the function (if it was created successfully)
33+
context, ctxErr := cf.CreateContext()
34+
assert.Nil(t, ctxErr)
35+
if context != nil {
36+
defer context.Close()
37+
}
38+
39+
// First, check the queue is empty
40+
queue := context.CreateQueue("DEV.QUEUE.1")
41+
consumer, conErr := context.CreateConsumer(queue)
42+
assert.Nil(t, conErr)
43+
if consumer != nil {
44+
defer consumer.Close()
45+
}
46+
reqMsgTest, err := consumer.ReceiveNoWait()
47+
assert.Nil(t, err)
48+
assert.Nil(t, reqMsgTest)
49+
50+
// Put a couple of messages before the one we're aiming to get back
51+
producer := context.CreateProducer().SetTimeToLive(10000)
52+
producer.SendString(queue, "One")
53+
producer.SendString(queue, "Two")
54+
55+
myMsgThreeStr := "Three"
56+
sentMsg := context.CreateTextMessageWithString(myMsgThreeStr)
57+
err = producer.Send(queue, sentMsg)
58+
assert.Nil(t, err)
59+
sentMsgID := sentMsg.GetJMSMessageID()
60+
61+
// Put a couple of messages after the one we're aiming to get back
62+
producer.SendString(queue, "Four")
63+
producer.SendString(queue, "Five")
64+
65+
// Create the consumer to read by CorrelID
66+
correlIDConsumer, correlErr := context.CreateConsumerWithSelector(queue, "JMSMessageID = '"+sentMsgID+"'")
67+
assert.Nil(t, correlErr)
68+
gotCorrelMsg, correlGetErr := correlIDConsumer.ReceiveNoWait()
69+
70+
// Clean up the remaining messages from the queue before we start checking if
71+
// we got the right one back.
72+
var cleanupMsg jms20subset.Message
73+
for ok := true; ok; ok = (cleanupMsg != nil) {
74+
cleanupMsg, err = consumer.ReceiveNoWait()
75+
}
76+
77+
// Now do the comparisons
78+
assert.Nil(t, correlGetErr)
79+
assert.NotNil(t, gotCorrelMsg)
80+
gotMsgID := gotCorrelMsg.GetJMSMessageID()
81+
assert.Equal(t, sentMsgID, gotMsgID)
82+
83+
switch msg := gotCorrelMsg.(type) {
84+
case jms20subset.TextMessage:
85+
assert.Equal(t, myMsgThreeStr, *msg.GetText())
86+
default:
87+
fmt.Println(reflect.TypeOf(gotCorrelMsg))
88+
assert.Fail(t, "Got something other than a text message")
89+
}
90+
91+
}
92+
93+
/*
94+
* Test receiving a specific message from a queue using its JMSMessageID
95+
*/
96+
func TestGetByMsgIDWithPrefix(t *testing.T) {
97+
98+
// Loads CF parameters from connection_info.json and applicationApiKey.json in the Downloads directory
99+
cf, cfErr := mqjms.CreateConnectionFactoryFromDefaultJSONFiles()
100+
assert.Nil(t, cfErr)
101+
102+
// Creates a connection to the queue manager, using defer to close it automatically
103+
// at the end of the function (if it was created successfully)
104+
context, ctxErr := cf.CreateContext()
105+
assert.Nil(t, ctxErr)
106+
if context != nil {
107+
defer context.Close()
108+
}
109+
110+
// First, check the queue is empty
111+
queue := context.CreateQueue("DEV.QUEUE.1")
112+
consumer, conErr := context.CreateConsumer(queue)
113+
assert.Nil(t, conErr)
114+
if consumer != nil {
115+
defer consumer.Close()
116+
}
117+
reqMsgTest, err := consumer.ReceiveNoWait()
118+
assert.Nil(t, err)
119+
assert.Nil(t, reqMsgTest)
120+
121+
// Put a couple of messages before the one we're aiming to get back
122+
producer := context.CreateProducer().SetTimeToLive(10000)
123+
producer.SendString(queue, "One-prefix")
124+
producer.SendString(queue, "Two-prefix")
125+
producer.SendString(queue, "Three-prefix")
126+
127+
myMsgFourStr := "Four-prefix"
128+
sentMsg := context.CreateTextMessageWithString(myMsgFourStr)
129+
err = producer.Send(queue, sentMsg)
130+
assert.Nil(t, err)
131+
sentMsgID := sentMsg.GetJMSMessageID()
132+
133+
// Put a couple of messages after the one we're aiming to get back
134+
producer.SendString(queue, "Five-prefix")
135+
136+
// Create the consumer to read by CorrelID
137+
correlIDConsumer, correlErr := context.CreateConsumerWithSelector(queue, "JMSMessageID = 'ID:"+sentMsgID+"'")
138+
assert.Nil(t, correlErr)
139+
gotCorrelMsg, correlGetErr := correlIDConsumer.ReceiveNoWait()
140+
141+
// Clean up the remaining messages from the queue before we start checking if
142+
// we got the right one back.
143+
var cleanupMsg jms20subset.Message
144+
for ok := true; ok; ok = (cleanupMsg != nil) {
145+
cleanupMsg, err = consumer.ReceiveNoWait()
146+
}
147+
148+
// Now do the comparisons
149+
assert.Nil(t, correlGetErr)
150+
assert.NotNil(t, gotCorrelMsg)
151+
gotMsgID := gotCorrelMsg.GetJMSMessageID()
152+
assert.Equal(t, sentMsgID, gotMsgID)
153+
154+
switch msg := gotCorrelMsg.(type) {
155+
case jms20subset.TextMessage:
156+
assert.Equal(t, myMsgFourStr, *msg.GetText())
157+
default:
158+
fmt.Println(reflect.TypeOf(gotCorrelMsg))
159+
assert.Fail(t, "Got something other than a text message")
160+
}
161+
162+
}

mqjms/ConsumerImpl.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -292,17 +292,23 @@ func applySelector(selector string, getmqmd *ibmmq.MQMD, gmo *ibmmq.MQGMO) error
292292
return nil
293293
}
294294

295-
// looking for something like "JMSCorrelationID = '01020304050607'"
295+
// looking for something like
296+
// "JMSCorrelationID = '01020304050607'"
297+
// "JMSMessageID = '414d5120514d31202020202020202020bec0ba61034dbe40'"
296298
clauseSplits := strings.Split(selector, "=")
297299

298300
if len(clauseSplits) != 2 {
299301
return errors.New("Unable to parse selector " + selector)
300302
}
301303

302-
if strings.TrimSpace(clauseSplits[0]) != "JMSCorrelationID" {
303-
// Currently we only support correlID selectors, so error out quickly
304+
selectorFieldName := strings.TrimSpace(clauseSplits[0])
305+
306+
if selectorFieldName != "JMSCorrelationID" &&
307+
selectorFieldName != "JMSMessageID" {
308+
309+
// Currently we only support correlID and messageID selectors, so error out quickly
304310
// if we see anything else.
305-
return errors.New("Only selectors on JMSCorrelationID are currently supported")
311+
return errors.New("Only selectors on JMSCorrelationID and JMSMessageID are currently supported")
306312
}
307313

308314
// Trim the value.
@@ -314,13 +320,28 @@ func applySelector(selector string, getmqmd *ibmmq.MQMD, gmo *ibmmq.MQGMO) error
314320

315321
// Parse out the value, and convert it to bytes
316322
stringSplits := strings.Split(value, "'")
317-
correlIDStr := stringSplits[1]
323+
selectorValue := stringSplits[1]
324+
325+
// For CorrelID and MsgID there is typically an "ID:" prefix on the
326+
// selector value that needs to be trimmed off before we convert it.
327+
if strings.HasPrefix(selectorValue, "ID:") {
328+
selectorValue = selectorValue[3:]
329+
}
330+
331+
if selectorValue != "" {
332+
333+
selectorValueBytes := convertStringToMQBytes(selectorValue)
334+
335+
switch selectorFieldName {
336+
case "JMSCorrelationID":
337+
getmqmd.CorrelId = selectorValueBytes
338+
339+
case "JMSMessageID":
340+
getmqmd.MsgId = selectorValueBytes
341+
}
318342

319-
if correlIDStr != "" {
320-
correlBytes := convertStringToMQBytes(correlIDStr)
321-
getmqmd.CorrelId = correlBytes
322343
} else {
323-
return errors.New("No value was found for CorrelationID")
344+
return errors.New("No value was found for selector string")
324345
}
325346

326347
} else {

0 commit comments

Comments
 (0)