From 4e1b9f14924e14e28176b36c1b9b9cb0b931f65f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 14 Jun 2022 14:00:28 +0200 Subject: [PATCH] Replace deep exception message nesting with custom inclusion of cause messages Includes deprecation of NestedServletException, whereas NestedCheckedException and NestedRuntimeException remain as base classes with several convenience methods. Closes gh-25162 --- .../beans/TypeMismatchException.java | 8 +- .../UnsatisfiedDependencyException.java | 6 +- .../config/PropertyResourceConfigurer.java | 4 +- .../AbstractAutowireCapableBeanFactory.java | 12 +- .../factory/support/ConstructorResolver.java | 6 +- .../support/SimpleInstantiationStrategy.java | 4 +- .../annotation/ConfigurationClassParser.java | 2 +- .../event/EventListenerMethodProcessor.java | 4 +- .../factory/xml/XmlBeanFactoryTests.java | 4 +- .../context/annotation/Spr12278Tests.java | 4 +- .../core/NestedCheckedException.java | 18 --- .../core/NestedExceptionUtils.java | 7 +- .../core/NestedRuntimeException.java | 18 --- .../core/NestedExceptionTests.java | 109 ------------------ .../jms/core/JmsMessagingTemplate.java | 5 +- .../ConnectionFactoryUtilsUnitTests.java | 14 +-- .../xml/AbstractXmlHttpMessageConverter.java | 2 +- .../Jaxb2CollectionHttpMessageConverter.java | 4 +- .../web/ErrorResponseException.java | 5 +- .../bind/ServletRequestBindingException.java | 5 +- .../web/filter/GenericFilterBean.java | 7 +- .../web/server/ResponseStatusException.java | 4 +- .../web/util/NestedServletException.java | 18 +-- .../web/client/RestTemplateTests.java | 6 +- .../web/context/support/Spr8510Tests.java | 12 +- .../web/servlet/DispatcherServlet.java | 7 +- .../web/servlet/FrameworkServlet.java | 5 +- .../ServletInvocableHandlerMethod.java | 6 +- .../servlet/view/groovy/GroovyMarkupView.java | 6 +- ...xceptionHandlerExceptionResolverTests.java | 6 +- .../support/WebSocketHttpRequestHandler.java | 5 +- 31 files changed, 78 insertions(+), 245 deletions(-) delete mode 100644 spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java diff --git a/spring-beans/src/main/java/org/springframework/beans/TypeMismatchException.java b/spring-beans/src/main/java/org/springframework/beans/TypeMismatchException.java index 4a6f52400e..ccfa6a0030 100644 --- a/spring-beans/src/main/java/org/springframework/beans/TypeMismatchException.java +++ b/spring-beans/src/main/java/org/springframework/beans/TypeMismatchException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -71,7 +71,8 @@ public class TypeMismatchException extends PropertyAccessException { (requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : "") + (propertyChangeEvent.getPropertyName() != null ? - " for property '" + propertyChangeEvent.getPropertyName() + "'" : ""), + " for property '" + propertyChangeEvent.getPropertyName() + "'" : "") + + (cause != null ? "; " + cause.getMessage() : ""), cause); this.propertyName = propertyChangeEvent.getPropertyName(); this.value = propertyChangeEvent.getNewValue(); @@ -97,7 +98,8 @@ public class TypeMismatchException extends PropertyAccessException { */ public TypeMismatchException(@Nullable Object value, @Nullable Class requiredType, @Nullable Throwable cause) { super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" + - (requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : ""), + (requiredType != null ? " to required type '" + ClassUtils.getQualifiedName(requiredType) + "'" : "") + + (cause != null ? "; " + cause.getMessage() : ""), cause); this.value = value; this.requiredType = requiredType; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/UnsatisfiedDependencyException.java b/spring-beans/src/main/java/org/springframework/beans/factory/UnsatisfiedDependencyException.java index 8ae820d9ac..29c4b47349 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/UnsatisfiedDependencyException.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/UnsatisfiedDependencyException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -62,7 +62,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException { public UnsatisfiedDependencyException( @Nullable String resourceDescription, @Nullable String beanName, String propertyName, BeansException ex) { - this(resourceDescription, beanName, propertyName, ""); + this(resourceDescription, beanName, propertyName, ex.getMessage()); initCause(ex); } @@ -94,7 +94,7 @@ public class UnsatisfiedDependencyException extends BeanCreationException { public UnsatisfiedDependencyException( @Nullable String resourceDescription, @Nullable String beanName, @Nullable InjectionPoint injectionPoint, BeansException ex) { - this(resourceDescription, beanName, injectionPoint, ""); + this(resourceDescription, beanName, injectionPoint, ex.getMessage()); initCause(ex); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyResourceConfigurer.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyResourceConfigurer.java index ad24226877..d6de515fa3 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyResourceConfigurer.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyResourceConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2022 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. @@ -86,7 +86,7 @@ public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport processProperties(beanFactory, mergedProps); } catch (IOException ex) { - throw new BeanInitializationException("Could not load properties", ex); + throw new BeanInitializationException("Could not load properties: " + ex.getMessage(), ex); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index a05635d1de..b063124ace 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -608,8 +608,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac throw (BeanCreationException) ex; } else { - throw new BeanCreationException( - mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); + throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex); } } @@ -1302,8 +1301,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return bw; } catch (Throwable ex) { - throw new BeanCreationException( - mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); + throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex); } } @@ -1699,8 +1697,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { - throw new BeanCreationException( - mbd.getResourceDescription(), beanName, "Error setting property values", ex); + throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex); } } @@ -1752,8 +1749,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } catch (Throwable ex) { throw new BeanCreationException( - (mbd != null ? mbd.getResourceDescription() : null), - beanName, "Invocation of init method failed", ex); + (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java index d7c4799466..5c33de9c16 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java @@ -303,8 +303,7 @@ class ConstructorResolver { return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse); } catch (Throwable ex) { - throw new BeanCreationException(mbd.getResourceDescription(), beanName, - "Bean instantiation via constructor failed", ex); + throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex); } } @@ -631,8 +630,7 @@ class ConstructorResolver { mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args); } catch (Throwable ex) { - throw new BeanCreationException(mbd.getResourceDescription(), beanName, - "Bean instantiation via factory method failed", ex); + throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java index 0ae2e3a688..ee7b059380 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -152,7 +152,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex); } catch (InvocationTargetException ex) { - String msg = "Factory method '" + factoryMethod.getName() + "' threw exception"; + String msg = ex.getTargetException().getMessage(); if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory && ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) { msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " + diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index 1128cabf84..90aa28fdd6 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -606,7 +606,7 @@ class ConfigurationClassParser { catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + - configClass.getMetadata().getClassName() + "]", ex); + configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex); } finally { this.importStack.pop(); diff --git a/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java b/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java index ad89b9e567..70c302fd02 100644 --- a/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -155,7 +155,7 @@ public class EventListenerMethodProcessor } catch (Throwable ex) { throw new BeanInitializationException("Failed to process @EventListener " + - "annotation on bean with name '" + beanName + "'", ex); + "annotation on bean with name '" + beanName + "': " + ex.getMessage(), ex); } } } diff --git a/spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java b/spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java index 13396f6628..955edca5c5 100644 --- a/spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java +++ b/spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java @@ -944,8 +944,8 @@ class XmlBeanFactoryTests { xbf.getBean("rod2Accessor"); } catch (BeanCreationException ex) { - assertThat(ex.toString().contains("touchy")).isTrue(); ex.printStackTrace(); + assertThat(ex.toString().contains("touchy")).isTrue(); assertThat((Object) ex.getRelatedCauses()).isNull(); } } @@ -1370,7 +1370,7 @@ class XmlBeanFactoryTests { reader.loadBeanDefinitions(INVALID_NO_SUCH_METHOD_CONTEXT); assertThatExceptionOfType(BeanDefinitionStoreException.class).isThrownBy(() -> xbf.getBean("constructorOverrides")) - .withMessageContaining("bogusMethod"); + .satisfies(ex -> ex.getCause().getMessage().contains("bogusMethod")); } @Test diff --git a/spring-context/src/test/java/org/springframework/context/annotation/Spr12278Tests.java b/spring-context/src/test/java/org/springframework/context/annotation/Spr12278Tests.java index c17203dbc1..c56c347b8c 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/Spr12278Tests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/Spr12278Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -56,7 +56,7 @@ public class Spr12278Tests { public void componentTwoSpecificConstructorsNoHint() { assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> new AnnotationConfigApplicationContext(BaseConfiguration.class, TwoSpecificConstructorsComponent.class)) - .withMessageContaining(NoSuchMethodException.class.getName()); + .withMessageContaining("No default constructor found"); } diff --git a/spring-core/src/main/java/org/springframework/core/NestedCheckedException.java b/spring-core/src/main/java/org/springframework/core/NestedCheckedException.java index 9df1a3f537..d737d9a746 100644 --- a/spring-core/src/main/java/org/springframework/core/NestedCheckedException.java +++ b/spring-core/src/main/java/org/springframework/core/NestedCheckedException.java @@ -33,7 +33,6 @@ import org.springframework.lang.Nullable; * @author Rod Johnson * @author Juergen Hoeller * @see #getMessage - * @see #printStackTrace * @see NestedRuntimeException */ public abstract class NestedCheckedException extends Exception { @@ -41,12 +40,6 @@ public abstract class NestedCheckedException extends Exception { /** Use serialVersionUID from Spring 1.2 for interoperability. */ private static final long serialVersionUID = 7100714597678207546L; - static { - // Eagerly load the NestedExceptionUtils class to avoid classloader deadlock - // issues on OSGi when calling getMessage(). Reported by Don Brown; SPR-5607. - NestedExceptionUtils.class.getName(); - } - /** * Construct a {@code NestedCheckedException} with the specified detail message. @@ -67,17 +60,6 @@ public abstract class NestedCheckedException extends Exception { } - /** - * Return the detail message, including the message from the nested exception - * if there is one. - */ - @Override - @Nullable - public String getMessage() { - return NestedExceptionUtils.buildMessage(super.getMessage(), getCause()); - } - - /** * Retrieve the innermost cause of this exception, if any. * @return the innermost exception, or {@code null} if none diff --git a/spring-core/src/main/java/org/springframework/core/NestedExceptionUtils.java b/spring-core/src/main/java/org/springframework/core/NestedExceptionUtils.java index db879c3676..2bac3b6619 100644 --- a/spring-core/src/main/java/org/springframework/core/NestedExceptionUtils.java +++ b/spring-core/src/main/java/org/springframework/core/NestedExceptionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -29,8 +29,6 @@ import org.springframework.lang.Nullable; * @since 2.0 * @see NestedRuntimeException * @see NestedCheckedException - * @see NestedIOException - * @see org.springframework.web.util.NestedServletException */ public abstract class NestedExceptionUtils { @@ -39,7 +37,10 @@ public abstract class NestedExceptionUtils { * @param message the base message * @param cause the root cause * @return the full exception message + * @deprecated as of 6.0, in favor of custom exception messages + * with selective inclusion of cause messages */ + @Deprecated @Nullable public static String buildMessage(@Nullable String message, @Nullable Throwable cause) { if (cause == null) { diff --git a/spring-core/src/main/java/org/springframework/core/NestedRuntimeException.java b/spring-core/src/main/java/org/springframework/core/NestedRuntimeException.java index 2162c8b871..a960a5ecb5 100644 --- a/spring-core/src/main/java/org/springframework/core/NestedRuntimeException.java +++ b/spring-core/src/main/java/org/springframework/core/NestedRuntimeException.java @@ -33,7 +33,6 @@ import org.springframework.lang.Nullable; * @author Rod Johnson * @author Juergen Hoeller * @see #getMessage - * @see #printStackTrace * @see NestedCheckedException */ public abstract class NestedRuntimeException extends RuntimeException { @@ -41,12 +40,6 @@ public abstract class NestedRuntimeException extends RuntimeException { /** Use serialVersionUID from Spring 1.2 for interoperability. */ private static final long serialVersionUID = 5439915454935047936L; - static { - // Eagerly load the NestedExceptionUtils class to avoid classloader deadlock - // issues on OSGi when calling getMessage(). Reported by Don Brown; SPR-5607. - NestedExceptionUtils.class.getName(); - } - /** * Construct a {@code NestedRuntimeException} with the specified detail message. @@ -67,17 +60,6 @@ public abstract class NestedRuntimeException extends RuntimeException { } - /** - * Return the detail message, including the message from the nested exception - * if there is one. - */ - @Override - @Nullable - public String getMessage() { - return NestedExceptionUtils.buildMessage(super.getMessage(), getCause()); - } - - /** * Retrieve the innermost cause of this exception, if any. * @return the innermost exception, or {@code null} if none diff --git a/spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java b/spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java deleted file mode 100644 index 5134ced05c..0000000000 --- a/spring-core/src/test/java/org/springframework/core/NestedExceptionTests.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - */ - -package org.springframework.core; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Rod Johnson - * @author Juergen Hoeller - */ -@SuppressWarnings("serial") -class NestedExceptionTests { - - @Test - void nestedRuntimeExceptionWithNoRootCause() { - String mesg = "mesg of mine"; - // Making a class abstract doesn't _really_ prevent instantiation :-) - NestedRuntimeException nex = new NestedRuntimeException(mesg) {}; - assertThat(nex.getCause()).isNull(); - assertThat(mesg).isEqualTo(nex.getMessage()); - - // Check printStackTrace - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintWriter pw = new PrintWriter(baos); - nex.printStackTrace(pw); - pw.flush(); - String stackTrace = new String(baos.toByteArray()); - assertThat(stackTrace.contains(mesg)).isTrue(); - } - - @Test - void nestedRuntimeExceptionWithRootCause() { - String myMessage = "mesg for this exception"; - String rootCauseMsg = "this is the obscure message of the root cause"; - Exception rootCause = new Exception(rootCauseMsg); - // Making a class abstract doesn't _really_ prevent instantiation :-) - NestedRuntimeException nex = new NestedRuntimeException(myMessage, rootCause) {}; - assertThat(rootCause).isEqualTo(nex.getCause()); - assertThat(nex.getMessage().contains(myMessage)).isTrue(); - assertThat(nex.getMessage().endsWith(rootCauseMsg)).isTrue(); - - // check PrintStackTrace - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintWriter pw = new PrintWriter(baos); - nex.printStackTrace(pw); - pw.flush(); - String stackTrace = new String(baos.toByteArray()); - assertThat(stackTrace.contains(rootCause.getClass().getName())).isTrue(); - assertThat(stackTrace.contains(rootCauseMsg)).isTrue(); - } - - @Test - void nestedCheckedExceptionWithNoRootCause() { - String mesg = "mesg of mine"; - // Making a class abstract doesn't _really_ prevent instantiation :-) - NestedCheckedException nex = new NestedCheckedException(mesg) {}; - assertThat(nex.getCause()).isNull(); - assertThat(mesg).isEqualTo(nex.getMessage()); - - // Check printStackTrace - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintWriter pw = new PrintWriter(baos); - nex.printStackTrace(pw); - pw.flush(); - String stackTrace = new String(baos.toByteArray()); - assertThat(stackTrace.contains(mesg)).isTrue(); - } - - @Test - void nestedCheckedExceptionWithRootCause() { - String myMessage = "mesg for this exception"; - String rootCauseMsg = "this is the obscure message of the root cause"; - Exception rootCause = new Exception(rootCauseMsg); - // Making a class abstract doesn't _really_ prevent instantiation :-) - NestedCheckedException nex = new NestedCheckedException(myMessage, rootCause) {}; - assertThat(rootCause).isEqualTo(nex.getCause()); - assertThat(nex.getMessage().contains(myMessage)).isTrue(); - assertThat(nex.getMessage().endsWith(rootCauseMsg)).isTrue(); - - // check PrintStackTrace - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintWriter pw = new PrintWriter(baos); - nex.printStackTrace(pw); - pw.flush(); - String stackTrace = new String(baos.toByteArray()); - assertThat(stackTrace.contains(rootCause.getClass().getName())).isTrue(); - assertThat(stackTrace.contains(rootCauseMsg)).isTrue(); - } - -} diff --git a/spring-jms/src/main/java/org/springframework/jms/core/JmsMessagingTemplate.java b/spring-jms/src/main/java/org/springframework/jms/core/JmsMessagingTemplate.java index 0835ae2e9b..af7e0e5e24 100644 --- a/spring-jms/src/main/java/org/springframework/jms/core/JmsMessagingTemplate.java +++ b/spring-jms/src/main/java/org/springframework/jms/core/JmsMessagingTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -473,7 +473,8 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate return this.messageConverter.toMessage(this.message, session); } catch (Exception ex) { - throw new MessageConversionException("Could not convert '" + this.message + "'", ex); + throw new MessageConversionException( + "Could not convert '" + this.message + "': " + ex.getMessage(), ex); } } } diff --git a/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/ConnectionFactoryUtilsUnitTests.java b/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/ConnectionFactoryUtilsUnitTests.java index fd976f38f3..ebbf3c370b 100644 --- a/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/ConnectionFactoryUtilsUnitTests.java +++ b/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/ConnectionFactoryUtilsUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2020 the original author or authors. + * Copyright 2019-2022 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. @@ -105,8 +105,7 @@ public class ConnectionFactoryUtilsUnitTests { Exception exception = ConnectionFactoryUtils.convertR2dbcException("TASK", "SOME-SQL", new R2dbcTransientResourceException("MESSAGE")); assertThat(exception).isInstanceOf( - TransientDataAccessResourceException.class).hasMessage( - "TASK; SQL [SOME-SQL]; MESSAGE; nested exception is io.r2dbc.spi.R2dbcTransientResourceException: MESSAGE"); + TransientDataAccessResourceException.class).hasMessage("TASK; SQL [SOME-SQL]; MESSAGE"); } @Test @@ -114,21 +113,20 @@ public class ConnectionFactoryUtilsUnitTests { Exception exception = ConnectionFactoryUtils.convertR2dbcException("TASK", null, new R2dbcTransientResourceException("MESSAGE")); assertThat(exception).isInstanceOf( - TransientDataAccessResourceException.class).hasMessage( - "TASK; MESSAGE; nested exception is io.r2dbc.spi.R2dbcTransientResourceException: MESSAGE"); + TransientDataAccessResourceException.class).hasMessage("TASK; MESSAGE"); } @Test public void messageGenerationNullMessage() { - Exception exception = ConnectionFactoryUtils.convertR2dbcException("TASK", "SOME-SQL", new R2dbcTransientResourceException()); assertThat(exception).isInstanceOf( - TransientDataAccessResourceException.class).hasMessage( - "TASK; SQL [SOME-SQL]; null; nested exception is io.r2dbc.spi.R2dbcTransientResourceException"); + TransientDataAccessResourceException.class).hasMessage("TASK; SQL [SOME-SQL]; null"); } + @SuppressWarnings("serial") private static class MyTransientExceptions extends R2dbcException { } + } diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java index 19d95e4bef..a2443afe29 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java @@ -75,7 +75,7 @@ public abstract class AbstractXmlHttpMessageConverter extends AbstractHttpMes throw ex; } catch (Exception ex) { - throw new HttpMessageNotReadableException("Could not unmarshal to [" + clazz + "]: " + ex.getMessage(), + throw new HttpMessageNotReadableException("Could not unmarshal to [" + clazz + "]: " + ex, ex, inputMessage); } } diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java index e1acb3a833..5730286baf 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -173,7 +173,7 @@ public class Jaxb2CollectionHttpMessageConverter } catch (UnmarshalException ex) { throw new HttpMessageNotReadableException( - "Could not unmarshal to [" + elementClass + "]: " + ex.getMessage(), ex, inputMessage); + "Could not unmarshal to [" + elementClass + "]: " + ex, ex, inputMessage); } catch (JAXBException ex) { throw new HttpMessageConversionException("Invalid JAXB setup: " + ex.getMessage(), ex); diff --git a/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java b/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java index ebd978709b..ea0b78b7c7 100644 --- a/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java +++ b/spring-web/src/main/java/org/springframework/web/ErrorResponseException.java @@ -18,14 +18,12 @@ package org.springframework.web; import java.net.URI; -import org.springframework.core.NestedExceptionUtils; import org.springframework.core.NestedRuntimeException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.lang.Nullable; - /** * {@link RuntimeException} that implements {@link ErrorResponse} to expose * an HTTP status, response headers, and a body formatted as an RFC 7808 @@ -137,8 +135,7 @@ public class ErrorResponseException extends NestedRuntimeException implements Er @Override public String getMessage() { - String message = this.status + (!this.headers.isEmpty() ? ", headers=" + this.headers : "") + ", " + this.body; - return NestedExceptionUtils.buildMessage(message, getCause()); + return this.status + (!this.headers.isEmpty() ? ", headers=" + this.headers : "") + ", " + this.body; } } diff --git a/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java b/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java index 2767f763bf..78297d229a 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java +++ b/spring-web/src/main/java/org/springframework/web/bind/ServletRequestBindingException.java @@ -16,11 +16,12 @@ package org.springframework.web.bind; +import jakarta.servlet.ServletException; + import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; import org.springframework.http.ProblemDetail; import org.springframework.web.ErrorResponse; -import org.springframework.web.util.NestedServletException; /** * Fatal binding exception, thrown when we want to @@ -34,7 +35,7 @@ import org.springframework.web.util.NestedServletException; * @author Juergen Hoeller */ @SuppressWarnings("serial") -public class ServletRequestBindingException extends NestedServletException implements ErrorResponse { +public class ServletRequestBindingException extends ServletException implements ErrorResponse { private final ProblemDetail body = ProblemDetail.forStatus(getStatusCode()); diff --git a/spring-web/src/main/java/org/springframework/web/filter/GenericFilterBean.java b/spring-web/src/main/java/org/springframework/web/filter/GenericFilterBean.java index f9c79d6bff..6936a66c6b 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/GenericFilterBean.java +++ b/spring-web/src/main/java/org/springframework/web/filter/GenericFilterBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -49,7 +49,6 @@ import org.springframework.util.StringUtils; import org.springframework.web.context.ServletContextAware; import org.springframework.web.context.support.ServletContextResourceLoader; import org.springframework.web.context.support.StandardServletEnvironment; -import org.springframework.web.util.NestedServletException; /** * Simple base implementation of {@link jakarta.servlet.Filter} which treats @@ -228,9 +227,9 @@ public abstract class GenericFilterBean implements Filter, BeanNameAware, Enviro } catch (BeansException ex) { String msg = "Failed to set bean properties on filter '" + - filterConfig.getFilterName() + "': " + ex.getMessage(); + filterConfig.getFilterName() + "': " + ex.getMessage(); logger.error(msg, ex); - throw new NestedServletException(msg, ex); + throw new ServletException(msg, ex); } } diff --git a/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java b/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java index 50b9a6c41b..143a6613fb 100644 --- a/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java +++ b/spring-web/src/main/java/org/springframework/web/server/ResponseStatusException.java @@ -16,7 +16,6 @@ package org.springframework.web.server; -import org.springframework.core.NestedExceptionUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatusCode; import org.springframework.lang.Nullable; @@ -112,8 +111,7 @@ public class ResponseStatusException extends ErrorResponseException { @Override public String getMessage() { - String msg = getStatusCode() + (this.reason != null ? " \"" + this.reason + "\"" : ""); - return NestedExceptionUtils.buildMessage(msg, getCause()); + return getStatusCode() + (this.reason != null ? " \"" + this.reason + "\"" : ""); } } diff --git a/spring-web/src/main/java/org/springframework/web/util/NestedServletException.java b/spring-web/src/main/java/org/springframework/web/util/NestedServletException.java index 08fc49bbea..6cd9489506 100644 --- a/spring-web/src/main/java/org/springframework/web/util/NestedServletException.java +++ b/spring-web/src/main/java/org/springframework/web/util/NestedServletException.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -37,10 +37,11 @@ import org.springframework.lang.Nullable; * @author Juergen Hoeller * @since 1.2.5 * @see #getMessage - * @see #printStackTrace * @see org.springframework.core.NestedCheckedException * @see org.springframework.core.NestedRuntimeException + * @deprecated as of 6.0, in favor of standard {@link ServletException} nesting */ +@Deprecated public class NestedServletException extends ServletException { /** Use serialVersionUID from Spring 1.2 for interoperability. */ @@ -68,18 +69,7 @@ public class NestedServletException extends ServletException { * @param cause the nested exception */ public NestedServletException(@Nullable String msg, @Nullable Throwable cause) { - super(msg, cause); - } - - - /** - * Return the detail message, including the message from the nested exception - * if there is one. - */ - @Override - @Nullable - public String getMessage() { - return NestedExceptionUtils.buildMessage(super.getMessage(), getCause()); + super(NestedExceptionUtils.buildMessage(msg, cause), cause); } } diff --git a/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java b/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java index 8124c4a800..58f0678eab 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java @@ -598,8 +598,7 @@ class RestTemplateTests { assertThatExceptionOfType(ResourceAccessException.class).isThrownBy(() -> template.getForObject(url, String.class)) - .withMessage("I/O error on GET request for \"https://example.com/resource\": " + - "Socket failure; nested exception is java.io.IOException: Socket failure"); + .withMessage("I/O error on GET request for \"https://example.com/resource\": Socket failure"); } @Test // SPR-15900 @@ -615,8 +614,7 @@ class RestTemplateTests { assertThatExceptionOfType(ResourceAccessException.class).isThrownBy(() -> template.getForObject(uri, String.class)) - .withMessage("I/O error on GET request for \"https://example.com/resource\": " + - "Socket failure; nested exception is java.io.IOException: Socket failure"); + .withMessage("I/O error on GET request for \"https://example.com/resource\": Socket failure"); } @Test diff --git a/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java b/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java index 85b7e70f09..13a2b425a8 100644 --- a/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java +++ b/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -47,7 +47,7 @@ public class Spr8510Tests { assertThatExceptionOfType(Throwable.class).isThrownBy(() -> cll.contextInitialized(new ServletContextEvent(sc))) - .withMessageEndingWith("Could not open ServletContext resource [/programmatic.xml]"); + .withMessageEndingWith("ServletContext resource [/programmatic.xml]"); } /** @@ -68,7 +68,7 @@ public class Spr8510Tests { assertThatExceptionOfType(Throwable.class).isThrownBy(() -> cll.contextInitialized(new ServletContextEvent(sc))) - .withMessageEndingWith("Could not open ServletContext resource [/from-init-param.xml]"); + .withMessageEndingWith("ServletContext resource [/from-init-param.xml]"); } /** @@ -86,7 +86,7 @@ public class Spr8510Tests { assertThatExceptionOfType(Throwable.class).isThrownBy(() -> cll.contextInitialized(new ServletContextEvent(sc))) - .withMessageEndingWith("Could not open ServletContext resource [/from-init-param.xml]"); + .withMessageEndingWith("ServletContext resource [/from-init-param.xml]"); } /** @@ -108,7 +108,7 @@ public class Spr8510Tests { assertThatExceptionOfType(Throwable.class).isThrownBy(() -> cll.contextInitialized(new ServletContextEvent(sc))) - .withMessageEndingWith("Could not open ServletContext resource [/from-init-param.xml]"); + .withMessageEndingWith("ServletContext resource [/from-init-param.xml]"); } /** @@ -127,7 +127,7 @@ public class Spr8510Tests { assertThatExceptionOfType(Throwable.class).isThrownBy(() -> cll.contextInitialized(new ServletContextEvent(sc))) - .withMessageEndingWith("Could not open ServletContext resource [/WEB-INF/applicationContext.xml]"); + .withMessageEndingWith("ServletContext resource [/WEB-INF/applicationContext.xml]"); } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index 91eb62a12d..de8ad303d9 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -62,7 +62,6 @@ import org.springframework.web.context.request.async.WebAsyncUtils; import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartResolver; -import org.springframework.web.util.NestedServletException; import org.springframework.web.util.ServletRequestPathUtils; import org.springframework.web.util.WebUtils; @@ -1077,7 +1076,7 @@ public class DispatcherServlet extends FrameworkServlet { catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. - dispatchException = new NestedServletException("Handler dispatch failed", err); + dispatchException = new ServletException("Handler dispatch failed: " + err, err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } @@ -1086,7 +1085,7 @@ public class DispatcherServlet extends FrameworkServlet { } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, - new NestedServletException("Handler processing failed", err)); + new ServletException("Handler processing failed: " + err, err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java index 7759527b26..8f5ddaff4a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/FrameworkServlet.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -68,7 +68,6 @@ import org.springframework.web.context.support.ServletRequestHandledEvent; import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.web.cors.CorsUtils; -import org.springframework.web.util.NestedServletException; import org.springframework.web.util.WebUtils; /** @@ -1009,7 +1008,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic } catch (Throwable ex) { failureCause = ex; - throw new NestedServletException("Request processing failed", ex); + throw new ServletException("Request processing failed: " + ex, ex); } finally { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java index eca685048d..7f106c08f2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ServletInvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -22,6 +22,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.concurrent.Callable; +import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -44,7 +45,6 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandlerCom import org.springframework.web.method.support.InvocableHandlerMethod; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.View; -import org.springframework.web.util.NestedServletException; /** * Extends {@link InvocableHandlerMethod} with the ability to handle return @@ -220,7 +220,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod { throw (Exception) result; } else if (result instanceof Throwable) { - throw new NestedServletException("Async processing failed", (Throwable) result); + throw new ServletException("Async processing failed: " + result, (Throwable) result); } return result; }, CALLABLE_METHOD); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java index e91c0f8220..7ef2500f93 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/groovy/GroovyMarkupView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2022 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. @@ -23,6 +23,7 @@ import java.util.Map; import groovy.text.Template; import groovy.text.markup.MarkupTemplateEngine; +import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -34,7 +35,6 @@ import org.springframework.context.ApplicationContextException; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.servlet.view.AbstractTemplateView; -import org.springframework.web.util.NestedServletException; /** * An {@link AbstractTemplateView} subclass based on Groovy XML/XHTML markup templates. @@ -133,7 +133,7 @@ public class GroovyMarkupView extends AbstractTemplateView { } catch (ClassNotFoundException ex) { Throwable cause = (ex.getCause() != null ? ex.getCause() : ex); - throw new NestedServletException( + throw new ServletException( "Could not find class while rendering Groovy Markup view with name '" + getUrl() + "': " + ex.getMessage() + "'", cause); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java index 90c9d2513b..42b86b9b90 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -23,6 +23,7 @@ import java.net.SocketTimeoutException; import java.util.Collections; import java.util.Locale; +import jakarta.servlet.ServletException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -61,7 +62,6 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import org.springframework.web.testfixture.servlet.MockHttpServletResponse; -import org.springframework.web.util.NestedServletException; import static org.assertj.core.api.Assertions.assertThat; @@ -315,7 +315,7 @@ public class ExceptionHandlerExceptionResolverTests { AssertionError err = new AssertionError("argh"); HandlerMethod handlerMethod = new HandlerMethod(new ResponseBodyController(), "handle"); ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerMethod, - new NestedServletException("Handler dispatch failed", err)); + new ServletException("Handler dispatch failed", err)); assertThat(mav).as("Exception was not handled").isNotNull(); assertThat(mav.isEmpty()).isTrue(); diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/server/support/WebSocketHttpRequestHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/server/support/WebSocketHttpRequestHandler.java index 997c547b44..1d238281e3 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/server/support/WebSocketHttpRequestHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/server/support/WebSocketHttpRequestHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -181,7 +181,8 @@ public class WebSocketHttpRequestHandler implements HttpRequestHandler, Lifecycl failure = ex; } catch (Exception ex) { - failure = new HandshakeFailureException("Uncaught failure for request " + request.getURI(), ex); + failure = new HandshakeFailureException( + "Uncaught failure for request " + request.getURI() + " - " + ex.getMessage(), ex); } finally { if (failure != null) {