Skip to content

Commit de11385

Browse files
committed
Update for MQ 9.4.3; enablement for Testcontainers
1 parent 990de82 commit de11385

32 files changed

+714
-202
lines changed

CHANGES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Changelog
22
Newest updates are at the top of this file
33

4+
## 3.5.1 (2025-06-19)
5+
- Update to MQ 9.4.3.0
6+
- Update Spring dependencies
7+
- Add Testcontainers enablement
8+
- See README_TESTCONTAINERS.md
9+
- See samples/s5
10+
411
## <No new version> (2025-03-06)
512
- Add Narayana-based global transaction sample
613
- Update build process in preparation for Boot 4.

README.md

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
# IBM MQ JMS Spring Components
22

3-
This repository contains code to help to provide Spring developers with easy configuration of the IBM MQ JMS package.
3+
This repository contains code to help to provide Spring developers with easy configuration and testing of the IBM MQ JMS
4+
package.
45

56
The library contains:
67

78
- `mq-jms-spring-boot-starter` for [Spring Boot](https://projects.spring.io/spring-boot/) applications
9+
- `mq-jms-spring-testcontainer` for testing Spring Boot applications
10+
- `mq-java-testcontainer` for integration with the [Testcontainers](https://testcontainers.org) project
811

9-
NOTE: Spring Boot 2 has now reached its end of non-commercial service life.
10-
So version 2.7.18 is the last update based on Spring 2. Further updates will
11-
follow the Spring 3 path only. If you want to continue to use Spring 2 with future versions of the MQ jars,
12-
then overriding the version inherited from the mq-jms-spring-boot in your parent pom.xml should be possible.
13-
However, this would not give easy access via configuration to any new features available in the MQ client.
12+
NOTE: Spring Boot 2 has now reached its end of non-commercial service life. So version 2.7.18 is the last update based
13+
on Spring 2. Further updates will follow the Spring 3 path only. If you want to continue to use Spring 2 with future
14+
versions of the MQ jars, then overriding the version inherited from the mq-jms-spring-boot in your parent pom.xml should
15+
be possible. However, this would not give easy access via configuration to any new features available in the MQ client.
16+
17+
NOTE: Spring Boot 4 is under development planned for release later in 2025. While this package does not currently do
18+
anything specific for Boot 4, the pieces are already in place to be able to build against it once it is available.
1419

1520
## Installation and Usage
1621

@@ -49,22 +54,28 @@ Maven:
4954
**Note** This repository and the corresponding Maven Central artifacts requires Spring Boot 3. Maven
5055
Central continues to provide older versions that work with Spring Boot 2.
5156

57+
## Testcontainers
58+
For testing Spring Boot applications, you may need to provision a queue manager as part of the process. This can be
59+
done by using the Testcontainers framework. For more information about the MQ package, see [here](README_TESTCONTAINERS.md).
60+
Also look at the `samples/s5` directory for a demonstration.
61+
5262
## Design Approach
5363

5464
The approach taken here is to follow the model for JMS applications shown in the
5565
[Spring Getting Started Guide for JMS](https://spring.io/guides/gs/messaging-jms/). That in turn
5666
is based on using the [JmsTemplate Framework](https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#jms-jmstemplate)
5767

58-
Some simple example programs using Spring Boot and JMS interfaces can be found in the samples directory. The RUNME.sh program in
59-
each subdirectory compiles and executes it. The application.properties files in that tree may need modification for your environment.
68+
Some simple example programs using Spring Boot and JMS interfaces can be found in the samples directory. The RUNME.sh
69+
program in each subdirectory compiles and executes it. The _application.properties_ or _application.yml_ files in that
70+
tree may need modification for your environment.
6071

6172
Essentially what gets configured from this package are a ConnectionFactory which Spring's JmsTemplate implementation
6273
exploits to provide a simpler interface, and a MessageListener.
6374

6475
## Getting Started
6576

6677
To get started quickly, you can use the default configuration settings in this package along with the
67-
IBM MQ for Developers container which runs the server processes.
78+
IBM MQ Advanced for Developers container which runs the server processes.
6879

6980
### Default Configuration
7081

@@ -80,7 +91,7 @@ This script will run the container on a Linux system.
8091
--publish 1414:1414 \
8192
--publish 9443:9443 \
8293
--detach \
83-
ibmcom/mq
94+
icr.io:ibm-messaging/mq:latest
8495

8596
The default attributes are
8697

@@ -90,7 +101,7 @@ The default attributes are
90101
ibm.mq.user=
91102
ibm.mq.password=
92103

93-
### Connection security
104+
### Authentication with passwords
94105

95106
The default userid and password have been removed from this package, as the corresponding default configuration has been
96107
removed from the MQ Developer images. Authentication must now be explicitly defined both for the queue manager, and for
@@ -106,11 +117,27 @@ must now set the `ibm.mq.user` and `ibm.mq.password` attribute.
106117
Configuration of secure connections with TLS are discussed below.
107118

108119

109-
#### JWT Tokens
120+
### Authentication with JWT tokens
110121
If the queue manager has been configured to authenticate applications based on JWT tokens, then those tokens can be
111122
provided through the JMS layer.
112123

113-
To use this, you can either set `ibm.mq.token`
124+
#### MQ-retrieved tokens
125+
The JMS client code can generate and retrieve tokens from a server automatically, without needing the application to
126+
explicitly contact the token server itself. The application needs configuration of how to contact the server, but then
127+
the communication to the token server (eg Keycloak) is handled automatically. The `ibm.mq.tokenServer` section of the
128+
configuration provides the route and authentication mechanism for the server.
129+
130+
**Note:** There are some current constraints on how this mechanism works, with respect to the HTTPS connection that needs
131+
to be made to the token server:
132+
* The keystore/truststore uses process-wide environment variables that might affect other components of the application
133+
if they also use the `javax.net.ssl` properties.
134+
* The keystore/truststore must be local JKS files, not embedded in the jar and its classpath
135+
* The `validateCertificatePolicy` setting cannot be used to always trust a token server's certificate
136+
137+
138+
#### Explicity-provided tokens
139+
Having the token provided directly in the application configuration continues to work, but is not the recommended
140+
approach, now that the MQ JMS layer can do that retrieval itself. To use this method, you can either set `ibm.mq.token`
114141
or the password to the token. If you use the `password` attribute, then the `user` must also be set to the empty value
115142
(which is now the default anyway).
116143

@@ -196,9 +223,31 @@ Spring Boot will then create a ConnectionFactory that can then be used to intera
196223

197224
The `reconnect` option was previously named `defaultReconnect` but both names work in the configuration.
198225

226+
For contacting a Token Server, these options define its address and authentication. All three properties
227+
have to be supplied if you are using this authentication mechanism:
228+
229+
| Option (ibm.mq.tokenServer) | Description |
230+
| -----------------------------| ------------------------------------------------------------------------------ |
231+
| endpoint | URL pointing at the token server (eg https://my.keycloak.server) |
232+
| clientId | The ClientId for authentication to the server (unrelated to ibm.mq.clientId) |
233+
| clientSecret | The ClientSecret for authentication to the server |
234+
199235
#### TLS related options
200236

201-
The following options all default to null, but may be used to assist with configuring TLS
237+
The preferred approach for setting the key/truststores is available from Spring 3.1, which introduced the
238+
concept of "SSL Bundles". This makes it possible to have different SSL configurations - keystores, truststores etc - for
239+
different components executing in the same Spring-managed process. See
240+
[here](https://spring.io/blog/2023/06/07/securing-spring-boot-applications-with-ssl) for a description of the options
241+
available. Each bundle has an identifier with the `spring.ssl.bundle.jks.<key>` tree of options. The key can be
242+
specified for this package with `ibm.mq.sslBundle` which then uses the Spring elements to create the connection
243+
configuration. The default value for this key is empty, meaning that `SSLBundles` will not be used; the global SSL
244+
configuration is used instead. However the `ibm.mq.jks` properties are now marked as deprecated.
245+
246+
| Option (ibm.mq) | Description |
247+
| -------------------- | ---------------------------------------------------------------------------- |
248+
| sslBundle | Spring Boot option (from 3.1) for granular certificate configuration |
249+
250+
The following options all default to null, but may also be used to assist with configuring TLS
202251

203252
| Option (ibm.mq) | Description |
204253
| -------------------- | ------------------------------------------------------------------------------- |
@@ -226,27 +275,8 @@ and
226275
| keyStore | Where is the keystore with a personal key and certificate |
227276
| keyStorePassword | Password for the keyStore |
228277

229-
These JKS options are an alternative to setting the `javax.net.ssl` system properties, usually done on the command line.
230-
231-
An alternative preferred approach for setting the key/truststores is available from Spring 3.1, which introduced the
232-
concept of "SSL Bundles". This makes it possible to have different SSL configurations - keystores, truststores etc - for
233-
different components executing in the same Spring-managed process. See
234-
[here](https://spring.io/blog/2023/06/07/securing-spring-boot-applications-with-ssl) for a description of the options
235-
available. Each bundle has an identifier with the `spring.ssl.bundle.jks.<key>` tree of options. The key can be
236-
specified for this package with `ibm.mq.sslBundle` which then uses the Spring elements to create the connection
237-
configuration. The default value for this key is empty, meaning that `SSLBundles` will not be used; the global SSL
238-
configuration is used instead. However the `ibm.mq.jks` properties are now marked as deprecated.
239-
240-
| Option (ibm.mq) | Description |
241-
| -------------------- | ---------------------------------------------------------------------------- |
242-
| sslBundle | Spring Boot option (from 3.1) for granular certificate configuration |
243-
244-
To achieve the same effect with Spring 2.x, you could use your own code to create an `SSLSocketFactory` object
245-
which can be applied to the MQ Connection Factory in a `customise` method before the CF is invoked.
246-
247-
Spring Boot 3.4.0 changed how the sslBundles are loaded. If you have a simple file name such as `location: "key.jks"`
248-
and there is an exception saying that the file cannot be found, then change the property to `location: "file:key.jks"`.
249-
This regression has been fixed in Spring Boot 3.4.2, so you should not see this problem.
278+
These deprecated JKS options are an alternative to setting the `javax.net.ssl` system properties, usually done on the
279+
command line. They are not used if you have set the `sslBundle` property.
250280

251281
#### Caching connection factory options
252282

@@ -344,8 +374,13 @@ more details.
344374
However this package also enables some simple use of JNDI for Connection definitions (but not Destinations, as they are
345375
still always handled by the core Spring classes).
346376

347-
You can set the `ibm.mq.jndi.providerUrl` and `ibm.mq.jndi.providerContextFactory` attributes to define how the lookup
348-
is to be carried out. For example,
377+
| Option (ibm.mq.jndi) | Description |
378+
| -----------------------| ------------------------------------------- |
379+
| providerUrl | Location of the directory |
380+
| providerContextFactory | Class implementing the directory |
381+
| additionalProperties | For further configuration - class-dependent |
382+
383+
For example,
349384

350385
```
351386
ibm.mq.jndi.providerUrl=file:///home/username/mqjms/jndi

README_TESTCONTAINERS.md

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Testcontainers for IBM MQ
22

3-
This commit introduces an initial version of support for the [testcontainers](https://testcontainers.org) project.
3+
This repo introduces enablement for the [testcontainers](https://testcontainers.org) project.
44

55
The project simplifies use of various resources as part of an application's automated testing, making it convenient for
66
use in things like CI pipelines.
@@ -10,29 +10,24 @@ one to integrate that with Spring.
1010
* com.ibm.com:mq-java-testcontainer
1111
* com.ibm.com:mq-jms-spring-testcontainer
1212

13-
The intention is eventually to release these jar files to Maven Central in the same way as other MQ java packages.
14-
Initially however, just to give early access and to validate that the components have the right options, features and
15-
overall shape, only the source code is available via this repository. You can then build the jar files and use them from
16-
your own environment.
17-
1813
I'm not going to go into details about using the `testcontainers` framework and how it fits into testing strategies. The
1914
intention is that this MQ support enables all of the common testing patterns in the same way as other resources.
2015

2116
While the testcontainers project has packages for a variety of languages, for now we are only providing a Java version.
2217

2318
## Container image licensing
24-
*NOTE:* The default container referenced in the `MQContainer` class points at the MQ Advanced for Developers image. That image
25-
has license restrictions, constraining it to internal development and unit testing. See
19+
*NOTE:* The default container referenced in the `MQContainer` class points at the MQ Advanced for Developers image. That
20+
image has license restrictions, constraining it to internal development and unit testing. See
2621
[here](https://www.ibm.com/support/customer/csol/terms/?id=L-HYGL-6STWD6&lc=en) for full terms.
2722

2823
Other licensed container images can be used that do not have the same restrictions. Just name the appropriate image in the
2924
test configuration and provide credentials for authenticating to the container registry.
3025

3126
## Known limitations
3227
The only prebuilt public MQ container image released by IBM is for Linux/x64 systems. Therefore this `testcontainers`
33-
function will can only use the default image on that platform. However, it is possible to reference non-public IBM images or to
34-
build your own containers for other platforms - in particular for Linux on Arm64 systems for MacOS developers - and then
35-
refer to that private container image.
28+
function can only use the default image on that platform. However, it is possible to reference non-public IBM images or
29+
to build your own containers for other platforms - in particular for Linux on Arm64 systems for MacOS developers - and
30+
then refer to that private container image.
3631

3732
Some of the controls assume options from an image built by the
3833
[`mq-container`](https://github.com/ibm-messaging/mq-container) scripts. That includes the default developer objects
@@ -41,17 +36,6 @@ such as `DEV.QUEUE.1` and the `app`/`admin` userids.
4136
If you are not using the MQ Advanced for Developers image, then application authentication (in particular) may need some
4237
consideration.
4338

44-
## Building the package
45-
Make sure you are in the `testcont` branch of the repository and use the RUNME.sh script to build the jar files. Java 17
46-
is the minimum level required to build the packages.
47-
48-
```
49-
git clone [email protected]:ibm-messaging/mq-jms-spring
50-
cd mq-jms-spring # To get into the root directory
51-
git checkout testcont # Make the branch active
52-
./RUNME.sh -b 3 -c -n # Compile the various components. They will appear under $HOME/.m2
53-
```
54-
5539
## Sample Test program
5640
The *s5* sample has a basic "normal" application, which is not very interesting. But there is also a "test" option that
5741
uses the SpringRunner framework to execute a simple test. To speed things up in initial repeated testing of the tests,
@@ -74,15 +58,14 @@ The _src/test/resources/99-startup.mqsc_ file has additional MQSC commands to be
7458
that file is included by default for the Classpath resource loaders at runtime. Also in that directory is some
7559
configuration for the logger, to show execution information.
7660

77-
Look at _build.gradle_ for the required dependencies. This includes looking locally for the jars that you have built in
78-
the previous step.
61+
Look at _build.gradle_ for the required dependencies.
7962

8063
## The MQContainer class
8164
The core of the container management is in the `com.ibm.mq.testcontainers.MQContainer` class. This ends up in the
8265
`mq-java-testcontainer.jar` package.
8366

84-
An image name (of type `DockerImageName`) must always be passed to the constructor for this class. You can use the
85-
`MQContainer.DEFAULT_IMAGE` to select the MQ Advanced for Developers image at whatever level the `latest` tag points at.
67+
An image name must always be passed to the constructor for this class. You can use the `MQContainer.DEFAULT_IMAGE` to
68+
select the MQ Advanced for Developers image at whatever level the `latest` tag points at.
8669

8770
There are then methods to apply some simple configuration changes. Not every possible option for connectivity is applied
8871
or exposed; the intention here is to have just enough for basic testing. In particular, nothing is done about TLS
@@ -94,9 +77,9 @@ configurations. Public methods include:
9477
* withChannel, withQueueManager
9578
* withWebServer: start the web server during container initialisation (default does not start it). Enable this feature
9679
if you want to test an application using one of the MQ REST APIs for messaging or administration.
97-
* withStartupMQSC: names an MQSC file on the Classpath that gets loaded into the container for automatic execution
80+
* withStartupMQSC: names a single MQSC file on the Classpath that gets loaded into the container for automatic execution
9881
during queue manager startup. This allows you to create additional objects or reset state if you are reusing an
99-
existing queue manager (eg a mounted external docker volume).
82+
existing queue manager (eg because you have mounted an external docker volume).
10083

10184
The `appPassword` ends up being the `password` value used for the Spring Boot JMS connection.
10285

RUNME.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ done
133133
shift $((OPTIND-1))
134134
if [ "$1" != "" ]
135135
then
136-
printSyntax
136+
tasks=$*
137137
fi
138138

139139
if [ -z "$bootVersions" ]
@@ -198,7 +198,8 @@ do
198198

199199
cd $curdir
200200
export BOOTVERSION=$vers
201-
args="" # "--stacktrace --debug" # Gradle debugging options
201+
mkdir -p /tmp/mvn.repo
202+
args="" # "-Dmaven.repo.local=/tmp/mvn.repo" # "--stacktrace --debug" # Gradle debugging options
202203

203204
if $gaRelease
204205
then
@@ -222,7 +223,7 @@ do
222223
fi
223224

224225
# Possible Targets are: publishAllPublicationsToMavenRepository publishToMavenLocal
225-
(./gradlew $args --warning-mode all clean jar $target 2>&1;echo $? > $rcFile) | tee -a $buildLog
226+
(./gradlew $args --warning-mode all clean jar $target $tasks 2>&1;echo $? > $rcFile) | tee -a $buildLog
226227

227228
# Always make sure we've got a dummy properties file - the values are not needed from here on
228229
cp -p gradle.properties.template gradle.properties

0 commit comments

Comments
 (0)