From ea5f8f5a7c2ad8053e8cf38fbc3d326abc1d3958 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 17 Jan 2018 20:24:57 +0100 Subject: [PATCH] Consistently handle NoClassDefFoundError in BeanUtils and related places Issue: SPR-16369 --- .../main/java/org/springframework/beans/BeanUtils.java | 10 +++++++--- .../beans/factory/support/AbstractBeanFactory.java | 4 ++-- .../factory/xml/DefaultNamespaceHandlerResolver.java | 10 +++++----- .../main/java/org/springframework/util/ClassUtils.java | 7 +++---- .../reactive/config/WebFluxConfigurationSupport.java | 9 +++------ .../springframework/web/servlet/DispatcherServlet.java | 8 ++++---- .../config/annotation/WebMvcConfigurationSupport.java | 4 ++-- 7 files changed, 26 insertions(+), 26 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java index 1a8d3cfd82..067a4be26b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -107,9 +107,10 @@ public abstract class BeanUtils { * @return the new instance * @throws BeanInstantiationException if the bean cannot be instantiated. * The cause may notably indicate a {@link NoSuchMethodException} if no - * primary/default constructor was found - or an exception thrown from - * the constructor invocation attempt, including a runtime-generated - * {@link NoClassDefFoundError} in case of an unresolvable dependency. + * primary/default constructor was found, a {@link NoClassDefFoundError} + * or other {@link LinkageError} in case of an unresolvable class definition + * (e.g. due to a missing dependency at runtime), or an exception thrown + * from the constructor invocation itself. * @see Constructor#newInstance */ public static T instantiateClass(Class clazz) throws BeanInstantiationException { @@ -125,6 +126,9 @@ public abstract class BeanUtils { catch (NoSuchMethodException ex) { throw new BeanInstantiationException(clazz, "No default constructor found", ex); } + catch (LinkageError err) { + throw new BeanInstantiationException(clazz, "Unresolvable class definition", err); + } } /** diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 7f93df817b..2b6c76eebf 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -1379,8 +1379,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } - catch (LinkageError ex) { - throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); + catch (LinkageError err) { + throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java index cd4a9399af..938e17fe0d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/xml/DefaultNamespaceHandlerResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -137,12 +137,12 @@ public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver return namespaceHandler; } catch (ClassNotFoundException ex) { - throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + - namespaceUri + "] not found", ex); + throw new FatalBeanException("Could not find NamespaceHandler class [" + className + + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageError err) { - throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + - namespaceUri + "]: problem with handler class file or dependent class", err); + throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + + className + "] for namespace [" + namespaceUri + "]", err); } } } diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 14dbb802eb..a000c5b4e5 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -298,11 +298,10 @@ public abstract class ClassUtils { return forName(className, classLoader); } catch (ClassNotFoundException ex) { - throw new IllegalArgumentException("Cannot find class [" + className + "]", ex); + throw new IllegalArgumentException("Could not find class [" + className + "]", ex); } - catch (LinkageError ex) { - throw new IllegalArgumentException( - "Error loading class [" + className + "]: problem with class file or dependent class.", ex); + catch (LinkageError err) { + throw new IllegalArgumentException("Unresolvable class definition for class [" + className + "]", err); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java index ef8a9fab75..eca05af22a 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -355,11 +355,8 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware { String name = "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean"; clazz = ClassUtils.forName(name, getClass().getClassLoader()); } - catch (ClassNotFoundException ex) { - throw new BeanInitializationException("Could not find default validator class", ex); - } - catch (LinkageError ex) { - throw new BeanInitializationException("Could not load default validator class", ex); + catch (ClassNotFoundException | LinkageError ex) { + throw new BeanInitializationException("Failed to resolve default validator class", ex); } validator = (Validator) BeanUtils.instantiateClass(clazz); } 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 9c56dba232..fa2c907f22 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-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -850,12 +850,12 @@ public class DispatcherServlet extends FrameworkServlet { catch (ClassNotFoundException ex) { throw new BeanInitializationException( "Could not find DispatcherServlet's default strategy class [" + className + - "] for interface [" + key + "]", ex); + "] for interface [" + key + "]", ex); } catch (LinkageError err) { throw new BeanInitializationException( - "Error loading DispatcherServlet's default strategy class [" + className + - "] for interface [" + key + "]: problem with class file or dependent class", err); + "Unresolvable class definition for DispatcherServlet's default strategy class [" + + className + "] for interface [" + key + "]", err); } } return strategies; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index 760b30a3d3..7bf0322dcb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -662,7 +662,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv clazz = ClassUtils.forName(className, WebMvcConfigurationSupport.class.getClassLoader()); } catch (ClassNotFoundException | LinkageError ex) { - throw new BeanInitializationException("Could not find default validator class", ex); + throw new BeanInitializationException("Failed to resolve default validator class", ex); } validator = (Validator) BeanUtils.instantiateClass(clazz); }