Support @Beans for Partitioning Properties

Fixed support for partition properties to be Spring configured

- Fixed support for 'partitionKeyExtractor' and 'partitionSelector' to be Spring configured
- Added new producer properties 'partitionKeyExtractorName' and 'partitionSelectorName'
- Deprecated 'partitionKeyExtractorClass' and 'partitionSelectorClass' properties
- Removed InitilaizingBean from MessageConverterConfigurer
- Updated documentation
- Added additional tests
- Removed PartitionedProducerTest  as redundant
- Fixed unrelated to this effort BinderPropertiesTests due to recent Boot changes

polishing
This commit is contained in:
Oleg Zhurakousky
2018-01-16 12:13:41 -05:00
committed by Gary Russell
parent b3d5c4f518
commit 00748985d6
9 changed files with 319 additions and 172 deletions

View File

@@ -2028,7 +2028,8 @@ In a scaled-up scenario, correct configuration of these two properties is import
==== Configuring Output Bindings for Partitioning
An output binding is configured to send partitioned data by setting one and only one of its `partitionKeyExpression` or `partitionKeyExtractorClass` properties, as well as its `partitionCount` property.
An output binding is configured to send partitioned data by setting one and only one of its `partitionKeyExpression` or `partitionKeyExtractorName` (see next paragraph) properties, as well as its `partitionCount` property.
For example, the following is a valid and typical configuration:
----
@@ -2042,37 +2043,35 @@ A partition key's value is calculated for each message sent to a partitioned out
The `partitionKeyExpression` is a SpEL expression which is evaluated against the outbound message for extracting the partitioning key.
If a SpEL expression is not sufficient for your needs, you can instead calculate the partition key value by setting the property `partitionKeyExtractorClass` to a class which implements the `org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy` interface.
While the SpEL expression should usually suffice, more complex cases may use the custom implementation strategy.
In that case, the property 'partitionKeyExtractorClass' can be set as follows:
If a SpEL expression is not sufficient for your needs, you can instead calculate the partition key value by providing implementation of `org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy` and configuring it as a bean (i.e., `@Bean`). In the event you have more then one bean of type `org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy` available in the Application Context you can further filter it by specifying its name via `partitionKeyExtractorName` property:
----
spring.cloud.stream.bindings.output.producer.partitionKeyExtractorClass=com.example.MyKeyExtractor
spring.cloud.stream.bindings.output.producer.partitionCount=5
----
Once the message key is calculated, the partition selection process will determine the target partition as a value between `0` and `partitionCount - 1`.
The default calculation, applicable in most scenarios, is based on the formula `key.hashCode() % partitionCount`.
This can be customized on the binding, either by setting a SpEL expression to be evaluated against the 'key' (via the `partitionSelectorExpression` property) or by setting a `org.springframework.cloud.stream.binder.PartitionSelectorStrategy` implementation (via the `partitionSelectorClass` property).
The binding level properties for 'partitionSelectorExpression' and 'partitionSelectorClass' can be specified similar to the way 'partitionKeyExpression' and 'partitionKeyExtractorClass' properties are specified in the above examples.
Additional properties can be configured for more advanced scenarios, as described in the following section.
===== Spring-managed custom `PartitionKeyExtractorClass` implementations
In the example above, a custom strategy such as `MyKeyExtractor` is instantiated by the Spring Cloud Stream directly.
In some cases, it is necessary for such a custom strategy implementation to be created as a Spring bean, for being able to be managed by Spring, so that it can perform dependency injection, property binding, etc.
This can be done by configuring it as a @Bean in the application context and using the fully qualified class name as the bean's name, as in the following example.
----
@Bean(name="com.example.MyKeyExtractor")
public MyKeyExtractor extractor() {
return new MyKeyExtractor();
--spring.cloud.stream.bindings.output.producer.partitionKeyExtractorName=customPartitionKeyExtractor
--spring.cloud.stream.bindings.output.producer.partitionCount=5
. . .
@Bean
public CustomPartitionKeyExtractorClass customPartitionKeyExtractor() {
return new CustomPartitionKeyExtractorClass();
}
----
As a Spring bean, the custom strategy benefits from the full lifecycle of a Spring bean.
For example, if the implementation need access to the application context directly, it can make implement 'ApplicationContextAware'.
NOTE: In previous versions of Spring Cloud Stream you could specify the implementation of `org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy` as `spring.cloud.stream.bindings.output.producer.partitionKeyExtractorClass` property. Since version 2.0 this property is deprecated and support for it will be removed in a future version.
Once the message key is calculated, the partition selection process will determine the target partition as a value between `0` and `partitionCount - 1`.
The default calculation, applicable in most scenarios, is based on the formula `key.hashCode() % partitionCount`.
This can be customized on the binding, either by setting a SpEL expression to be evaluated against the 'key' (via the `partitionSelectorExpression` property) or by configuring an implementation of `org.springframework.cloud.stream.binder.PartitionSelectorStrategy` as a bean (i.e., @Bean). And similarly to the `PartitionKeyExtractorStrategy` you can further filter it using `spring.cloud.stream.bindings.output.producer.partitionSelectorName` property in the event there are more then one bean of this type is available in the Application Context.
----
--spring.cloud.stream.bindings.output.producer.partitionSelectorName=customPartitionSelector
. . .
@Bean
public CustomPartitionSelectorClass customPartitionSelector() {
return new CustomPartitionSelectorClass();
}
----
NOTE: In previous versions of Spring Cloud Stream you could specify the implementation of `org.springframework.cloud.stream.binder.PartitionSelectorStrategy` as `spring.cloud.stream.bindings.output.producer.partitionSelectorClass` property. Since version 2.0 this property is deprecated and support for it will be removed in a future version.
===== Configuring Input Bindings for Partitioning