Skip to content

Commit 2bfa860

Browse files
authored
Merge pull request #50 from ibm-messaging/queuebrowser
Add support for QueueBrowser - #49
2 parents 158e5ad + 8dcf986 commit 2bfa860

File tree

7 files changed

+666
-0
lines changed

7 files changed

+666
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ your own error handling or logging.
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)
122122
* Get by JMSMessageID - [getbymsgid_test.go](getbymsgid_test.go)
123+
* Browse messages non-destructively using a QueueBrowser - [queuebrowser_test.go](queuebrowser_test.go)
123124
* Request/reply messaging pattern - [requestreply_test.go](requestreply_test.go)
124125
* Send and receive under a local transaction - [local_transaction_test.go](local_transaction_test.go)
125126
* Sending a message that expires after a period of time - [timetolive_test.go](timetolive_test.go)

jms20subset/JMSContext.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ type JMSContext interface {
4141
// name and different parameters we must use a different function name.
4242
CreateConsumerWithSelector(dest Destination, selector string) (JMSConsumer, JMSException)
4343

44+
// CreateBrowser creates a consumer for the specified Destination so that
45+
// an application can look at messages without removing them.
46+
CreateBrowser(dest Destination) (QueueBrowser, JMSException)
47+
4448
// CreateQueue creates a queue object which encapsulates a provider specific
4549
// queue name.
4650
//

jms20subset/MessageIterator.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Derived from the Eclipse Project for JMS, available at;
2+
// https://github.com/eclipse-ee4j/jms-api
3+
//
4+
// This program and the accompanying materials are made available under the
5+
// terms of the Eclipse Public License 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 jms20subset provides interfaces for messaging applications in the style of the Java Message Service (JMS) API.
11+
package jms20subset
12+
13+
// MessageIterator provides the ability for the application to consume
14+
// a sequence of Messages.
15+
type MessageIterator interface {
16+
17+
// GetNext returns the next Message that is available
18+
// or else nil if no messages are available.
19+
GetNext() (Message, JMSException)
20+
}

jms20subset/QueueBrowser.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Derived from the Eclipse Project for JMS, available at;
2+
// https://github.com/eclipse-ee4j/jms-api
3+
//
4+
// This program and the accompanying materials are made available under the
5+
// terms of the Eclipse Public License 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 jms20subset provides interfaces for messaging applications in the style of the Java Message Service (JMS) API.
11+
package jms20subset
12+
13+
// QueueBrowser provides the ability for an application to look at messages on
14+
// a queue without removing them.
15+
type QueueBrowser interface {
16+
17+
// GetEnumeration returns an iterator for browsing the current
18+
// queue messages in the order they would be received.
19+
GetEnumeration() (MessageIterator, JMSException)
20+
21+
// Closes the QueueBrowser in order to free up any resources that were
22+
// allocated by the provider.
23+
Close()
24+
}

mqjms/BrowserImpl.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) IBM Corporation 2022.
2+
//
3+
// This program and the accompanying materials are made available under the
4+
// terms of the Eclipse Public License 2.0, which is available at
5+
// http://www.eclipse.org/legal/epl-2.0.
6+
//
7+
// SPDX-License-Identifier: EPL-2.0
8+
9+
// Package mqjms provides the implementation of the JMS style Golang interfaces to communicate with IBM MQ.
10+
package mqjms
11+
12+
import (
13+
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
14+
ibmmq "github.com/ibm-messaging/mq-golang/v5/ibmmq"
15+
)
16+
17+
// BrowserImpl represents the JMS QueueBrowser object that allows applications
18+
// to peek at messages on a queue without destructively consuming them.
19+
type BrowserImpl struct {
20+
browseOption *int32
21+
ConsumerImpl // Browser is a specialized form of consumer
22+
}
23+
24+
// GetEnumeration returns an iterator for browsing the current
25+
// queue messages in the order they would be received.
26+
//
27+
// In this implementation there is exactly one Enumeration per
28+
// QueueBrowser. If an application wants to browse two independent
29+
// copies of the messages it must create two QueueBrowsers.
30+
func (browser *BrowserImpl) GetEnumeration() (jms20subset.MessageIterator, jms20subset.JMSException) {
31+
32+
// A browser is just an alternative view of a Consumer that
33+
// presents slightly different functions + behaviour.
34+
return browser, nil
35+
36+
}
37+
38+
// GetNext returns the next Message that is available
39+
// or else nil if no messages are available.
40+
func (browser *BrowserImpl) GetNext() (jms20subset.Message, jms20subset.JMSException) {
41+
42+
// Like a ReceiveNoWait, but with Browse turned on.
43+
gmo := ibmmq.NewMQGMO()
44+
gmo.Options |= *browser.browseOption
45+
46+
msg, err := browser.receiveInternal(gmo)
47+
48+
if err == nil {
49+
// After we have browsed the first message successfully we move on to asking
50+
// for the "next" message from this point onwards.
51+
brse := int32(ibmmq.MQGMO_BROWSE_NEXT)
52+
browser.browseOption = &brse
53+
}
54+
55+
return msg, err
56+
}

mqjms/ContextImpl.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,54 @@ func (ctx ContextImpl) CreateConsumerWithSelector(dest jms20subset.Destination,
113113
return consumer, retErr
114114
}
115115

116+
// CreateBrowser creates a consumer for the specified Destination so that
117+
// an application can look at messages without removing them.
118+
func (ctx ContextImpl) CreateBrowser(dest jms20subset.Destination) (jms20subset.QueueBrowser, jms20subset.JMSException) {
119+
120+
// Set up the necessary objects to open the queue
121+
mqod := ibmmq.NewMQOD()
122+
var openOptions int32
123+
openOptions = ibmmq.MQOO_FAIL_IF_QUIESCING
124+
openOptions |= ibmmq.MQOO_INPUT_AS_Q_DEF
125+
openOptions |= ibmmq.MQOO_BROWSE // This is the important part for browsing!
126+
mqod.ObjectType = ibmmq.MQOT_Q
127+
mqod.ObjectName = dest.GetDestinationName()
128+
129+
var retErr jms20subset.JMSException
130+
var browser jms20subset.QueueBrowser
131+
132+
// Invoke the MQ command to open the queue.
133+
qObject, err := ctx.qMgr.Open(mqod, openOptions)
134+
135+
if err == nil {
136+
137+
// Success - store the necessary objects away for later use to receive
138+
// messages.
139+
consumer := ConsumerImpl{
140+
ctx: ctx,
141+
qObject: qObject,
142+
}
143+
144+
brse := int32(ibmmq.MQGMO_BROWSE_FIRST)
145+
146+
browser = &BrowserImpl{
147+
browseOption: &brse,
148+
ConsumerImpl: consumer,
149+
}
150+
151+
} else {
152+
153+
// Error occurred - extract the failure details and return to the caller.
154+
rcInt := int(err.(*ibmmq.MQReturn).MQRC)
155+
errCode := strconv.Itoa(rcInt)
156+
reason := ibmmq.MQItoString("RC", rcInt)
157+
retErr = jms20subset.CreateJMSException(reason, errCode, err)
158+
159+
}
160+
161+
return browser, retErr
162+
}
163+
116164
// CreateTextMessage is a JMS standard mechanism for creating a TextMessage.
117165
func (ctx ContextImpl) CreateTextMessage() jms20subset.TextMessage {
118166

0 commit comments

Comments
 (0)