Skip to content

Use object provider for LoadBalancerRestClientPostProcessor #1366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* @author Will Tran
* @author Gang Li
* @author Olga Maciaszek-Sharma
* @author Henning Pöttker
*/
@AutoConfiguration
@Conditional(BlockingRestClassesPresentCondition.class)
Expand Down Expand Up @@ -86,17 +87,18 @@ static class DeferringLoadBalancerInterceptorConfig {

@Bean
@ConditionalOnMissingBean
public DeferringLoadBalancerInterceptor deferringLoadBalancerInterceptor(
public static DeferringLoadBalancerInterceptor deferringLoadBalancerInterceptor(
ObjectProvider<BlockingLoadBalancerInterceptor> loadBalancerInterceptorObjectProvider) {
return new DeferringLoadBalancerInterceptor(loadBalancerInterceptorObjectProvider);
}

@Bean
@ConditionalOnBean(DeferringLoadBalancerInterceptor.class)
@ConditionalOnMissingBean
LoadBalancerRestClientBuilderBeanPostProcessor lbRestClientPostProcessor(
DeferringLoadBalancerInterceptor loadBalancerInterceptor, ApplicationContext context) {
return new LoadBalancerRestClientBuilderBeanPostProcessor(loadBalancerInterceptor, context);
@ConditionalOnMissingBean(LoadBalancerRestClientBuilderBeanPostProcessor.class)
static LoadBalancerRestClientBuilderBeanPostProcessor<DeferringLoadBalancerInterceptor> lbRestClientPostProcessor(
ObjectProvider<DeferringLoadBalancerInterceptor> loadBalancerInterceptorProvider,
ApplicationContext context) {
return new LoadBalancerRestClientBuilderBeanPostProcessor<>(loadBalancerInterceptorProvider, context);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.cloud.client.loadbalancer;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.http.client.ClientHttpRequestInterceptor;
Expand All @@ -29,15 +30,21 @@
* @author Olga Maciaszek-Sharma
* @since 4.1.0
*/
public class LoadBalancerRestClientBuilderBeanPostProcessor implements BeanPostProcessor {
public class LoadBalancerRestClientBuilderBeanPostProcessor<T extends ClientHttpRequestInterceptor>
implements BeanPostProcessor {

private final ClientHttpRequestInterceptor loadBalancerInterceptor;
private final ObjectProvider<T> loadBalancerInterceptorProvider;

private final ApplicationContext context;

public LoadBalancerRestClientBuilderBeanPostProcessor(ClientHttpRequestInterceptor loadBalancerInterceptor,
public LoadBalancerRestClientBuilderBeanPostProcessor(T loadBalancerInterceptor, ApplicationContext context) {
this.loadBalancerInterceptorProvider = new SimpleObjectProvider<>(loadBalancerInterceptor);
this.context = context;
}

public LoadBalancerRestClientBuilderBeanPostProcessor(ObjectProvider<T> loadBalancerInterceptorProvider,
ApplicationContext context) {
this.loadBalancerInterceptor = loadBalancerInterceptor;
this.loadBalancerInterceptorProvider = loadBalancerInterceptorProvider;
this.context = context;
}

Expand All @@ -47,7 +54,11 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
if (context.findAnnotationOnBean(beanName, LoadBalanced.class) == null) {
return bean;
}
((RestClient.Builder) bean).requestInterceptor(loadBalancerInterceptor);
ClientHttpRequestInterceptor interceptor = loadBalancerInterceptorProvider.getIfAvailable();
if (interceptor == null) {
throw new IllegalStateException(ClientHttpRequestInterceptor.class.getSimpleName() + " not available.");
}
((RestClient.Builder) bean).requestInterceptor(interceptor);
}
return bean;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2012-2024 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
*
* https://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.client.loadbalancer;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerWebClientBuilderBeanPostProcessor;

/**
* Wrapper for {@link ObjectProvider}. Added to use for a workaround in
* {@link LoadBalancerWebClientBuilderBeanPostProcessor}.
*
* @param <T> type of the object to fetch
* @author Spencer Gibb
* @deprecated for removal in 4.0
*/
@Deprecated(forRemoval = true)
public class SimpleObjectProvider<T> implements ObjectProvider<T> {

private final T object;

public SimpleObjectProvider(T object) {
this.object = object;
}

@Override
public T getObject(Object... args) throws BeansException {
return this.object;
}

@Override
public T getIfAvailable() throws BeansException {
return this.object;
}

@Override
public T getIfUnique() throws BeansException {
return this.object;
}

@Override
public T getObject() throws BeansException {
return this.object;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2024 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.
Expand Down Expand Up @@ -55,7 +55,7 @@ void tryResolveDelegate() {
if (delegate == null) {
delegate = exchangeFilterFunctionProvider.getIfAvailable();
if (delegate == null) {
throw new IllegalStateException("ReactorLoadBalancerExchangeFilterFunction not available.");
throw new IllegalStateException("LoadBalancer ExchangeFilterFunction not available.");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2024 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.
Expand Down Expand Up @@ -39,16 +39,19 @@
* beans.
*
* @author Olga Maciaszek-Sharma
* @author Henning Pöttker
* @since 2.2.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(WebClient.class)
@Conditional(LoadBalancerBeanPostProcessorAutoConfiguration.OnAnyLoadBalancerImplementationPresentCondition.class)
public class LoadBalancerBeanPostProcessorAutoConfiguration {

@SuppressWarnings("rawtypes")
@Bean
public LoadBalancerWebClientBuilderBeanPostProcessor loadBalancerWebClientBuilderBeanPostProcessor(
DeferringLoadBalancerExchangeFilterFunction deferringExchangeFilterFunction, ApplicationContext context) {
public static LoadBalancerWebClientBuilderBeanPostProcessor loadBalancerWebClientBuilderBeanPostProcessor(
ObjectProvider<DeferringLoadBalancerExchangeFilterFunction> deferringExchangeFilterFunction,
ApplicationContext context) {
return new LoadBalancerWebClientBuilderBeanPostProcessor(deferringExchangeFilterFunction, context);
}

Expand All @@ -58,7 +61,7 @@ protected static class ReactorDeferringLoadBalancerFilterConfig {

@Bean
@Primary
DeferringLoadBalancerExchangeFilterFunction<LoadBalancedExchangeFilterFunction> reactorDeferringLoadBalancerExchangeFilterFunction(
static DeferringLoadBalancerExchangeFilterFunction<LoadBalancedExchangeFilterFunction> reactorDeferringLoadBalancerExchangeFilterFunction(
ObjectProvider<LoadBalancedExchangeFilterFunction> exchangeFilterFunctionProvider) {
return new DeferringLoadBalancerExchangeFilterFunction<>(exchangeFilterFunctionProvider);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2024 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.
Expand All @@ -17,8 +17,10 @@
package org.springframework.cloud.client.loadbalancer.reactive;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.SimpleObjectProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.web.reactive.function.client.WebClient;

Expand All @@ -30,15 +32,28 @@
* @author Olga Maciaszek-Sharma
* @since 2.2.0
*/
@SuppressWarnings({ "removal", "rawtypes" })
public class LoadBalancerWebClientBuilderBeanPostProcessor implements BeanPostProcessor {

private final DeferringLoadBalancerExchangeFilterFunction exchangeFilterFunction;
private final ObjectProvider<DeferringLoadBalancerExchangeFilterFunction> exchangeFilterFunctionObjectProvider;

private final ApplicationContext context;

/**
* @deprecated in favour of
* {@link LoadBalancerWebClientBuilderBeanPostProcessor#LoadBalancerWebClientBuilderBeanPostProcessor(ObjectProvider, ApplicationContext)}
*/
@Deprecated(forRemoval = true)
public LoadBalancerWebClientBuilderBeanPostProcessor(
DeferringLoadBalancerExchangeFilterFunction exchangeFilterFunction, ApplicationContext context) {
this.exchangeFilterFunction = exchangeFilterFunction;
this.exchangeFilterFunctionObjectProvider = new SimpleObjectProvider<>(exchangeFilterFunction);
this.context = context;
}

public LoadBalancerWebClientBuilderBeanPostProcessor(
ObjectProvider<DeferringLoadBalancerExchangeFilterFunction> exchangeFilterFunction,
ApplicationContext context) {
this.exchangeFilterFunctionObjectProvider = exchangeFilterFunction;
this.context = context;
}

Expand All @@ -48,7 +63,12 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
if (context.findAnnotationOnBean(beanName, LoadBalanced.class) == null) {
return bean;
}
((WebClient.Builder) bean).filter(exchangeFilterFunction);
DeferringLoadBalancerExchangeFilterFunction exchangeFilterFunction = exchangeFilterFunctionObjectProvider
.getIfAvailable();
if (exchangeFilterFunction == null) {
throw new IllegalStateException("LoadBalancerExchangeFilterFunction not found");
}
((WebClient.Builder) bean).filter(exchangeFilterFunctionObjectProvider.getIfAvailable());
}
return bean;
}
Expand Down