spring-projects-experimental / spring-cloud-square Goto Github PK
View Code? Open in Web Editor NEWSpring Cloud auto-configuration of Retrofit and OkHttp (with Spring Cloud LoadBalancer).
License: Apache License 2.0
Spring Cloud auto-configuration of Retrofit and OkHttp (with Spring Cloud LoadBalancer).
License: Apache License 2.0
Loadbalanced RetrofitClients use the name
property as service id. The name is also used to register the RetrofitClient bean
It is impossible to split a vast server API into multiple, smaller clients.
Describe the solution you'd like
I'd like to create multiple RetrofitClient to use the same load-balanced service. Therefore the @RetrofitClient
annotation should add a serviceId
property, which would be used to create the serviceIdUrl
in the AbstractRetrofitClientFactoryBean
and use the name
as a fallback.
e.g.
@RetrofitClient(name = "customerClient", serviceId = "serverAPI")
@RetrofitClient(name = "accountClient", serviceId = "serverAPI")
Describe alternatives you've considered
As an alternative, the same service must/could be registered under different service ids, but this works only if the app is using a static configuration.
Describe the bug
I'm using both spring-cloud-square-retrofit
and spring-cloud-square-retrofit-core
dependencies. I've declared a Retrofit Converter.Factory
for kotlinx.serialization.
Unfortunately this Converter.Factory
bean is registered together with the SpringConverterFactory
declared in the DefaultRetrofitClientConfiguration
because this bean is declared with @ConditionalOnMissingBean(ConverterFactory.class)
targeting Spring's ConverterFactory
class instead of Retrofit's Converter.Factory
class.
It results in having the SpringConverterFactory
called instead of my custom Retrofit.Factory
Sample
To fix replace @ConditionalOnMissingBean(ConverterFactory.class)
in @ConditionalOnMissingBean(Converter.Factory.class)
in the DefaultRetrofitClientConfiguration
class
Describe the bug
I use spring-cloud-square-retrofit-webclient
as a HTTP request client without spring-cloud-loadbalancer
dependency, and need diffrent WebClient.Builder
beans for diffrent API servers. I found this issue #25 , But it only works with @LoadBalanced
. So I create a PR here #43 to support this.
This sample, that works with Cloud 2020.x
+Boot 2.5.x
, fails to find the WebClient.Builder
instance that is provided in the config while trying to set up load-balancing when run with Cloud 2021.x
+ Boot 2.6.x
. More precisely, this call does not return any WebClient.Builder instance for the HelloServer context with 2021.x
+2.6.x
, while it provides this one with 2020.x
+2.5.x
.
Is your feature request related to a problem? Please describe.
Support for using spring-cloud-square with Project Reactor & Spring Boot
Describe the solution you'd like
I'd like to be able to natively send requests using a Flux
.
Any plans for when FallbackFactory
and circuit breakers
will be added?
Maybe it's done in the retrofit
package?
Is your feature request related to a problem? Please describe.
Support for using spring-cloud-square with DefaultFallBackFactory
Describe the solution you'd like
As you know, when we use spring-cloud-openfeign, we can make a default FallbackFacotry whith feign-hystrix, so that when some
service is unavliable,the fallback method works ,So how should we do when we use spring-cloud-square? Is there some plugin like feign-hystrix or sentinel ?
Hi.
This project will be releasing this year (2021)? or where do you plan to release it? we would like to use it in production environments. We already use Retrofit + Okhttp client on production environments.
Regards.
It would be nice to have the capability to mark generated beans as non-primary.
This would allow for the applications to be able to automatically wire a local implementation of the service and, if non is present, fallback to the Retrofit provider.
This is really useful when building microservice architectures that can also work as modulites, where the client and the server-side implementation may or may not co-exist in the same application depending on the setup.
It might be as simple as changing:
AbstractRetrofitClientsRegistrar#registerRetrofitClient
beanDefinition.setPrimary(true); --> beanDefinition.setPrimary( «config-based-boolean» );
As it is right now, if the application contains an implementation of the service a retrofit client is always loaded regardless.
Cheers
In the documentation of ReactorCallAdapterFactory it states that if you provide a scheduler it will modify the outcome of the request to be executed on a thread managed by the scheduler provided by using publishOn.
I would assume this functionality is added to provide a way for users to get off the netty response thread quickly after returning from webclient where you may potentially do blocking work on the netty response thread downstream as documented on https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-concurrency-model
However in the code it doesnt use publishOn it uses subscribeOn ReactoryCallAdapter which I believe does nothing except moves the subscription to the schedulers thread, than executes the request and afterwards leaves the response to be handled on the netty thread incorrectly.
I believe this should be using publishOn as documented to move the response handling to a thread controlled by the scheduler provided.
Describe the bug
spring-cloud-square-okhttp version 0.4.1
Auto-configuration of the org.springframework.cloud.square.okhttp.tracing.TracingOkHttpInterceptor
only works if the client builder bean has been annotated with @LoadBalanced
: OkHttpBuilderBeanPostProcessor.java#L42
Tracing and load balancing should work independently of each other.
Sample
@Configuration
class SampleContext {
@Bean
@LoadBalanced // Drop the annotation and tracing headers will no longer be added to the request
fun okHttpClientBuilder() : OkHttpClient.Builder = OkHttpClient.Builder()
@Bean
fun okHttpClient(builder: OkHttpClient.Builder): OkHttpClient = builder.build()
}
Describe the bug
Using spring cloud square 0.4.1
When creating an interface for retrofit and declaring a return type which is a parameterized class doesn't allow the application to start due to a ClassCastException in WebClientCallAdapterFactory#81
or, if not wrapping inside a Mono/Flux, WebClientCallAdapterFactory#87
The ReactorCallAdapterFactory used in com.jakewharton.retrofit:retrofit2-reactor-adapter
allows such things, but then we lose the feature of a fully non-blocking client.
Also trying to use spring-cloud-square-retrofit + spring-cloud-square-okhttp does not work in webflux applications since a HttpMessageConverters
bean is not created due to Conditional annotations.
Sample
Just create an application with spring webflux and an interface like the following:
@RetrofitClient(name ="whatever")
public interface MyClient {
@GET("/something")
Flux<MyType<MyObject>> getMyTypeWithMyObject();
}
And include in your pom
Describe the bug
Hi guys, @OlgaMaciaszek
I am trying to use @RetrofitClient with WebClient using the retrofit2 @Multipart
annotation and it is not possible to do it (it is not working)
I am trying with the following Retrofit Client:
@Multipart
@POST("multipart/mono")
fun multipartMono(@Part("file") file: Mono<org.springframework.http.codec.multipart.Part>): Mono<ResponseEntity<String>>
We want to know if there is a bug to use @Multipart
with @RetrofitClient and WebClient or there is not still support for it?
if there is support for it, please can you share the link with the documentation about it?
if there is no support for it, do you have plans to support @Multipart
with @RetrofitClient and WebClient?
I did not find spring documentation about how to create a org.springframework.http.codec.multipart.Part from a File, if there is documentation or examples, can you please share it to me?
Currently it is not documented how to use Multipart + Retrofit + WebClient in the official documentation of spring:
https://spring-projects-experimental.github.io/spring-cloud-square/docs/current/reference/html/index.html
https://github.com/spring-projects-experimental/spring-cloud-square
https://spring.io/blog/2021/04/13/introducing-spring-cloud-square
The examples out there are using Multipart + Retrofit + Okhttp:
https://square.github.io/retrofit/
https://futurestud.io/tutorials/retrofit-2-passing-multiple-parts-along-a-file-with-partmap
https://adinugroho.medium.com/upload-image-from-android-app-using-retrofit-2-ae6f922b184c
https://stackoverflow.com/questions/34562950/post-multipart-form-data-using-retrofit-2-0-including-image
I am looking forward to hearing from you!
Best Regards!
If possible, please provide a test case or sample application that reproduces
the problem. This makes it much easier for us to diagnose the problem and to verify that
we have fixed it.
See: #38 (comment)
Describe the bug
When I set the version to 0.4.0-M2, repositories required to work are milestone & snapshot due library parent pom is:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
**<version>3.1.0-SNAPSHOT</version>**
<relativePath/>
</parent>
Otherwise, libs are not downloaded successfully just using milestones.
The previous version M1 just required a milestone repository. Is this ok?
Regards.
Not sure if this is a bug or a missing feature. The WebClient.Builder
can't be defined in a custom Configuration defined in a child applicationcontext for each RetrofitClient.
Describe the solution you'd like
WebClient.Builder
in a custom Configuration and lookup the bean in the child applicationcontextWebClient.Builder
in multiple RetrofitClientDescribe alternatives you've considered
none
Describe the bug
Please provide details of the problem, including the version of Spring Cloud that you
are using.
Hi guys, @OlgaMaciaszek
I am trying to use @RetrofitClient with WebClient using the @Body annotation for the body, but it is not working.
I am trying with the following Retrofit Client:
@RetrofitClient(name = "HelloServer", url = "http://localhost:7111", configuration = HelloClientConfiguration.class)
public interface HelloClient {
@GET("/")
Mono<String> hello();
@Headers({"Content-Type: application/json"})
@POST("/card")
Mono<Card> create(@Body Card card);
}
I have the following questions:
I would like to know if you have implemented the CallAdapterFactory or ConverterFactory so that the @Body works serializing the object to be set as the request body? We are using the version 0.4.0-M1 of spring-cloud-square-retrofit and the serializing of the Body is not working.
We would like to know if you know about this and how We can do to solve this problem: maybe adding a specific configuration or waiting for the next version of spring-cloud-square?
I am looking forward to hearing from you!
Important: If you need help regarding to this issue, please let me know how I can help you.
Best Regards!
Sample
If possible, please provide a test case or sample application that reproduces
the problem. This makes it much easier for us to diagnose the problem and to verify that
we have fixed it.
Hi guys, @OlgaMaciaszek
I am trying to implement a decorator to ClientHttpRequestDecorator to print some logs using @RetrofitClient @Body with Flux for the request body using WebClient, but it is not working. The method writeWith(body: Publisher) of the decorator is being invoked (actually this method should have been invoked: writeAndFlushWith()) and it doesn't receive correctly the data buffers causing the logs are not printed correctly, only the text {"prefetch":-1} is printed as request body.
I am trying with the following Retrofit Client:
@Headers(*["Content-Type: application/stream+json", "Accept: application/stream+json"])
@Streaming
@POST("cards/search-stream")
fun searchStream(@Body cardsSearchAllRequest: Flux<Card>): Flux<Card>
Note:
The method writeAndFlushWith() is being invoked and works correctly when an http request is invoked directly using WebClient (but We would like to use the component @RetrofitClient
and not just the WebClient directly), like this:
val webClient =
WebClient.builder().baseUrl("http://localhost:8082/support/cards/v1").defaultHeader("Content-Type", "application/stream+json").clientConnector(
DefaultReactorClientHttpConnectorDecorator(
ReactorClientHttpConnector(HttpClient.create()), { -> true}))
.build()
return webClient
.post()
.uri("/cards/search-stream")
.header(org.springframework.http.HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_STREAM_JSON_VALUE)
.header("caller-name", "web-client")
.header("Request-ID", "550e8400-1234-41d4-a716-446655440025")
.body(Flux.just(Card("a", "b"), Card("c", "d"), Card("e", "f"), Card("g", "h")), Card::class.java)
.retrieve()
.bodyToMono(Card::class.java);
We want to know if there is a bug for this scenery or there is not still support for making this type of call: @post call with request @Body Flux using @RetrofitClient(WebClient)?
I am looking forward to hearing from you!
Describe the bug
Hi guys, @OlgaMaciaszek,
at the docs about Retrofit with WebClient you can find information about how to configure a WebClient.Builder
to be used under the hood for the Retrofit clients as shown by the following configuration:
@Configuration
@EnableRetrofitClients
class OkHttpClientConfig {
@Bean
@LoadBalanced
public WebClient.Builder okHttpClientBuilder() {
return WebClient.builder();
}
}
As you can notice, this configuration shows us how to use a shared WebClient.Builder
to be used for all the @RetrofitClient
instances.
I have the following question:
how Can I configure a different WebClient.Builder
for each @RetrofitClient
instance?
Imagine I have two client instances:
@RetrofitClient(name = "Api1Client")
public interface Api1Client {
@GET("/")
Mono<String> hello();
}
and
@RetrofitClient(name = "Api2Client")
public interface Api2Client {
@GET("/")
Mono<String> hello();
}
and I want to configure different timeouts and other properties for each client:
for example for Api1Client I want to configure:
httpClient.tcpConfiguration(tcpClient -> tcpClient
.proxy(proxy -> proxy
.type(ProxyProvider.Proxy.HTTP)
.host("ourproxy.com")
.port(8080)
and for client Api2Client I want to configure:
How can I configure 2 different WebClient Builders, one for Api1Client and other for Api2Client?
Is there a way to specify a different WebClient.Builder
to be used in the @RetrofitClient
?
Please, could you help me with these questions?
Thanks and Regards.
Sample
If possible, please provide a test case or sample application that reproduces
the problem. This makes it much easier for us to diagnose the problem and to verify that
we have fixed it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.