- Notifications
You must be signed in to change notification settings - Fork 38.9k
Description
when a PropertyBatchUpdateException gets instantiated it does not pass the PropertyAccessExceptions as cause to its super (BeansException), instead storing it locally in propertyAccessExceptions:
Lines 48 to 56 in a63c5ad
| /** | |
| * Create a new PropertyBatchUpdateException. | |
| * @param propertyAccessExceptions the List of PropertyAccessExceptions | |
| */ | |
| public PropertyBatchUpdateException(PropertyAccessException[] propertyAccessExceptions) { | |
| super(null, null); | |
| Assert.notEmpty(propertyAccessExceptions, "At least 1 PropertyAccessException required"); | |
| this.propertyAccessExceptions = propertyAccessExceptions; | |
| } |
this makes sense since propertyAccessExceptions is a list while cause can only be a single exception.
however, the output of this is really nondescript and does not contain the actual root cause:
Error creating bean with name 'exampleRepository' defined in org.example.repository.exampleRepository defined in @EnableElasticsearchRepositories declared on OpenSearchConfiguration: Failed properties: Property 'elasticsearchOperations' threw exception org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exampleRepository' defined in org.example.repository.exampleRepository defined in @EnableElasticsearchRepositories declared on OpenSearchConfiguration: Failed properties: Property 'elasticsearchOperations' threw exception at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1746) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1460) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) at app//org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339) at app//org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:346) at app//org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337) at app//org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.instantiateSingleton(DefaultListableBeanFactory.java:1149) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingleton(DefaultListableBeanFactory.java:1121) at app//org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:1056) at app//org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:987) at app//org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:627) at app//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) at app//org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) at app//org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) at app//org.springframework.boot.SpringApplication.run(SpringApplication.java:318) at app//org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137) at app//org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58) at app//org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46) at app//org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1461) at app//org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553) at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137) at app//org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108) at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225) at app//org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152) at app//org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130) at app//org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener.injectFields(BeanOverrideTestExecutionListener.java:93) at app//org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener.prepareTestInstance(BeanOverrideTestExecutionListener.java:64) at app//org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260) at app//org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:160) at java.base@21.0.5/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) at java.base@21.0.5/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base@21.0.5/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) at java.base@21.0.5/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base@21.0.5/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708) at java.base@21.0.5/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) at java.base@21.0.5/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base@21.0.5/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.base@21.0.5/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.base@21.0.5/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base@21.0.5/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) at java.base@21.0.5/java.util.Optional.orElseGet(Optional.java:364) at java.base@21.0.5/java.util.ArrayList.forEach(ArrayList.java:1596) Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'elasticsearchOperations' threw exception at app//org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:135) at app//org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:79) at app//org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1743) ... 43 more as you can see it includes PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'elasticsearchOperations' threw exception which comes from its name:
spring-framework/spring-beans/src/main/java/org/springframework/beans/MethodInvocationException.java
Line 44 in a63c5ad
| super(propertyChangeEvent, "Property '" + propertyChangeEvent.getPropertyName() + "' threw exception", cause); |
however it doesn't say what that exception (i.e. its cause) is. it has a cause set (i checked with the debugger), it's just a matter of also printing it. i presume the formatting for printing is done by PropertyBatchUpdateException#toString:
Lines 96 to 106 in a63c5ad
| @Override | |
| public String toString() { | |
| StringBuilder sb = new StringBuilder(); | |
| sb.append(getClass().getName()).append("; nested PropertyAccessExceptions ("); | |
| sb.append(getExceptionCount()).append(") are:"); | |
| for (int i = 0; i < this.propertyAccessExceptions.length; i++) { | |
| sb.append('\n').append("PropertyAccessException ").append(i + 1).append(": "); | |
| sb.append(this.propertyAccessExceptions[i]); | |
| } | |
| return sb.toString(); | |
| } |
it seems that the standard
PropertyAccessException#toString does not include the cause, so maybe that needs to be handled by PropertyBatchUpdateException#toString? (i didn't create a minimum repro for this as i think the affected code is quite obvious from the callstacks & source links provided)