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