Defensive PersistenceExceptionTranslator bean retrieval on shutdown
Closes gh-33067
This commit is contained in:
parent
203fa75196
commit
65dbfd09b4
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2023 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,6 +20,7 @@ import org.aopalliance.intercept.MethodInterceptor;
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.BeanCreationNotAllowedException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
@ -146,7 +147,14 @@ public class PersistenceExceptionTranslationInterceptor
|
||||||
if (translator == null) {
|
if (translator == null) {
|
||||||
Assert.state(this.beanFactory != null,
|
Assert.state(this.beanFactory != null,
|
||||||
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
|
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
|
||||||
translator = detectPersistenceExceptionTranslators(this.beanFactory);
|
try {
|
||||||
|
translator = detectPersistenceExceptionTranslators(this.beanFactory);
|
||||||
|
}
|
||||||
|
catch (BeanCreationNotAllowedException ex2) {
|
||||||
|
// Cannot create PersistenceExceptionTranslator bean on shutdown:
|
||||||
|
// fall back to rethrowing original exception without translation
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
this.persistenceExceptionTranslator = translator;
|
this.persistenceExceptionTranslator = translator;
|
||||||
}
|
}
|
||||||
throw DataAccessUtils.translateIfNecessary(ex, translator);
|
throw DataAccessUtils.translateIfNecessary(ex, translator);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.dao.annotation;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -29,6 +30,7 @@ import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.dao.support.ChainedPersistenceExceptionTranslator;
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
|
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
|
||||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
@ -78,10 +80,37 @@ class PersistenceExceptionTranslationInterceptorTests extends PersistenceExcepti
|
||||||
given(invocation.proceed()).willThrow(exception);
|
given(invocation.proceed()).willThrow(exception);
|
||||||
|
|
||||||
assertThatThrownBy(() -> interceptor.invoke(invocation)).isSameAs(exception);
|
assertThatThrownBy(() -> interceptor.invoke(invocation)).isSameAs(exception);
|
||||||
|
|
||||||
assertThat(callOrder).containsExactly(10, 20, 30);
|
assertThat(callOrder).containsExactly(10, 20, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void detectPersistenceExceptionTranslatorsOnShutdown() throws Throwable {
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
bf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
|
||||||
|
bf.registerBeanDefinition("peti", new RootBeanDefinition(PersistenceExceptionTranslationInterceptor.class));
|
||||||
|
bf.registerBeanDefinition("pet", new RootBeanDefinition(ChainedPersistenceExceptionTranslator.class));
|
||||||
|
|
||||||
|
PersistenceExceptionTranslationInterceptor interceptor =
|
||||||
|
bf.getBean("peti", PersistenceExceptionTranslationInterceptor.class);
|
||||||
|
interceptor.setAlwaysTranslate(true);
|
||||||
|
|
||||||
|
RuntimeException exception = new RuntimeException();
|
||||||
|
MethodInvocation invocation = mock();
|
||||||
|
given(invocation.proceed()).willThrow(exception);
|
||||||
|
|
||||||
|
AtomicBoolean correctException = new AtomicBoolean(false);
|
||||||
|
bf.registerDisposableBean("disposable", () -> {
|
||||||
|
try {
|
||||||
|
interceptor.invoke(invocation);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
correctException.set(ex == exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bf.destroySingletons();
|
||||||
|
assertThat(correctException).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class CallOrderAwareExceptionTranslator implements PersistenceExceptionTranslator, Ordered {
|
private static class CallOrderAwareExceptionTranslator implements PersistenceExceptionTranslator, Ordered {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue