diff --git a/CHANGES.md b/CHANGES.md index 7cebf67..72a3b31 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,14 @@ # Changelog Newest updates are at the top of this file +## 2.7.17 and 3.1.5 (2023-10-20) +- Update Spring dependencies +- Update to MQ 9.3.4.0 + - Uniform Cluster balancing options now available in JMS +- Fix SSLBundle sequencing (#96) +- Update documentation links to reflect IBM site changes (#100) +- Update to Gradle 8.4 + ## 2.7.14 and 3.1.2 (2023-07-20) - Update Spring dependencies - Add SSLBundle configuration option for Boot 3.1 apps (#94) diff --git a/README.md b/README.md index 3f8f871..bd88be5 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,18 @@ The library contains: The compiled versions of this package can be automatically downloaded from Maven Central. -For local modifications -and building it yourself, you can use the `RUNME.sh` script. It uses gradle as the build mechanism and has tasks that can -push compiled jars to either a local repository (typically under `$HOME/.m2`) or to Maven Central. -When signing/authentication of modules is required, use the `gradle.properties.template` file as a starter for your own `gradle.properties`. +For local modifications and building it yourself, you can use the `RUNME.sh` script. It uses gradle as the build +mechanism and has tasks that can push compiled jars to either a local repository (typically under `$HOME/.m2`) or to +Maven Central. When signing/authentication of modules is required, use the `gradle.properties.template` file as a +starter for your own `gradle.properties`. -Java 17 is required as the compiler level when building this package, as that is the baseline for Spring 3. Compiler directives are used to build -the Spring 2 version as compatible with the older Java 8 runtime. +Java 17 is required as the compiler level when building this package, as that is the baseline for Spring 3. Compiler +directives are used to build the Spring 2 version as compatible with the older Java 8 runtime. -The script builds modules for both the JMS2 and JMS3 standards. The JMS3 (Jakarta) variant is the primary source. The older JMS2 version does not have a separate source tree in this repository. Instead, the source is generated automatically during the build process, by simply changing package names in the JMS3 code. The created jar files have the same names, but different version numbers. +The script builds modules for both the JMS2 and JMS3 standards. The JMS3 (Jakarta) variant is the primary source. The +older JMS2 version does not have a separate source tree in this repository. Instead, the source is generated +automatically during the build process, by simply changing package names in the JMS3 code. The created jar files have +the same names, but different version numbers. ### Spring Boot Applications @@ -43,8 +46,7 @@ Maven: ``` -**Note** This repository and the corresponding Maven Central artifacts require -either Spring Boot 2 or 3. +**Note** This repository and the corresponding Maven Central artifacts require either Spring Boot 2 or 3. ## Design Approach @@ -89,25 +91,25 @@ The default attributes are ### Connection security -The default userid and password have been chosen for a commonly-used queue manager -configuration. +The default userid and password have been chosen for a commonly-used queue manager configuration. -To disable user/password checking entirely, you must set the `ibm.mq.user` attribute to an empty value -so that the default is not used. +To disable user/password checking entirely, you must set the `ibm.mq.user` and `ibm.mq.password` attribute to empty +values so that the defaults are not used. ``` ibm.mq.user= + ibm.mq.password= ``` -Of course, that level of access must be permitted by your queue manager. The usual CHLAUTH and CONNAUTH -rules will apply to assign an identity to the connection. +Of course, that level of access must be permitted by your queue manager. The usual CHLAUTH and CONNAUTH rules will apply +to assign an identity to the connection. Configuration of secure connections with TLS are discussed below. ### Configuration Options -If you already have a running MQ queue manager that you want to use, then you can easily modify the -default configuration to match by providing override values. +If you already have a running MQ queue manager that you want to use, then you can easily modify the default +configuration to match by providing override values. The queue manager name is given as @@ -120,13 +122,12 @@ For client connections to a queue manager, you must also have either or - `ibm.mq.ccdtUrl` -If both the channel and connName are empty, and the CCDTURL is not supplied, -then a local queue manager is assumed. The CCDTURL property is taken in preference to -the channel and connName. The channel and connName have non-blank defaults, so must be -explicitly set to empty strings if you do not wish them to be used. +If both the channel and connName are empty, and the CCDTURL is not supplied, then a local queue manager is assumed. The +CCDTURL property is taken in preference to the channel and connName. The channel and connName have non-blank defaults, +so must be explicitly set to empty strings if you do not wish them to be used. -Optionally you can provide a [client id](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q112000_.html) -and [application name](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q111810_.htm) if required. +Optionally you can provide a [client id](https://www.ibm.com/docs/en/ibm-mq/latest?topic=objects-clientid) +and [application name](https://www.ibm.com/docs/en/ibm-mq/latest?topic=applications-specifying-application-name-in-supported-programming-languages) if required. - `ibm.mq.clientId` - `ibm.mq.applicationName` @@ -164,6 +165,9 @@ Spring Boot will then create a ConnectionFactory that can then be used to intera | ibm.mq.tempModel | The name of a model queue for creating temporary destinations. | | ibm.mq.reconnect | Whether app tries automatic reconnect. Options of YES/NO/QMGR/DISABLED/DEFAULT | | ibm.mq.autoConfigure | If explicitly set to "false", then the autoconfigure bean is disabled | +| ibm.mq.balancingApplicationType | Hint how uniform clusters should treat the app. Options of SIMPLE/REQREP | +| ibm.mq.balancingTimeout | Uniform cluster timer. Options NEVER/DEFAULT/IMMEDIATE or integer seconds | +| ibm.mq.balancingOptions | Rebalancing options. Options of NONE/IGNORETRANS. Default NONE. | The `reconnect` option was previously named `defaultReconnect` but both names work in the configuration. @@ -198,14 +202,14 @@ and These JKS options are an alternative to setting the `javax.net.ssl` system properties, usually done on the command line. -An alternative preferred approach for setting the key/truststores is -available from Spring 3.1, which introduced the concept of "SSL Bundles". This makes it possible to have different -SSL configurations - keystores, truststores etc - for different components executing in the same Spring-managed process. -See [here](https://spring.io/blog/2023/06/07/securing-spring-boot-applications-with-ssl) -for a description of the options available. Each bundle has an identifier with the `spring.ssl.bundle.jks.` tree of options. -The key can be specified for this package with `ibm.mq.sslBundle` which then uses the Spring elements to create the -connection configuration. The default value for this key is empty, meaning that `SSLBundles` will not be used; the global -SSL configuration is used instead. However the `ibm.mq.jks` properties are now marked as deprecated. +An alternative preferred approach for setting the key/truststores is available from Spring 3.1, which introduced the +concept of "SSL Bundles". This makes it possible to have different SSL configurations - keystores, truststores etc - for +different components executing in the same Spring-managed process. See +[here](https://spring.io/blog/2023/06/07/securing-spring-boot-applications-with-ssl) for a description of the options +available. Each bundle has an identifier with the `spring.ssl.bundle.jks.` tree of options. The key can be +specified for this package with `ibm.mq.sslBundle` which then uses the Spring elements to create the connection +configuration. The default value for this key is empty, meaning that `SSLBundles` will not be used; the global SSL +configuration is used instead. However the `ibm.mq.jks` properties are now marked as deprecated. | Option | Description | | ------------------------------- | ---------------------------------------------------------------------------- | @@ -246,10 +250,10 @@ the options can be found [here](https://github.com/messaginghub/pooled-jms/blob/ ### JMS Polling Listener Timer configuration -The Spring AbstractPollingMessageListenerContainer interface has a default polling timer of 1 second. This can be configured -with the `spring.jms.listener.receiveTimeout` property. If the property is not explicitly set, then this MQ Spring Boot -component resets the initial timeout value to 30 seconds which has been shown to be more cost-effective. Application code -can still set its own preferred value. +The Spring AbstractPollingMessageListenerContainer interface has a default polling timer of 1 second. This can be +configured with the `spring.jms.listener.receiveTimeout` property. If the property is not explicitly set, then this MQ +Spring Boot component resets the initial timeout value to 30 seconds which has been shown to be more cost-effective. +Application code can still set its own preferred value. | Option | Description | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | @@ -257,53 +261,50 @@ can still set its own preferred value. ### Additional properties -Additional properties that are not in the recognised sets listed here can be put onto the -Connection Factory via a map in the external properties definitions. Use the format -`ibm.mq.additionalProperties.CONSTANT_NAME=value`. The CONSTANT_NAME can be either the -real string for the property, and will often begin with "XMSC", or it can be the variable as known -in the WMQConstants class. +Additional properties that are not in the recognised sets listed here can be put onto the Connection Factory via a map +in the external properties definitions. Use the format `ibm.mq.additionalProperties.CONSTANT_NAME=value`. The +CONSTANT_NAME can be either the real string for the property, and will often begin with "XMSC", or it can be the +variable as known in the WMQConstants class. -For example, the constant `WMQConstants.WMQ_SECURITY_EXIT` has the value `"XMSC_WMQ_SECURITY_EXIT"` -and can be written in the properties file either as - `ibm.mq.additionalProperties.XMSC_WMQ_SECURITY_EXIT=com.example.SecExit` -or as - `ibm.mq.additionalProperties.WMQ_SECURITY_EXIT=com.example.SecExit` +For example, the constant `WMQConstants.WMQ_SECURITY_EXIT` has the value `"XMSC_WMQ_SECURITY_EXIT"` and can be written +in the properties file either as `ibm.mq.additionalProperties.XMSC_WMQ_SECURITY_EXIT=com.example.SecExit` or as +`ibm.mq.additionalProperties.WMQ_SECURITY_EXIT=com.example.SecExit` +There is no error checking on the property name or value. This may help with enabling rarely-used properties and reduce +the need for a customizer method in application code. See +[the KnowledgeCenter](https://www.ibm.com/docs/en/ibm-mq/latest?topic=messaging-mqconnectionfactoryconnectionfactoryproperty) +for a list of all the currently-recognised properties that may be set on a CF - though note that many are now +deprecated. -There is no error checking on the property name or value. This may help with enabling -rarely-used properties and reduce the need for a customizer method in application -code. See [the KnowledgeCenter](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.javadoc.doc/WMQJMSClasses/com/ibm/mq/jms/MQConnectionFactory.ConnectionFactoryProperty.html) -for a list of all the currently-recognised properties that may be set on a CF - though note that many are now deprecated. - -If the value looks like a number, it is treated as such. You can use hex constants beginning "0X" or decimals for a number. -Similarly if the value is TRUE/FALSE then that is processed as a boolean. -So you cannot try to set a string property that appears to be an integer. -Symbols representing the value of integer attributes cannot be used - the real +If the value looks like a number, it is treated as such. You can use hex constants beginning "0X" or decimals for a +number. Similarly if the value is TRUE/FALSE then that is processed as a boolean. So you cannot try to set a string +property that appears to be an integer. Symbols representing the value of integer attributes cannot be used - the real number must be given. ## JNDI -Spring already has configuration parameters for the use of a JNDI repository with a JMS program. -See the [Spring documentation](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/jms.html) for more -details. +Spring already has configuration parameters for the use of a JNDI repository with a JMS program. See the +[Spring documentation](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/jms.html) for +more details. -However this package also enables some simple use of JNDI for Connection definitions (but not Destinations, as they are still always -handled by the core Spring classes). +However this package also enables some simple use of JNDI for Connection definitions (but not Destinations, as they are +still always handled by the core Spring classes). -You can set the `ibm.mq.jndi.providerUrl` and `ibm.mq.jndi.providerContextFactory` attributes to define -how the lookup is to be carried out. For example, +You can set the `ibm.mq.jndi.providerUrl` and `ibm.mq.jndi.providerContextFactory` attributes to define how the lookup +is to be carried out. For example, ``` ibm.mq.jndi.providerUrl=file:///home/username/mqjms/jndi ibm.mq.jndi.providerContextFactory=com.sun.jndi.fscontext.RefFSContextFactory ``` -If you choose to use this mechanism, all of the other queue manager properties that might be defined in your resource definitions are ignored and not -traced in order to avoid confusion. They will instead be picked up from the ConnectionFactory definition in JNDI. -The `queueManager` property is then more accurately used as the ConnectionFactory name used as the lookup. If you are using -an LDAP JNDI provider, then the CF name will be modified if necessary to always begin with `cn=`. +If you choose to use this mechanism, all of the other queue manager properties that might be defined in your resource +definitions are ignored and not traced in order to avoid confusion. They will instead be picked up from the +ConnectionFactory definition in JNDI. The `queueManager` property is then more accurately used as the ConnectionFactory +name used as the lookup. If you are using an LDAP JNDI provider, then the CF name will be modified if necessary to +always begin with `cn=`. -The `ibm.mq.jndi.additionalProperties` prefix can be used for any other JNDI-related properties that need to be applied to the -*Context* object. The symbolic name of the field from that Java class can be used. For example, +The `ibm.mq.jndi.additionalProperties` prefix can be used for any other JNDI-related properties that need to be applied +to the *Context* object. The symbolic name of the field from that Java class can be used. For example, ``` ibm.mq.jndi.additionalProperties.SECURITY_CREDENTIALS=passw0rd @@ -314,29 +315,27 @@ results in env.put(Context.SECURITY_CREDENTIALS,"passw0rd") ``` -The `MQConnectionFactoryFactory.getJndiContext` method is public so you can use it with your own -constructed properties object and get access to a JNDI Context object - it might make it easier to work -with Destinations if you can reuse the same way of getting directory access. +The `MQConnectionFactoryFactory.getJndiContext` method is public so you can use it with your own constructed properties +object and get access to a JNDI Context object - it might make it easier to work with Destinations if you can reuse the +same way of getting directory access. ## Logging & Tracing -The package makes use of the logging capabilities within Spring. You can enable -tracing of this specific component in your application's properties file by setting -`logging.level.com.ibm.mq.spring.boot=TRACE`. Otherwise it uses the standard -inheritance of logging configuration from `logging.level.root`downwards. +The package makes use of the logging capabilities within Spring. You can enable tracing of this specific component in +your application's properties file by setting `logging.level.com.ibm.mq.spring.boot=TRACE`. Otherwise it uses the +standard inheritance of logging configuration from `logging.level.root`downwards. ## Related documentation -- [MQ documentation](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest) +- [MQ documentation](https://www.ibm.com/docs/en/ibm-mq/latest) - [Spring Boot documentation](https://projects.spring.io/spring-boot/) - [Spring Framework documentation](https://projects.spring.io/spring-framework/) ### Contributions and Pull requests -Contributions to this package can be accepted under the terms of the Developer's Certificate -of Origin, found in the [DCO file](DCO1.1.txt) of this repository. When -submitting a pull request, you must include a statement stating you accept the terms -in the DCO. +Contributions to this package can be accepted under the terms of the Developer's Certificate of Origin, found in the +[DCO file](DCO1.1.txt) of this repository. When submitting a pull request, you must include a statement stating you +accept the terms in the DCO. ### Using in Other Projects @@ -346,20 +345,20 @@ The preferred approach for using this package in other projects will be to use t Copyright © 2018, 2023 IBM Corp. All rights reserved. -Licensed under the apache license, version 2.0 (the "license"); you may not use this file except in compliance with the license. -You may obtain a copy of the license at +Licensed under the apache license, version 2.0 (the "license"); you may not use this file except in compliance with the +license. You may obtain a copy of the license at http://www.apache.org/licenses/LICENSE-2.0.html -Unless required by applicable law or agreed to in writing, software distributed under the license is distributed on an "as is" basis, -without warranties or conditions of any kind, either express or implied. See the license for the specific language governing -permissions and limitations under the license. +Unless required by applicable law or agreed to in writing, software distributed under the license is distributed on an +"as is" basis, without warranties or conditions of any kind, either express or implied. See the license for the specific +language governing permissions and limitations under the license. ### Health Warning -This package is provided as-is with no guarantees of support or updates. You cannot use -IBM formal support channels (Cases/PMRs) for assistance with material in this repository. -There are also no guarantees of compatibility with any future versions of the package; -the API is subject to change based on any feedback. Versioned releases are made to assist with using stable APIs. +This package is provided as-is with no guarantees of support or updates. You cannot use IBM formal support channels +(Cases/PMRs) for assistance with material in this repository. There are also no guarantees of compatibility with any +future versions of the package; the API is subject to change based on any feedback. Versioned releases are made to +assist with using stable APIs. ### Issues diff --git a/RUNME.sh b/RUNME.sh index 3a5c81a..7e315cb 100755 --- a/RUNME.sh +++ b/RUNME.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright 2022 IBM Corp. All rights reserved. +# Copyright 2022, 2023 IBM Corp. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file # except in compliance with the License. You may obtain a copy of the License at diff --git a/build.gradle b/build.gradle index 1e2c99f..6705c8a 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ subprojects { apply plugin: 'signing' // This is the MQ client version - ext.mqVersion = '9.3.3.0' + ext.mqVersion = '9.3.4.0' ext.mqGroup = 'com.ibm.mq' // The groupid for the compiled jars when uploaded @@ -92,7 +92,7 @@ subprojects { } task sourcesJar(type: Jar, dependsOn: ['mqPrereq',classes]) { - classifier = 'sources' + archiveClassifier = 'sources' sourceSets.all { into(name + "/java", { from allJava }) into(name + "/resources", { from resources }) @@ -125,7 +125,7 @@ subprojects { } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc.destinationDir } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf..41d9927 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 41dfb87..e411586 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acf..1b6c787 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a1..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/jms2.properties b/jms2.properties index 8f5cd1b..09e8241 100644 --- a/jms2.properties +++ b/jms2.properties @@ -1,14 +1,14 @@ // This file contains the versions of Spring etc to work with a javax.jms-based system ext { // Our shipped version - should usually match the Spring Boot Version - mqStarterVersion = '2.7.14' + mqStarterVersion = '2.7.17' // Direct Dependencies - give versions here - springVersion = '5.3.29' - springBootVersion = '2.7.14' + springVersion = '5.3.30' + springBootVersion = '2.7.17' // The pooledJms v2.x level is built against Java 11 so we can't move there - pooledJmsVersion = '1.2.4' + pooledJmsVersion = '1.2.5' jUnitVersion = '4.13.2' // MQ client package diff --git a/jms3.properties b/jms3.properties index 41a9588..ce61434 100644 --- a/jms3.properties +++ b/jms3.properties @@ -2,13 +2,13 @@ ext { // Our shipped version - should usually match the Spring Boot Version but // we keep it different during the pre-GA releases - mqStarterVersion = '3.1.2' + mqStarterVersion = '3.1.5' // Direct Dependencies - give versions here - springVersion = '6.0.11' - springBootVersion = '3.1.2' + springVersion = '6.0.13' + springBootVersion = '3.1.5' - pooledJmsVersion = '3.1.0' + pooledJmsVersion = '3.1.4' jUnitVersion = '4.13.2' // MQ client has a 'jakarta' name diff --git a/mq-jms-spring-boot-starter/build.gradle b/mq-jms-spring-boot-starter/build.gradle index 515947d..2cb0660 100644 --- a/mq-jms-spring-boot-starter/build.gradle +++ b/mq-jms-spring-boot-starter/build.gradle @@ -1,5 +1,5 @@ /* - * Copyright © 2018,2022 IBM Corp. All rights reserved. + * Copyright © 2018,2023 IBM Corp. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -14,10 +14,11 @@ buildscript { repositories { - maven { url 'https://repo.spring.io/plugins-release' } + // maven { url 'https://repo.spring.io/plugins-release' } + mavenCentral() } dependencies { - classpath 'io.spring.gradle:propdeps-plugin:0.0.9.RELEASE' + // classpath 'io.spring.gradle:propdeps-plugin:0.0.9.RELEASE' } } diff --git a/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQAutoConfiguration.java b/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQAutoConfiguration.java index f98bbbf..18e1ab8 100644 --- a/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQAutoConfiguration.java +++ b/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018, 2020 IBM Corp. All rights reserved. + * Copyright © 2018, 2023 IBM Corp. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at @@ -14,8 +14,8 @@ package com.ibm.mq.spring.boot; -import jakarta.jms.ConnectionFactory; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -31,6 +31,8 @@ import com.ibm.mq.jakarta.jms.MQConnectionFactory; +import jakarta.jms.ConnectionFactory; + // See https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0.0-M5-Release-Notes // where autoconfiguration was moved from META-INF/spring.factories to a separate file. The // original file can remain in place though for both Boot 2 and Boot 3. @@ -42,7 +44,11 @@ @ConditionalOnProperty(prefix = "ibm.mq", name = "autoConfigure", matchIfMissing=true) @ConditionalOnMissingBean(ConnectionFactory.class) @EnableConfigurationProperties({MQConfigurationProperties.class, JmsProperties.class}) -@Import({ MQXAConnectionFactoryConfiguration.class,MQConnectionFactoryConfiguration.class }) +@Import({ MQConfigurationSslBundles.class, MQXAConnectionFactoryConfiguration.class,MQConnectionFactoryConfiguration.class }) public class MQAutoConfiguration { + private static Logger logger = LoggerFactory.getLogger(MQAutoConfiguration.class); + public MQAutoConfiguration() { + logger.trace("constructor"); + } } diff --git a/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQConfigurationProperties.java b/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQConfigurationProperties.java index 8cb9c40..4e2aa9b 100644 --- a/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQConfigurationProperties.java +++ b/mq-jms-spring-boot-starter/src/main/java/com/ibm/mq/spring/boot/MQConfigurationProperties.java @@ -14,6 +14,8 @@ package com.ibm.mq.spring.boot; +import java.time.Duration; +import java.time.format.DateTimeParseException; import java.util.HashMap; import java.util.Map; @@ -26,15 +28,19 @@ import com.ibm.msg.client.jakarta.wmq.WMQConstants; /** - * There are many properties that can be set on an MQ Connection Factory/ This class allows configuration for most of them - * for both direct and client connections. Any that are not explicitly named in here can be managed through the "additionalProperties" - * map. + * There are many properties that can be set on an MQ Connection Factory/ This + * class allows configuration for most of them + * for both direct and client connections. Any that are not explicitly named in + * here can be managed through the "additionalProperties" map. *

- * This class allows for setting the CipherSuite/CipherSpec property, and an indication of whether or not - * to use the IBM JRE maps for Cipher names - that's not something that is standardised. + * This class allows for setting the CipherSuite/CipherSpec property, and an + * indication of whether or not + * to use the IBM JRE maps for Cipher names - that's not something that is + * standardised. *

* The default values have been set to match the settings of the - * developer-configured container. + * developer-configured + * container. * *