Skip to content

Commit

Permalink
Merge pull request #50 from ibm-messaging/queuebrowser
Browse files Browse the repository at this point in the history
Add support for QueueBrowser - #49
  • Loading branch information
matrober-uk authored Feb 12, 2022
2 parents 158e5ad + 8dcf986 commit 2bfa860
Show file tree
Hide file tree
Showing 7 changed files with 666 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ your own error handling or logging.
* Set a message property of type string, int, double or boolean - [messageproperties_test.go](messageproperties_test.go)
* Get by CorrelationID - [getbycorrelid_test.go](getbycorrelid_test.go)
* Get by JMSMessageID - [getbymsgid_test.go](getbymsgid_test.go)
* Browse messages non-destructively using a QueueBrowser - [queuebrowser_test.go](queuebrowser_test.go)
* Request/reply messaging pattern - [requestreply_test.go](requestreply_test.go)
* Send and receive under a local transaction - [local_transaction_test.go](local_transaction_test.go)
* Sending a message that expires after a period of time - [timetolive_test.go](timetolive_test.go)
Expand Down
4 changes: 4 additions & 0 deletions jms20subset/JMSContext.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type JMSContext interface {
// name and different parameters we must use a different function name.
CreateConsumerWithSelector(dest Destination, selector string) (JMSConsumer, JMSException)

// CreateBrowser creates a consumer for the specified Destination so that
// an application can look at messages without removing them.
CreateBrowser(dest Destination) (QueueBrowser, JMSException)

// CreateQueue creates a queue object which encapsulates a provider specific
// queue name.
//
Expand Down
20 changes: 20 additions & 0 deletions jms20subset/MessageIterator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Derived from the Eclipse Project for JMS, available at;
// https://github.com/eclipse-ee4j/jms-api
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0, which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

// Package jms20subset provides interfaces for messaging applications in the style of the Java Message Service (JMS) API.
package jms20subset

// MessageIterator provides the ability for the application to consume
// a sequence of Messages.
type MessageIterator interface {

// GetNext returns the next Message that is available
// or else nil if no messages are available.
GetNext() (Message, JMSException)
}
24 changes: 24 additions & 0 deletions jms20subset/QueueBrowser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Derived from the Eclipse Project for JMS, available at;
// https://github.com/eclipse-ee4j/jms-api
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0, which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

// Package jms20subset provides interfaces for messaging applications in the style of the Java Message Service (JMS) API.
package jms20subset

// QueueBrowser provides the ability for an application to look at messages on
// a queue without removing them.
type QueueBrowser interface {

// GetEnumeration returns an iterator for browsing the current
// queue messages in the order they would be received.
GetEnumeration() (MessageIterator, JMSException)

// Closes the QueueBrowser in order to free up any resources that were
// allocated by the provider.
Close()
}
56 changes: 56 additions & 0 deletions mqjms/BrowserImpl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) IBM Corporation 2022.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0, which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

// Package mqjms provides the implementation of the JMS style Golang interfaces to communicate with IBM MQ.
package mqjms

import (
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
ibmmq "github.com/ibm-messaging/mq-golang/v5/ibmmq"
)

// BrowserImpl represents the JMS QueueBrowser object that allows applications
// to peek at messages on a queue without destructively consuming them.
type BrowserImpl struct {
browseOption *int32
ConsumerImpl // Browser is a specialized form of consumer
}

// GetEnumeration returns an iterator for browsing the current
// queue messages in the order they would be received.
//
// In this implementation there is exactly one Enumeration per
// QueueBrowser. If an application wants to browse two independent
// copies of the messages it must create two QueueBrowsers.
func (browser *BrowserImpl) GetEnumeration() (jms20subset.MessageIterator, jms20subset.JMSException) {

// A browser is just an alternative view of a Consumer that
// presents slightly different functions + behaviour.
return browser, nil

}

// GetNext returns the next Message that is available
// or else nil if no messages are available.
func (browser *BrowserImpl) GetNext() (jms20subset.Message, jms20subset.JMSException) {

// Like a ReceiveNoWait, but with Browse turned on.
gmo := ibmmq.NewMQGMO()
gmo.Options |= *browser.browseOption

msg, err := browser.receiveInternal(gmo)

if err == nil {
// After we have browsed the first message successfully we move on to asking
// for the "next" message from this point onwards.
brse := int32(ibmmq.MQGMO_BROWSE_NEXT)
browser.browseOption = &brse
}

return msg, err
}
48 changes: 48 additions & 0 deletions mqjms/ContextImpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,54 @@ func (ctx ContextImpl) CreateConsumerWithSelector(dest jms20subset.Destination,
return consumer, retErr
}

// CreateBrowser creates a consumer for the specified Destination so that
// an application can look at messages without removing them.
func (ctx ContextImpl) CreateBrowser(dest jms20subset.Destination) (jms20subset.QueueBrowser, jms20subset.JMSException) {

// Set up the necessary objects to open the queue
mqod := ibmmq.NewMQOD()
var openOptions int32
openOptions = ibmmq.MQOO_FAIL_IF_QUIESCING
openOptions |= ibmmq.MQOO_INPUT_AS_Q_DEF
openOptions |= ibmmq.MQOO_BROWSE // This is the important part for browsing!
mqod.ObjectType = ibmmq.MQOT_Q
mqod.ObjectName = dest.GetDestinationName()

var retErr jms20subset.JMSException
var browser jms20subset.QueueBrowser

// Invoke the MQ command to open the queue.
qObject, err := ctx.qMgr.Open(mqod, openOptions)

if err == nil {

// Success - store the necessary objects away for later use to receive
// messages.
consumer := ConsumerImpl{
ctx: ctx,
qObject: qObject,
}

brse := int32(ibmmq.MQGMO_BROWSE_FIRST)

browser = &BrowserImpl{
browseOption: &brse,
ConsumerImpl: consumer,
}

} else {

// Error occurred - extract the failure details and return to the caller.
rcInt := int(err.(*ibmmq.MQReturn).MQRC)
errCode := strconv.Itoa(rcInt)
reason := ibmmq.MQItoString("RC", rcInt)
retErr = jms20subset.CreateJMSException(reason, errCode, err)

}

return browser, retErr
}

// CreateTextMessage is a JMS standard mechanism for creating a TextMessage.
func (ctx ContextImpl) CreateTextMessage() jms20subset.TextMessage {

Expand Down
Loading

0 comments on commit 2bfa860

Please sign in to comment.