diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java index f0e5438c4..5f9054d9f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.web; import java.lang.invoke.MethodHandles; +import java.util.concurrent.atomic.AtomicReference; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -54,7 +55,7 @@ public class TraceHandlerInterceptor extends HandlerInterceptorAdapter { private Tracer tracer; private TraceKeys traceKeys; - private ErrorController errorController; + private AtomicReference errorController; public TraceHandlerInterceptor(BeanFactory beanFactory) { this.beanFactory = beanFactory; @@ -187,16 +188,19 @@ public class TraceHandlerInterceptor extends HandlerInterceptorAdapter { return this.traceKeys; } - private ErrorController getErrorController() { + ErrorController getErrorController() { if (this.errorController == null) { try { - this.errorController = this.beanFactory.getBean(ErrorController.class); + ErrorController errorController = this.beanFactory.getBean(ErrorController.class); + this.errorController = new AtomicReference<>(errorController); } catch (NoSuchBeanDefinitionException e) { if (log.isTraceEnabled()) { log.trace("ErrorController bean not found"); } + this.errorController = new AtomicReference<>(); } } - return this.errorController; + return this.errorController.get(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptorTests.java index 9130095d9..dc761d7d2 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptorTests.java @@ -16,9 +16,6 @@ package org.springframework.cloud.sleuth.instrument.web; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.BDDMockito; @@ -28,8 +25,10 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.web.ErrorController; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.only; /** * @author Marcin Grzejszczak @@ -41,13 +40,21 @@ public class TraceHandlerInterceptorTests { @InjectMocks TraceHandlerInterceptor traceHandlerInterceptor; @Test - public void should_not_blow_up_when_there_is_no_error_controller() throws Exception { - BDDMockito.given(this.beanFactory.getBean(ErrorController.class)).willThrow(new NoSuchBeanDefinitionException("errorController")); - HttpServletRequest request = new MockHttpServletRequest(); - HttpServletResponse response = new MockHttpServletResponse(); - Object handler = new Object(); + public void should_cache_the_retrieved_bean_when_exception_took_place() throws Exception { + given(this.beanFactory.getBean(ErrorController.class)).willThrow(new NoSuchBeanDefinitionException("errorController")); - this.traceHandlerInterceptor.afterCompletion(request, response, handler, null); + then(this.traceHandlerInterceptor.getErrorController()).isNull(); + then(this.traceHandlerInterceptor.getErrorController()).isNull(); + BDDMockito.then(this.beanFactory).should(only()).getBean(ErrorController.class); + } + + @Test + public void should_cache_the_retrieved_bean_when_no_exception_took_place() throws Exception { + given(this.beanFactory.getBean(ErrorController.class)).willReturn(() -> null); + + then(this.traceHandlerInterceptor.getErrorController()).isNotNull(); + then(this.traceHandlerInterceptor.getErrorController()).isNotNull(); + BDDMockito.then(this.beanFactory).should(only()).getBean(ErrorController.class); } } \ No newline at end of file