Skip to content

Commit 9622e59

Browse files
authored
Merge pull request #1 from ibm-messaging/local-bindings
Support for local bindings connections
2 parents 0ceea57 + d2e9d67 commit 9622e59

14 files changed

+160
-40
lines changed

Gopkg.lock

Lines changed: 14 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727

2828
[[constraint]]
2929
name = "github.com/ibm-messaging/mq-golang"
30-
version = "3.3.4"
30+
version = "4.1.0"
3131

3232
[[constraint]]
3333
name = "github.com/stretchr/testify"
34-
version = "1.3.0"
34+
version = "1.4.0"
3535

3636
[prune]
3737
go-tests = true

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ assert.Equal(t, "MQRC_NOT_AUTHORIZED", err.GetReason())
110110
Other sample code can be found in the testcase files as follows. When writing your own applications you will
111111
generally replace the various "assert" calls that test the successful execution of the application logic with
112112
your own error handling or logging.
113-
* Creating a ConnectionFactory - [connectionfactory_test.go](connectionfactory_test.go)
113+
* Creating a ConnectionFactory that uses a client connection to a remote queue manager - [connectionfactory_test.go](connectionfactory_test.go)
114+
* Creating a ConnectionFactory that uses a bindings connection to a local queue manager - [local_bindings_test.go](local_bindings_test.go)
114115
* Send/receive a text string - [sample_sendreceive_test.go](sample_sendreceive_test.go)
115116
* Send a message as Persistent or NonPersistent - [deliverymode_test.go](deliverymode_test.go)
116117
* Get by CorrelationID - [getbycorrelid_test.go](getbycorrelid_test.go)
@@ -130,7 +131,7 @@ go test -run TestSampleSendReceiveWithErrorHandling
130131
The IBM MQ client on which this library depends is supported on Linux and Windows, and is [now available for development use on MacOS](https://developer.ibm.com/messaging/2019/02/05/ibm-mq-macos-toolkit-for-developers/)).
131132

132133
1. Install Golang
133-
- This library has been validated with Golang v1.11.4. If you don't have Golang installed on your system you can [download it here](https://golang.org/doc/install) for MacOS, Linux or Windows
134+
- This library has been validated with Golang v1.11.4 and v1.12.9. If you don't have Golang installed on your system you can [download it here](https://golang.org/doc/install) for MacOS, Linux or Windows
134135
2. Install 'dep' to manage the dependent packages
135136
- See [Installation instructions](https://github.com/golang/dep#installation) for details
136137
3. Install the MQ Client library
@@ -193,9 +194,9 @@ The test cases use the `CreateConnectionFactoryFromDefaultJSONFiles` method to o
193194
- `connection_info.json` contains information like the hostname/port/channel
194195
- If you are using the MQ on Cloud service you can download a pre-populated file directly from the queue manager details page as [described here](https://cloud.ibm.com/docs/services/mqcloud/mqoc_jms_tls.html#connection_info-json)
195196
- Otherwise you can insert details of your own queue manager into [this sample file](./config-samples/connection_info.json) and copy it to your `/Downloads` directory
196-
- `apiKey.json` contains the Application username and password that will be used to connect to your queue manager
197+
- `applicationApiKey.json` contains the Application username and password that will be used to connect to your queue manager
197198
- If you are using the MQ on Cloud service you can download a pre-populated file directly from the Application Permissions tab in the service console as [described here](https://cloud.ibm.com/docs/services/mqcloud/mqoc_jms_tls.html#apikey-json)
198-
- Otherwise you can insert details of your own queue manager into [this sample file](./config-samples/apiKey.json) and copy it to your `/Downloads` directory
199+
- Otherwise you can insert details of your own queue manager into [this sample file](./config-samples/applicationApiKey.json) and copy it to your `/Downloads` directory
199200

200201
Once you have added the details of your queue manager and user credentials into the two JSON files and placed them in your `/Downloads` directory you are ready to run the test, which is done in the same way as any other Go tests.
201202

File renamed without changes.

connectionfactory_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ func TestLoadCFFromJSON(t *testing.T) {
3030
log.Fatal(err)
3131
}
3232

33+
assert.Equal(t, mqjms.TransportType_CLIENT, cf.TransportType)
34+
3335
// Creates a connection to the queue manager, using defer to close it automatically
3436
// at the end of the function (if it was created successfully)
3537
context, errCtx := cf.CreateContext()

local_bindings_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (c) IBM Corporation 2019
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+
"github.com/ibm-messaging/mq-golang-jms20/mqjms"
15+
"github.com/stretchr/testify/assert"
16+
"os"
17+
"testing"
18+
)
19+
20+
/*
21+
* Test the use of a local bindings connection to the queue manager, as
22+
* opposed to a remote client connection.
23+
*
24+
* Assumes a locally running queue manager called QM1, with a defined local
25+
* queue called LOCAL.QUEUE
26+
*/
27+
func TestLocalBindingsConnect(t *testing.T) {
28+
29+
// Checking the presence of the mqs.ini file is a reasonably reliable way of
30+
// identifying if there is a local queue manager installation, so that we
31+
// can skip this test if necessary.
32+
if _, err := os.Stat("/var/mqm/mqs.ini"); os.IsNotExist(err) {
33+
fmt.Println("Skipping local bindings test as there is no local queue manager installation.")
34+
return
35+
}
36+
37+
// Create a connection factory that indicates we should use local bindings.
38+
// Note that it includes none of the normal parameters like hostname, port etc.
39+
cf := mqjms.ConnectionFactoryImpl{
40+
QMName: "QM1",
41+
TransportType: mqjms.TransportType_BINDINGS,
42+
}
43+
44+
// Creates a connection to the queue manager, using defer to close it automatically
45+
// at the end of the function (if it was created successfully)
46+
context, ctxErr := cf.CreateContext()
47+
assert.Nil(t, ctxErr)
48+
if context != nil {
49+
defer context.Close()
50+
}
51+
assert.NotNil(t, context)
52+
53+
// Equivalent to a JNDI lookup or other declarative definition
54+
queue := context.CreateQueue("LOCAL.QUEUE")
55+
56+
// Set up the consumer ready to receive messages.
57+
consumer, conErr := context.CreateConsumer(queue)
58+
assert.Nil(t, conErr)
59+
if consumer != nil {
60+
defer consumer.Close()
61+
}
62+
63+
// Check no message on the queue to start with
64+
testMsg, err1 := consumer.ReceiveNoWait()
65+
assert.Nil(t, err1)
66+
assert.Nil(t, testMsg)
67+
68+
// Check the getter/setter behaviour on a producer.
69+
tmpProducer := context.CreateProducer()
70+
tmpProducer.SetTimeToLive(2000)
71+
72+
// Send a message that will expire after 1 second, then immediately receive it (will not have expired)
73+
msgBody := "Local message."
74+
context.CreateProducer().SendString(queue, msgBody)
75+
rcvBody, rcvErr := consumer.ReceiveStringBodyNoWait()
76+
assert.Nil(t, rcvErr)
77+
assert.NotNil(t, rcvBody)
78+
assert.Equal(t, msgBody, *rcvBody)
79+
80+
}

mqjms/ConnectionFactoryImpl.go

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
package mqjms
1111

1212
import (
13-
"github.com/ibm-messaging/mq-golang/ibmmq"
1413
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
14+
"github.com/ibm-messaging/mq-golang/ibmmq"
1515
"strconv"
1616
)
1717

@@ -28,6 +28,8 @@ type ConnectionFactoryImpl struct {
2828
ChannelName string
2929
UserName string
3030
Password string
31+
32+
TransportType int // Default to TransportType_CLIENT (0)
3133
}
3234

3335
// CreateContext implements the JMS method to create a connection to an IBM MQ
@@ -36,26 +38,36 @@ func (cf ConnectionFactoryImpl) CreateContext() (jms20subset.JMSContext, jms20su
3638

3739
// Allocate the internal structures required to create an connection to IBM MQ.
3840
cno := ibmmq.NewMQCNO()
39-
cd := ibmmq.NewMQCD()
40-
41-
// Fill in the required fields in the channel definition structure
42-
cd.ChannelName = cf.ChannelName
43-
cd.ConnectionName = cf.Hostname + "(" + strconv.Itoa(cf.PortNumber) + ")"
44-
45-
// Store the user credentials in an MQCSP, which ensures that long passwords
46-
// can be used.
47-
csp := ibmmq.NewMQCSP()
48-
csp.AuthenticationType = ibmmq.MQCSP_AUTH_USER_ID_AND_PWD
49-
csp.UserId = cf.UserName
50-
csp.Password = cf.Password
51-
52-
// Join the objects together as necessary so that they can be provided as
53-
// part of the connect call.
54-
cno.ClientConn = cd
55-
cno.SecurityParms = csp
56-
57-
// Indicate that we want to use a client (TCP) connection.
58-
cno.Options = ibmmq.MQCNO_CLIENT_BINDING
41+
42+
if cf.TransportType == TransportType_CLIENT {
43+
44+
// Indicate that we want to use a client (TCP) connection.
45+
cno.Options = ibmmq.MQCNO_CLIENT_BINDING
46+
47+
// Fill in the required fields in the channel definition structure
48+
cd := ibmmq.NewMQCD()
49+
cd.ChannelName = cf.ChannelName
50+
cd.ConnectionName = cf.Hostname + "(" + strconv.Itoa(cf.PortNumber) + ")"
51+
cno.ClientConn = cd
52+
53+
} else if cf.TransportType == TransportType_BINDINGS {
54+
55+
// Indicate to use Bindings connections.
56+
cno.Options = ibmmq.MQCNO_LOCAL_BINDING
57+
58+
}
59+
60+
if cf.UserName != "" {
61+
62+
// Store the user credentials in an MQCSP, which ensures that long passwords
63+
// can be used.
64+
csp := ibmmq.NewMQCSP()
65+
csp.AuthenticationType = ibmmq.MQCSP_AUTH_USER_ID_AND_PWD
66+
csp.UserId = cf.UserName
67+
csp.Password = cf.Password
68+
cno.SecurityParms = csp
69+
70+
}
5971

6072
var ctx jms20subset.JMSContext
6173
var retErr jms20subset.JMSException

mqjms/Constants.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) IBM Corporation 2019.
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+
// Implementation of the JMS style Golang interfaces to communicate with IBM MQ.
10+
package mqjms
11+
12+
// Used to configure the TransportType property of the ConnectionFactory,
13+
// to use a TCP client connection to the queue manager. This is the default.
14+
const TransportType_CLIENT int = 0
15+
16+
// Used to configure the TransportType property of the ConnectionFactory,
17+
// to use a local bindings connection to the queue manager
18+
const TransportType_BINDINGS int = 1

mqjms/ConsumerImpl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ package mqjms
1111

1212
import (
1313
"errors"
14-
"github.com/ibm-messaging/mq-golang/ibmmq"
1514
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
15+
"github.com/ibm-messaging/mq-golang/ibmmq"
1616
"strconv"
1717
"strings"
1818
)

mqjms/ContextImpl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
package mqjms
1111

1212
import (
13-
"github.com/ibm-messaging/mq-golang/ibmmq"
1413
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
14+
"github.com/ibm-messaging/mq-golang/ibmmq"
1515
"strconv"
1616
)
1717

mqjms/FactoryFactory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func CreateConnectionFactoryFromJSON(connectionInfoLocn string, apiKeyLocn strin
5858
}
5959

6060
if apiKeyLocn == "" {
61-
apiKeyLocn = os.Getenv("HOME") + "/Downloads/apiKey.json"
61+
apiKeyLocn = os.Getenv("HOME") + "/Downloads/applicationApiKey.json"
6262
}
6363

6464
// Attempt to read the connection info file at the specified location.

mqjms/ProducerImpl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ package mqjms
1111

1212
import (
1313
"fmt"
14-
"github.com/ibm-messaging/mq-golang/ibmmq"
1514
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
15+
"github.com/ibm-messaging/mq-golang/ibmmq"
1616
"log"
1717
"strconv"
1818
)

mqjms/TextMessageImpl.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ package mqjms
1212
import (
1313
"encoding/hex"
1414
"fmt"
15-
"github.com/ibm-messaging/mq-golang/ibmmq"
1615
"github.com/ibm-messaging/mq-golang-jms20/jms20subset"
16+
"github.com/ibm-messaging/mq-golang/ibmmq"
1717
"log"
1818
"strconv"
1919
"strings"
@@ -99,7 +99,7 @@ func (msg *TextMessageImpl) SetJMSReplyTo(dest jms20subset.Destination) jms20sub
9999
log.Fatal(jms20subset.CreateJMSException("UnexpectedDestinationType", "UnexpectedDestinationType", nil))
100100
}
101101

102-
// The option to return an error is not currently used.
102+
// The option to return an error is not currently used.
103103
return nil
104104
}
105105

next-features.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ Not currently implemented:
1414
- Topics (pub/sub)
1515
- Message Properties etc
1616
- Temporary destinations
17-
- Local bindings connections
1817
- Priority
1918

2019

0 commit comments

Comments
 (0)