spring-cloud-aws
spring-cloud-aws copied to clipboard
Make AwsClientCustomizer Flexible
Type: Feature
Is your feature request related to a problem? Please describe.
Imagine a developer wants to add a single request interceptor to a specific client. If I understand the whole thing correctly, the only way to do this is to create an AwsClientCustomizer
bean that returns a ClientOverrideConfiguration
instance in which the interceptor is added. This is a bit sub-optimal. The ClientOverrideConfiguration
(COC) is huge one and I don't feel comfortable overriding the original instance (considering the fact that COC instance returned by the customizer replaces the original instance). Looking at the implementation, at least in AWSpring case, the COC instance is not an empty one, which means if I inject my bean, I have to duplicate the logic in SpringCloudClientConfiguration
.
Describe the solution you'd like
I think it makes sense to have more granular customizers, instead of a big fat one providing COC. (I'm fine with the rest of the existing customizer which are merely providers.)
Another alternative is to expect a Consumer<ClientOverrideConfiguration.Builder>
instead of a ready-to-use instance of COC
. A less optimal solution is to considering user-defined beans of type request interceptors.
Another totally different approach would be to expose the client builder in the customizer.
Describe alternatives you've considered
Right now I override the SesClient
to get access to the client builder to inject my interceptor.
Let me know if you need more information.
Sounds reasonable. Can you provide some code samples how this API would be used (without implementing it yet)?
Random ideas:
- Add
overrideConfigurationBuilder
method toAwsClientCustomizer
interface. The question is what to do withoverrideConfiguration
method? - Accept a
Consumer<ClientOverrideConfiguration.Builder>
bean while building the configuration instance.
I think I'd go with the first one since it's consistent with what we already have in AwsClientCustomizer
.
Hey @akefirad ,
I am not sure I am following the question. By AWS docs:
Configuration values for which the client already provides sensible defaults. All values are optional, and not specifying them will use optimal values defined by the service itself. Use builder() to create a set of options.
Meaning if you add an interceptor and do not touch other values they should be a default, just like when you just do Client.build().
Inside of SpringCloudClientConfiguration
we have the method clientOverrideConfiguration
. We can make this method return ClientOverrideConfiguration.Builder
instead of ClientOverrideConfiguration
.
Then you could use something like:
@Bean
AwsClientCustomizer<SnsClientBuilder> snsClientBuilderAwsClientConfigurer() {
return new CustomAwsClientConfig.SnsAwsClientConfigurer();
}
class SnsAwsClientConfigurer implements AwsClientCustomizer<SnsClientBuilder> {
@Override
@Nullable
public ClientOverrideConfiguration overrideConfiguration() {
return new SpringCloudClientConfiguration().clientOverrideConfiguration().apiCallTimeout(Duration.ofMillis(1999)).build();
}
}
}
Almost there 🙂, it's should be like this:
@Bean
fun sesClientCustomizer(): AwsClientCustomizer<SesClientBuilder> = object : AwsClientCustomizer<SesClientBuilder> {
// Refactor when awspring/spring-cloud-aws/#562 is fixed!
override fun overrideConfiguration(): ClientOverrideConfiguration {
return SpringCloudClientConfiguration()
.clientOverrideConfiguration()
.toBuilder() // COC is immutable!
.apiCallTimeout(Duration.ofMillis(1999))
.build()
}
}
In fact, that's what actually I'm doing right now. So yes, it's not a blocker right now.
Apart from "being a bit hacky (to my eyes)" and code duplication, the fact that I need to instantiate a third party class to just get an instance of an AWS class feels a bit sub-optimal. The developer needs to just add an interface, why does she need to know about SpringCloudClientConfiguration
at all? Does that make sense?
Makes sense, maybe we should apply:
SpringCloudClientConfiguration
.putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, getUserAgent());
inside of AwsClientCustomizer
and with your approach then we can combine it. This of course means it will be
ClientOverrideConfiguration.Builder
instead of ClientOverrideConfiguration
.
This way it is hidden from the user but it is always applied.
This issue should simplify #199 .
Let me know if you need help with the implementation.
Hey @akefirad , the contribution is welcome! :) Do you want me to assign you?
Sure.