{"id":668,"date":"2020-03-27T11:20:56","date_gmt":"2020-03-27T11:20:56","guid":{"rendered":"https:\/\/marketaylor.synology.me\/?p=668"},"modified":"2025-06-24T14:44:44","modified_gmt":"2025-06-24T13:44:44","slug":"mq-jms-spring-boot-performance","status":"publish","type":"post","link":"https:\/\/marketaylor.synology.me\/?p=668","title":{"rendered":"MQ JMS and Spring Boot &#8211; improved efficiency"},"content":{"rendered":"<p>The Spring Framework provides simple ways for Java programs to use a variety of interfaces. Its JMS component includes classes that help a program wait for new messages, similar to a Message Driven Bean. The default behaviour of the Spring implementation is known to be non-optimal when working with IBM MQ and I wanted to improve the efficiency.<\/p>\n<p>This article shows recent improvements to <a href=\"https:\/\/github.com\/spring-projects\/spring-framework\" target=\"_blank\" rel=\"noopener noreferrer\">Spring Boot<\/a> and the corresponding <a href=\"https:\/\/github.com\/ibm-messaging\/mq-jms-spring\" target=\"_blank\" rel=\"noopener noreferrer\">MQ JMS Spring Boot<\/a> component. They remove the need for application developers to know about, and to write code to deal with that inefficiency.<\/p>\n<p><!--more--><\/p>\n<p>For more information about the MQ Spring Boot Starter, see<a href=\"https:\/\/marketaylor.synology.me\/?p=425\" target=\"_blank\" rel=\"noopener noreferrer\"> this article<\/a>.<\/p>\n<h2>The problem<\/h2>\n<p>Paul wrote more information about the behaviour of the polling listener in <a href=\"https:\/\/community.ibm.com\/community\/user\/viewdocument\/top-tip-when-using-ibm-mq-and-the-s?CommunityKey=183ec850-4947-49c8-9a2e-8e7c7fc46c64&amp;tab=librarydocuments\" target=\"_blank\" rel=\"noopener noreferrer\">this article<\/a>. But in summary, the Spring <a href=\"https:\/\/docs.spring.io\/spring\/docs\/current\/javadoc-api\/org\/springframework\/jms\/listener\/DefaultMessageListenerContainer.html\" target=\"_blank\" rel=\"noopener noreferrer\">DefaultMessageListenerContainer<\/a> implementation uses a polling approach to receive JMS messages. Essentially it is doing<\/p>\n<pre>  while (no message received) {\n    MQGET(wait for receiveTimeout value)\n    see if anything else needs to be done\n  }\n<\/pre>\n<p>The <em>receiveTimeout<\/em> setting determines how fast the polling loop goes. The value doesn&#8217;t matter for responsiveness to processing an arriving message &#8211; whatever it is set to, the message is read as soon as it is available on the input queue. But setting a high value\u00a0 will mean that other things that might need to be handled (the Spring Framework might be looking for shutdown requests, for example) are delayed until expiry of the timer. So it is important to tune the value.<\/p>\n<p>The default value is 1 second which can mean far more MQGETs being issued than is desirable.<\/p>\n<h3>Tuning in application code<\/h3>\n<p>Application developers can insert a call to <em>setReceiveTimeout()<\/em> on the created listener object in their code. That has been the only way to override that 1s value. The developer must know to do it, as well as picking a suitable value. There has been no mechanism in Spring to change the timer without changing the application code and recompiling the program.<\/p>\n<h2>A better solution<\/h2>\n<p>It is possible to set many properties of a Spring application externally, with a file containing values that is &#8220;outside&#8221; of the application code, although deployed with it. For example, you might have set <code>ibm.mq.queueManager=QM1<\/code>or <code>java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory<\/code>.<\/p>\n<p>But up to now, the listener&#8217;s receiveTimeout could only be set programmatically.<\/p>\n<h3>Changes to Spring Boot<\/h3>\n<p>A change was accepted into Spring Boot version 2.2.0 that makes the JMS Listener capable of using external configuration for the timer. In order to keep the behaviour unchanged for all JMS providers, the default value is still 1s. But it is now possible to put <code>spring.jms.listener.receive-timeout=30s<\/code> in a properties file to change the value (unless the application had previously been coded to set it explicitly).<\/p>\n<p>The property is in <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/time\/Duration.html\" target=\"_blank\" rel=\"noopener noreferrer\">Duration<\/a> format &#8211; a suffix indicates the units. Most likely you&#8217;d want to set it to some number of seconds (eg <code>30s)<\/code>, but a small number of minutes (eg <code>2m<\/code>) may be appropriate. The default unit for a Duration is ms (milliseconds) so not giving the unit suffix might make the polling loop much faster than you expect!<\/p>\n<h3>Changes to MQ JMS package<\/h3>\n<p>Alongside the changes to Spring Boot, a further change was made to the MQ Spring Boot classes in (what is coincidentally the same number) version 2.2.0.<\/p>\n<p>That change detects whether there is an external configuration of the <code>spring.jms.listener.receive-timeout<\/code> property. If found, then that value is respected. If it is not set, then the value is automatically changed from 1s to 30s. And of course, if the application code sets the value later, then that takes precedence instead.<\/p>\n<h2>Demonstration of changes<\/h2>\n<p>To show the changes are effective, I can use the sample program provided with the MQ Spring Boot package. And I can also use the Application Activity Trace to see the real MQI calls being made to the queue manager under the covers.<\/p>\n<p>In one window I run the sample program:<\/p>\n<pre class=\"wp-block-preformatted\">$ cd github.com\/ibm-messaging\/mq-jms-spring\/samples\n$ .\/RUNME.sh\n2020-03-27 10:42:28.301  INFO 2451661 --- [           main] sample1.Application                      : Starting Application\n 2020-03-27 10:42:28.304  INFO 2451661 --- [           main] sample1.Application                      : No active profile set, falling back to default profiles: default\n 2020-03-27 10:42:29.270  INFO 2451661 --- [           main] sample1.Application                      : Started Application in 1.264 seconds (JVM running for 1.577)\n ========================================\n MQ JMS Sample started. Message sent to queue: DEV.QUEUE.1\n ========================================\n MQ JMS Listener started for queue: DEV.QUEUE.1\n NOTE: This program does not automatically end - it continues to wait\n       for more messages, so you may need to hit BREAK to end it.\n ========================================\n Received message is: Hello from IBM MQ at Fri Mar 27 10:42:29 GMT 2020\n &lt;=========----&gt; 75% EXECUTING [17s]\n   :bootRun<\/pre>\n<p>In another window I subscribe to information about the application&#8217;s behaviour:<\/p>\n<pre class=\"wp-block-preformatted\">$ export TOPIC='$SYS\/MQ\/INFO\/QMGR\/QM1\/ActivityTrace\/ApplName\/sample1.Application'\n$ amqsevt -t $TOPIC -m QM1 -o json |\\\n    jq  '.eventData.activityTrace[] | \n         select(.operationId == \"Get\") |\n         .operationTime'<\/pre>\n<p>The <code>jq<\/code> filter pulls out just the timestamps associated with an MQGET operation.<\/p>\n<h3>Before the new capability<\/h3>\n<p>Changing the sample application&#8217;s <strong>build.gradle<\/strong> file to refer to the MQ spring-boot-starter 2.1.4 release (the last version before these changes), and leaving the program to run for a while, we get the output<\/p>\n<pre class=\"wp-block-preformatted\">\"10:50:12\"\n\"10:50:13\"\n\"10:50:14\"\n\"10:50:15\"\n\"10:50:16\"\n\"10:50:17\"\n\"10:50:18\"\n\"10:50:19\"\n\"10:50:20\"\n\"10:50:21\"\n\"10:50:22\"\n\"10:50:23\"\n...<\/pre>\n<p>You can see the 1s loops.<\/p>\n<h3>With the new capability<\/h3>\n<p>Reverting the <strong>build.gradle<\/strong> file to refer to the current <em>mq-jms-spring-boot-starter<\/em> release, and with no other changes, the output looks like<\/p>\n<pre class=\"wp-block-preformatted\">\"10:54:17\"\n\"10:54:17\"\n\"10:54:47\"\n\"10:55:17\"<\/pre>\n<p>where we can see the behaviour is now a 30s loop. Which has significantly reduced the number of MQGET calls. The first MQGET in this short sequence is the one where a message was returned; the rest of the calls receive <code>MQRC_NO_MSG_AVAILABLE<\/code> (2033).<\/p>\n<h3>Explicitly configuring a timer<\/h3>\n<p>For the final test, we add the line <code>spring.jms.listener.receive-timeout=10s<\/code>to the application.properties file in the sample directory. The output now appears like<\/p>\n<pre>\"10:59:02\"\n\"10:59:02\"\n\"10:59:12\"\n\"10:59:22\"\n\"10:59:32\"\n\"10:59:42\"\n\"10:59:52\"\n<\/pre>\n<p>so we can see the 10s non-default value took effect.<\/p>\n<h2>Summary<\/h2>\n<p>If you use Spring Boot with MQ JMS, you now get the benefit of better use of MQ resources without needing to make application changes. Existing applications automatically get this enhancement by simply building with a current version of the <em>mq-jms-spring-boot-starter<\/em>.<\/p>\n<p>Update: 2025-06-24 &#8211; link to Paul&#8217;s article needed to be changed<\/p>\n<p class=\"last-modified\" style=\"border:1px solid;padding: 10px;\">This post was last updated on June 24th, 2025 at 02:44 pm<\/p>","protected":false},"excerpt":{"rendered":"<p>The efficiency of MQ JMS is now improved when used in a Spring Boot application.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[5],"tags":[35,48,20,51,52],"class_list":["post-668","post","type-post","status-publish","format-standard","hentry","category-mq","tag-ibmmq","tag-jms","tag-mqseries","tag-spring","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>MQ JMS and Spring Boot - improved efficiency - Mark Taylor&#039;s Blog<\/title>\n<meta name=\"description\" content=\"The default behaviour of the Spring JMS interface is known to be costly. This post explains improvements to the MQ Spring Boot layer to deal with that.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/marketaylor.synology.me\/?p=668\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MQ JMS and Spring Boot - improved efficiency - Mark Taylor&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"The default behaviour of the Spring JMS interface is known to be costly. This post explains improvements to the MQ Spring Boot layer to deal with that.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/marketaylor.synology.me\/?p=668\" \/>\n<meta property=\"og:site_name\" content=\"Mark Taylor&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-03-27T11:20:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-24T13:44:44+00:00\" \/>\n<meta name=\"author\" content=\"Mark\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@marketaylor\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mark\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668\"},\"author\":{\"name\":\"Mark\",\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/#\\\/schema\\\/person\\\/2d6f4113ff54187023e20c20186bbb3c\"},\"headline\":\"MQ JMS and Spring Boot &#8211; improved efficiency\",\"datePublished\":\"2020-03-27T11:20:56+00:00\",\"dateModified\":\"2025-06-24T13:44:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668\"},\"wordCount\":852,\"commentCount\":6,\"keywords\":[\"ibmmq\",\"jms\",\"mqseries\",\"spring\",\"spring boot\"],\"articleSection\":[\"IBM MQ\"],\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668\",\"url\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668\",\"name\":\"MQ JMS and Spring Boot - improved efficiency - Mark Taylor&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/#website\"},\"datePublished\":\"2020-03-27T11:20:56+00:00\",\"dateModified\":\"2025-06-24T13:44:44+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/#\\\/schema\\\/person\\\/2d6f4113ff54187023e20c20186bbb3c\"},\"description\":\"The default behaviour of the Spring JMS interface is known to be costly. This post explains improvements to the MQ Spring Boot layer to deal with that.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/?p=668#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/marketaylor.synology.me\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"MQ JMS and Spring Boot &#8211; improved efficiency\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/#website\",\"url\":\"https:\\\/\\\/marketaylor.synology.me\\\/\",\"name\":\"Mark Taylor&#039;s Blog\",\"description\":\"Messaging, Music and Moving Around\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/marketaylor.synology.me\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/marketaylor.synology.me\\\/#\\\/schema\\\/person\\\/2d6f4113ff54187023e20c20186bbb3c\",\"name\":\"Mark\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9a5ae091c43730194cba7cabb5d65c1dc3f48d05caaddec6ff2319a1ce66376f?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9a5ae091c43730194cba7cabb5d65c1dc3f48d05caaddec6ff2319a1ce66376f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9a5ae091c43730194cba7cabb5d65c1dc3f48d05caaddec6ff2319a1ce66376f?s=96&d=mm&r=g\",\"caption\":\"Mark\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/marketaylor\"],\"url\":\"https:\\\/\\\/marketaylor.synology.me\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MQ JMS and Spring Boot - improved efficiency - Mark Taylor&#039;s Blog","description":"The default behaviour of the Spring JMS interface is known to be costly. This post explains improvements to the MQ Spring Boot layer to deal with that.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/marketaylor.synology.me\/?p=668","og_locale":"en_GB","og_type":"article","og_title":"MQ JMS and Spring Boot - improved efficiency - Mark Taylor&#039;s Blog","og_description":"The default behaviour of the Spring JMS interface is known to be costly. This post explains improvements to the MQ Spring Boot layer to deal with that.","og_url":"https:\/\/marketaylor.synology.me\/?p=668","og_site_name":"Mark Taylor&#039;s Blog","article_published_time":"2020-03-27T11:20:56+00:00","article_modified_time":"2025-06-24T13:44:44+00:00","author":"Mark","twitter_card":"summary_large_image","twitter_creator":"@marketaylor","twitter_misc":{"Written by":"Mark","Estimated reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/marketaylor.synology.me\/?p=668#article","isPartOf":{"@id":"https:\/\/marketaylor.synology.me\/?p=668"},"author":{"name":"Mark","@id":"https:\/\/marketaylor.synology.me\/#\/schema\/person\/2d6f4113ff54187023e20c20186bbb3c"},"headline":"MQ JMS and Spring Boot &#8211; improved efficiency","datePublished":"2020-03-27T11:20:56+00:00","dateModified":"2025-06-24T13:44:44+00:00","mainEntityOfPage":{"@id":"https:\/\/marketaylor.synology.me\/?p=668"},"wordCount":852,"commentCount":6,"keywords":["ibmmq","jms","mqseries","spring","spring boot"],"articleSection":["IBM MQ"],"inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/marketaylor.synology.me\/?p=668#respond"]}]},{"@type":"WebPage","@id":"https:\/\/marketaylor.synology.me\/?p=668","url":"https:\/\/marketaylor.synology.me\/?p=668","name":"MQ JMS and Spring Boot - improved efficiency - Mark Taylor&#039;s Blog","isPartOf":{"@id":"https:\/\/marketaylor.synology.me\/#website"},"datePublished":"2020-03-27T11:20:56+00:00","dateModified":"2025-06-24T13:44:44+00:00","author":{"@id":"https:\/\/marketaylor.synology.me\/#\/schema\/person\/2d6f4113ff54187023e20c20186bbb3c"},"description":"The default behaviour of the Spring JMS interface is known to be costly. This post explains improvements to the MQ Spring Boot layer to deal with that.","breadcrumb":{"@id":"https:\/\/marketaylor.synology.me\/?p=668#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/marketaylor.synology.me\/?p=668"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/marketaylor.synology.me\/?p=668#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/marketaylor.synology.me\/"},{"@type":"ListItem","position":2,"name":"MQ JMS and Spring Boot &#8211; improved efficiency"}]},{"@type":"WebSite","@id":"https:\/\/marketaylor.synology.me\/#website","url":"https:\/\/marketaylor.synology.me\/","name":"Mark Taylor&#039;s Blog","description":"Messaging, Music and Moving Around","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/marketaylor.synology.me\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/marketaylor.synology.me\/#\/schema\/person\/2d6f4113ff54187023e20c20186bbb3c","name":"Mark","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/9a5ae091c43730194cba7cabb5d65c1dc3f48d05caaddec6ff2319a1ce66376f?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/9a5ae091c43730194cba7cabb5d65c1dc3f48d05caaddec6ff2319a1ce66376f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9a5ae091c43730194cba7cabb5d65c1dc3f48d05caaddec6ff2319a1ce66376f?s=96&d=mm&r=g","caption":"Mark"},"sameAs":["https:\/\/x.com\/marketaylor"],"url":"https:\/\/marketaylor.synology.me\/?author=1"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=\/wp\/v2\/posts\/668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=668"}],"version-history":[{"count":15,"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=\/wp\/v2\/posts\/668\/revisions"}],"predecessor-version":[{"id":1773,"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=\/wp\/v2\/posts\/668\/revisions\/1773"}],"wp:attachment":[{"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marketaylor.synology.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}