diff --git a/build.gradle b/build.gradle index 6bbfdd891c..98bf664661 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ ext { freemarkerVersion = "2.3.28" groovyVersion = "2.5.7" hsqldbVersion = "2.4.1" - jackson2Version = "2.9.8" + jackson2Version = "2.9.9" jettyVersion = "9.4.18.v20190429" junit5Version = "5.4.2" kotlinVersion = "1.3.31" diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java index 707638c9f7..32ed2408ed 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/xml/support/DefaultNamespaceHandlerResolverTests.java @@ -51,7 +51,7 @@ public class DefaultNamespaceHandlerResolverTests { } @Test - public void testNonExistentHandlerClass() throws Exception { + public void testNonExistentHandlerClass() { String mappingPath = "org/springframework/beans/factory/xml/support/nonExistent.properties"; try { new DefaultNamespaceHandlerResolver(getClass().getClassLoader(), mappingPath); @@ -63,29 +63,18 @@ public class DefaultNamespaceHandlerResolverTests { } @Test - public void testResolveInvalidHandler() throws Exception { - String mappingPath = "org/springframework/beans/factory/xml/support/invalid.properties"; - try { - new DefaultNamespaceHandlerResolver(getClass().getClassLoader(), mappingPath); - fail("Should not be able to map a class that doesn't implement NamespaceHandler"); - } - catch (Throwable expected) { - } - } - - @Test - public void testCtorWithNullClassLoaderArgument() throws Exception { + public void testCtorWithNullClassLoaderArgument() { // simply must not bail... new DefaultNamespaceHandlerResolver(null); } @Test(expected = IllegalArgumentException.class) - public void testCtorWithNullClassLoaderArgumentAndNullMappingLocationArgument() throws Exception { + public void testCtorWithNullClassLoaderArgumentAndNullMappingLocationArgument() { new DefaultNamespaceHandlerResolver(null, null); } @Test - public void testCtorWithNonExistentMappingLocationArgument() throws Exception { + public void testCtorWithNonExistentMappingLocationArgument() { // simply must not bail; we don't want non-existent resources to result in an Exception new DefaultNamespaceHandlerResolver(null, "738trbc bobabloobop871"); } diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java b/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java index 0067fcded1..44066ff363 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/SimpleMessageListenerContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,6 +66,8 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta private boolean connectLazily = false; + private boolean recoverOnException = true; + private int concurrentConsumers = 1; @Nullable @@ -94,6 +96,21 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta this.connectLazily = connectLazily; } + /** + * Specify whether to explicitly recover the shared JMS Connection and the + * associated Sessions and MessageConsumers whenever a JMSException is reported. + *

Default is "true": refreshing the shared connection and re-initializing the + * consumers whenever the connection propagates an exception to its listener. + * Set this flag to "false" in order to rely on automatic recovery within the + * provider, holding on to the existing connection and consumer handles. + * @since 5.1.8 + * @see #onException(JMSException) + * @see Connection#setExceptionListener + */ + public void setRecoverOnException(boolean recoverOnException) { + this.recoverOnException = recoverOnException; + } + /** * Specify concurrency limits via a "lower-upper" String, e.g. "5-10", or a simple * upper limit String, e.g. "10". @@ -227,8 +244,11 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta /** * JMS ExceptionListener implementation, invoked by the JMS provider in * case of connection failures. Re-initializes this listener container's - * shared connection and its sessions and consumers. + * shared connection and its sessions and consumers, if necessary. * @param ex the reported connection exception + * @see #setRecoverOnException + * @see #refreshSharedConnection() + * @see #initializeConsumers() */ @Override public void onException(JMSException ex) { @@ -236,21 +256,23 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta invokeExceptionListener(ex); // Now try to recover the shared Connection and all consumers... - if (logger.isDebugEnabled()) { - logger.debug("Trying to recover from JMS Connection exception: " + ex); - } - try { - synchronized (this.consumersMonitor) { - this.sessions = null; - this.consumers = null; + if (this.recoverOnException) { + if (logger.isDebugEnabled()) { + logger.debug("Trying to recover from JMS Connection exception: " + ex); + } + try { + synchronized (this.consumersMonitor) { + this.sessions = null; + this.consumers = null; + } + refreshSharedConnection(); + initializeConsumers(); + logger.debug("Successfully refreshed JMS Connection"); + } + catch (JMSException recoverEx) { + logger.debug("Failed to recover JMS Connection", recoverEx); + logger.error("Encountered non-recoverable JMSException", ex); } - refreshSharedConnection(); - initializeConsumers(); - logger.debug("Successfully refreshed JMS Connection"); - } - catch (JMSException recoverEx) { - logger.debug("Failed to recover JMS Connection", recoverEx); - logger.error("Encountered non-recoverable JMSException", ex); } } diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java index 80f21cfa8b..5730132cf1 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageWriter.java @@ -202,8 +202,8 @@ public class MultipartHttpMessageWriter extends LoggingCodecSupport if (contentType != null) { return MediaType.MULTIPART_FORM_DATA.includes(contentType); } - for (String name : map.keySet()) { - for (Object value : map.get(name)) { + for (List values : map.values()) { + for (Object value : values) { if (value != null && !(value instanceof String)) { return true; } diff --git a/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java index 394b907ef8..d36aed18c5 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java @@ -280,8 +280,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter values : map.values()) { + for (Object value : values) { if (value != null && !(value instanceof String)) { return true; } diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd index a1a62d6bd2..7c6fd031df 100644 --- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd +++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc.xsd @@ -601,8 +601,8 @@