From 68dc29a0edb41618d6f13f661274c1ee25c93fae Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 14 Feb 2018 17:58:54 +0100 Subject: [PATCH] wrapping all rest templates via BPP; fixes gh-846 --- .../TraceWebClientAutoConfiguration.java | 50 +++++++---- .../instrument/web/client/GH846Test.java | 85 +++++++++++++++++++ 2 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java index 4ea1c6bc1..4255b8b86 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java @@ -18,12 +18,9 @@ package org.springframework.cloud.sleuth.instrument.web.client; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import javax.annotation.PostConstruct; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -37,7 +34,6 @@ import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.web.HttpSpanInjector; import org.springframework.cloud.sleuth.instrument.web.HttpTraceKeysInjector; import org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -72,9 +68,6 @@ public class TraceWebClientAutoConfiguration { @Configuration protected static class TraceInterceptorConfiguration { - @Autowired - private ApplicationContext applicationContext; - @Autowired private TraceRestTemplateInterceptor traceRestTemplateInterceptor; @@ -84,15 +77,9 @@ public class TraceWebClientAutoConfiguration { return new TraceRestTemplateCustomizer(this.traceRestTemplateInterceptor); } - @PostConstruct - public void init() { - Map restTemplates = BeanFactoryUtils - .beansOfTypeIncludingAncestors(this.applicationContext, - RestTemplate.class); - for (RestTemplate restTemplate : restTemplates.values()) { - new RestTemplateInterceptorInjector( - this.traceRestTemplateInterceptor).inject(restTemplate); - } + @Bean + TraceRestTemplateBPP traceRestTemplateBPP(BeanFactory beanFactory) { + return new TraceRestTemplateBPP(beanFactory); } } @@ -183,6 +170,37 @@ class TraceRestTemplateCustomizer implements RestTemplateCustomizer { } } +class TraceRestTemplateBPP implements BeanPostProcessor { + + private final BeanFactory beanFactory; + private TraceRestTemplateInterceptor interceptor; + + TraceRestTemplateBPP(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + @Override public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + @Override public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (bean instanceof RestTemplate) { + RestTemplate rt = (RestTemplate) bean; + new RestTemplateInterceptorInjector(interceptor()).inject(rt); + } + return bean; + } + + private TraceRestTemplateInterceptor interceptor() { + if (this.interceptor == null) { + this.interceptor = this.beanFactory.getBean(TraceRestTemplateInterceptor.class); + } + return this.interceptor; + } +} + class TraceUserInfoRestTemplateCustomizer implements UserInfoRestTemplateCustomizer { private final BeanFactory beanFactory; diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java new file mode 100644 index 000000000..9944ad5a5 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013-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. + * You may obtain a copy of the License at + * + * http://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.cloud.sleuth.instrument.web.client; + +import javax.annotation.PostConstruct; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestTemplate; + +@SpringBootTest(classes = GH846Test.App.class, webEnvironment=WebEnvironment.NONE) +@RunWith(SpringRunner.class) +public class GH846Test { + + @Autowired + private MyBean myBean; + + @Test + public void doit() throws Exception { + int count = myBean.listAndCount(); + Assert.assertEquals("Change detected in RestTemplate interceptor *after* @PostConstruct", count, myBean.getCountAtPostConstruct()); + } + + @EnableAutoConfiguration + @Configuration + static class App { + @Bean + public RestTemplate myRestTemplate() { + return new RestTemplate(); + } + + @Bean + public MyBean myBean() { + return new MyBean(); + } + } + + + static class MyBean { + @Autowired + private RestTemplate restTemplate; + + /** Number of interceptors registered in the RestTemplate during @PostConstruct */ + private int countAtPostConstruct; + + @PostConstruct + public void init() { + countAtPostConstruct = listAndCount(); + } + + public int listAndCount() { + for(ClientHttpRequestInterceptor interceptor: restTemplate.getInterceptors()) { + System.out.println(interceptor); + } + return restTemplate.getInterceptors().size(); + } + + public int getCountAtPostConstruct() { + return countAtPostConstruct; + } + } +}