Fix all trailing whitespace
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
To build the source you will need to install JDK {jdkversion}.
|
||||
|
||||
The build uses the Maven wrapper so you don't have to install a specific
|
||||
version of Maven. To enable the tests for Redis, Rabbit, and Kafka bindings you
|
||||
version of Maven. To enable the tests for Redis, Rabbit, and Kafka bindings you
|
||||
should have those servers running before building. See below for more
|
||||
information on running the servers.
|
||||
|
||||
|
||||
@@ -39,4 +39,4 @@ added after the original pull request but before a merge.
|
||||
other target branch in the main project).
|
||||
* When writing a commit message please follow http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions],
|
||||
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
|
||||
message (where XXXX is the issue number).
|
||||
message (where XXXX is the issue number).
|
||||
|
||||
@@ -21,7 +21,7 @@ Sabby Anandan; Marius Bogoevici; Eric Bottard; Mark Fisher; Ilayaperumal Gopinat
|
||||
:sc-ext: java
|
||||
// ======================================================================================
|
||||
|
||||
= Preface
|
||||
= Preface
|
||||
include::preface.adoc[]
|
||||
|
||||
= Reference Guide
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
|
||||
You can try Spring Cloud Stream in less then 5 min even before you jump into any details and the following _three-step guide_ will help.
|
||||
|
||||
We'll create a simple Spring Cloud Stream application which receives messages coming from the messaging middleware of your choice (more on this later) and
|
||||
logs received messages to the console. We'll call it _LoggingConsumer_. While not very practical it will certainly provide a good introduction to some of the main concepts
|
||||
We'll create a simple Spring Cloud Stream application which receives messages coming from the messaging middleware of your choice (more on this later) and
|
||||
logs received messages to the console. We'll call it _LoggingConsumer_. While not very practical it will certainly provide a good introduction to some of the main concepts
|
||||
and abstractions, making it easier to digest the rest of this user guide.
|
||||
|
||||
So let's get started. . .
|
||||
|
||||
==== Step One - Create sample Application using Spring Initilaizer
|
||||
Visit the https://start.spring.io[Spring Initializr]. This is where we'll generate our _LoggingConsumer_ application.
|
||||
==== Step One - Create sample Application using Spring Initilaizer
|
||||
Visit the https://start.spring.io[Spring Initializr]. This is where we'll generate our _LoggingConsumer_ application.
|
||||
|
||||
In the _Dependencies_ start typing 'stream' and _Cloud Stream_ option should pop up. Select it. Now start typing either 'kafka' or 'rabbit'. Basically this is where you are choosing
|
||||
In the _Dependencies_ start typing 'stream' and _Cloud Stream_ option should pop up. Select it. Now start typing either 'kafka' or 'rabbit'. Basically this is where you are choosing
|
||||
what messaging midleware this application will be bound to. Choose the one you have already installed and/or feel more comfortable with installing/running.
|
||||
Also, as you can see from the Initilaizer screen there are few other options you can choose. For example, you can choose Gradle as your build tool instead of the default Maven.
|
||||
With the _Dependencies_ selected the only other thing you have to identify is the application name - _logging-consumer_.
|
||||
@@ -31,7 +31,7 @@ Here you simply import the project into your IDE of choice.
|
||||
Please keep in mind that dependening on the IDE you may need to follow a specific import procedures. For example depending on how the project was generated (Maven or Gradle)
|
||||
you may need to follow specific import procedure (e.g., in Eclipse/STS: `File -> Import -> Maven -> Existing Maven Project`).
|
||||
|
||||
Ones imported the project must have no errors of any kind and `src/main/java` should also contain `com.example.loggingconsumer.LoggingConsumerApplication`.
|
||||
Ones imported the project must have no errors of any kind and `src/main/java` should also contain `com.example.loggingconsumer.LoggingConsumerApplication`.
|
||||
|
||||
Technically at this point you can just run the application's main class since it's already a valid _Spring Boot_ application, but it does not do anything, so let's add some code.
|
||||
|
||||
@@ -70,13 +70,13 @@ public class LoggingConsumerApplication {
|
||||
|
||||
As you can see from the above:
|
||||
|
||||
* We've enabled `Sink` binding (input-no-output) via `@EnableBinding(Sink.class)`. This will signal to the framework to initiate binding to the messaging middleware where
|
||||
* We've enabled `Sink` binding (input-no-output) via `@EnableBinding(Sink.class)`. This will signal to the framework to initiate binding to the messaging middleware where
|
||||
it will auto-create the destination (i.e., queue, topic) which will be bound to `Sink.INPUT` channel.
|
||||
* We've added handler method to receive incoming Message as type `Person`. What this means is that here youcan already observe one of the core features of the framework where
|
||||
it will attempt to automatically convert incoming message's payload to type `Person`.
|
||||
|
||||
This is it, we now have a fully functional Spring Cloud Stream application that does something. From here for simplicity we'll assume RabbitMQ was selected in _step one_.
|
||||
Assuming you have RabbitMQ installed and running, start the application by simply running its `main` method.
|
||||
Assuming you have RabbitMQ installed and running, start the application by simply running its `main` method.
|
||||
|
||||
You should see following output:
|
||||
|
||||
@@ -88,8 +88,8 @@ You should see following output:
|
||||
. . .
|
||||
--- [ main] c.e.l.LoggingConsumerApplication : Started LoggingConsumerApplication in 2.531 seconds (JVM running for 2.897)
|
||||
|
||||
Go to RabbitMQ management console or any other RabbitMQ client and simply send message to `input.anonymous.CbMIwdkJSBO1ZoPDOtHtCg`
|
||||
(NOTE: the `anonymous.CbMIwdkJSBO1ZoPDOtHtCg` part represents the group name and is generated and will be different in your environment. For something more
|
||||
Go to RabbitMQ management console or any other RabbitMQ client and simply send message to `input.anonymous.CbMIwdkJSBO1ZoPDOtHtCg`
|
||||
(NOTE: the `anonymous.CbMIwdkJSBO1ZoPDOtHtCg` part represents the group name and is generated and will be different in your environment. For something more
|
||||
predictable you can use explicit group name via `spring.cloud.stream.bindings.input.group=hello`).
|
||||
|
||||
The contents of the message should be JSON representation of `Person` class, so let's send this:
|
||||
@@ -105,7 +105,7 @@ You can also build/package your application into a boot jar (i.e., `./mvnw clean
|
||||
That is all!
|
||||
|
||||
== What's New in 2.0?
|
||||
Spring Cloud Stream introduces quite a number of new features, enhancements and changes. The following sections outline most notable ones.
|
||||
Spring Cloud Stream introduces quite a number of new features, enhancements and changes. The following sections outline most notable ones.
|
||||
|
||||
=== New Features and Components
|
||||
|
||||
@@ -122,14 +122,14 @@ Please refer to the appropriate section for more details
|
||||
There are now new new Actuator binding controls to both visualize as well as control Bindings lifecycle. For more details please visit <<Binding visualization and control>>
|
||||
|
||||
==== Configurable RetryTemplate
|
||||
Aside from providing properties to configure `RetryTemplate` we now allow you to provide your own effectively overriding the one provided by the framework. Simply configure
|
||||
Aside from providing properties to configure `RetryTemplate` we now allow you to provide your own effectively overriding the one provided by the framework. Simply configure
|
||||
it as a `@Bean` in your application.
|
||||
|
||||
=== Notable changes and enhancements
|
||||
=== Notable changes and enhancements
|
||||
|
||||
==== Both Actuator and Web dependencies are now optional
|
||||
|
||||
This helps to slim down the footprint of the deployed application in the event neither of the functionality is required.
|
||||
This helps to slim down the footprint of the deployed application in the event neither of the functionality is required.
|
||||
It also allows one to swicth between the reactive and conventional web paradigms by adding one of the following dependencies manually:
|
||||
[source,xml]
|
||||
----
|
||||
@@ -165,21 +165,21 @@ https://spring.io/blog/2018/02/26/spring-cloud-stream-2-0-content-type-negotiati
|
||||
* Introduction of `@StreamMessageConverter` annotation to provide custom `MessageConverters`.
|
||||
* Introduction of the default _Content Type_ as `application/json` which needs to be taken into consideration when migrating 1.3
|
||||
application and/or operating in the mixed mode (i.e., 1.3 producer -> 2.0 consumer).
|
||||
* Messages with textual payloads and _contentType_ `text/...` or `.../json` are no longer converted to `Message<String>` for cases where argument type of the provided `MessageHandler`
|
||||
can not be determnied (i.e., `public void handle(Message<?> message)` or `public void handle(Object payload)`). Further more, a strong argument type may not be enough
|
||||
* Messages with textual payloads and _contentType_ `text/...` or `.../json` are no longer converted to `Message<String>` for cases where argument type of the provided `MessageHandler`
|
||||
can not be determnied (i.e., `public void handle(Message<?> message)` or `public void handle(Object payload)`). Further more, a strong argument type may not be enough
|
||||
to properly convert messages, so `contentType` header is may be used as supplement by some `MessageConverters`.
|
||||
|
||||
=== Notable Deprecations
|
||||
==== Java serialization (Java native and Kryo)
|
||||
* `JavaSerializationMessageConverter` and `KryoMessageConverter`. While these two converters remain for now, they will be moved out of the core packages and support in the future.
|
||||
The main reason for this deprecation is to signal the issue _type-based language-specific_ serialization couuld cause in the distributed environments, where Producers and Consumers
|
||||
may not only depend on different JVM versions or have different versions of supporting libraries (i.e., Kryo), but to also draw the attention to the fact that Consumers and Producers
|
||||
may not only depend on different JVM versions or have different versions of supporting libraries (i.e., Kryo), but to also draw the attention to the fact that Consumers and Producers
|
||||
may and in a lot of cases are non-Java based.
|
||||
|
||||
==== Deprecated classes and methods
|
||||
Following is a quick summary of notable deprecations. See corresponding javadocs fort more details.
|
||||
|
||||
* `SharedChannelRegistry` in favor of `SharedBindingTargetRegistry`.
|
||||
* `SharedChannelRegistry` in favor of `SharedBindingTargetRegistry`.
|
||||
* `Bindings` - beans qualified by it are already uniquely identified by their type. For example, provided `Source`, `Processor` or custom bindings:
|
||||
[source,java]
|
||||
----
|
||||
|
||||
@@ -1196,7 +1196,7 @@ http://<host>:<port>/actuator/bindings/myBindingName
|
||||
|
||||
...if you want to visualize a single binding named 'myBindingName'
|
||||
|
||||
You can also _stop, start, pause_ and _resume_ individual binding by posting to the same URL while providing `state` argument as JSON.
|
||||
You can also _stop, start, pause_ and _resume_ individual binding by posting to the same URL while providing `state` argument as JSON.
|
||||
|
||||
For example,
|
||||
----
|
||||
@@ -1207,8 +1207,8 @@ curl -d '{"state":"RESUMED"}' -H "Content-Type: application/json" -X POST http:/
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
_PAUSED_ and _RESUMED_ are only effective if corresponding binder and its underlyig technology supports it, otherwise you'll see the warning message in the logs.
|
||||
====
|
||||
_PAUSED_ and _RESUMED_ are only effective if corresponding binder and its underlyig technology supports it, otherwise you'll see the warning message in the logs.
|
||||
Currently only Kafka binder supports _PAUSED_ and _RESUMED_ state.
|
||||
====
|
||||
|
||||
@@ -1557,26 +1557,26 @@ NOTE: If you need to support dynamic destinations with multiple binder types, us
|
||||
|
||||
=== Introduction
|
||||
|
||||
Data transformation is one of the core features of any message-driven microservice architecture. Given that in Spring Cloud Stream, such data
|
||||
Data transformation is one of the core features of any message-driven microservice architecture. Given that in Spring Cloud Stream, such data
|
||||
is represented as a Spring `Message`, such message may have to be transformed to a desired shape/size before reaching its destination. This is required for two reasons:
|
||||
|
||||
_1. To convert the contents of the incoming message to match the signature of the application-provided handler._
|
||||
|
||||
_2. To convert the contents of the outgoing message to the wire format._
|
||||
|
||||
The wire format is typically `byte[]` (i.e., Kafka and Rabbit binders), but is governed by the binder implementation.
|
||||
The wire format is typically `byte[]` (i.e., Kafka and Rabbit binders), but is governed by the binder implementation.
|
||||
|
||||
In Spring Cloud Stream, message transformation is accomplished with a `org.springframework.messaging.converter.MessageConverter`.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
As a supplement to the details to follow you may also want to read the following
|
||||
As a supplement to the details to follow you may also want to read the following
|
||||
https://spring.io/blog/2018/02/26/spring-cloud-stream-2-0-content-type-negotiation-and-transformation[blog]
|
||||
====
|
||||
|
||||
=== Mechanics
|
||||
|
||||
To better understand the mechanics and the necessity behind content-type negotiation let’s look at the very simple use case using the following message
|
||||
To better understand the mechanics and the necessity behind content-type negotiation let’s look at the very simple use case using the following message
|
||||
handler as an example. Also let’s assume that this is the only handler in the application (no internal pipeline) for simplicity.
|
||||
|
||||
[source, java]
|
||||
@@ -1586,35 +1586,35 @@ handler as an example. Also let’s assume that this is the only handler in the
|
||||
public String handle(Person person) {..}
|
||||
----
|
||||
|
||||
The above handler expects `Person` type as an argument and will produce `String` type as an output. In order for the framework to succeed in passing the incoming
|
||||
`Message` as an argument to this handler it has to somehow transform the payload of the `Message` from the wire format to `Person` type.
|
||||
In other words the framework must locate and apply the appropriate `MessageConverter`. To accomplish that the framework needs some instructions
|
||||
from the user. One of these instructions is already provided by the signature of the handler method itself (`Person` type), so in theory, that should and in some
|
||||
cases is enough, but for the majority of the use cases in order to select the appropriate `MessageConverter` the framework needs an additional piece of information.
|
||||
The above handler expects `Person` type as an argument and will produce `String` type as an output. In order for the framework to succeed in passing the incoming
|
||||
`Message` as an argument to this handler it has to somehow transform the payload of the `Message` from the wire format to `Person` type.
|
||||
In other words the framework must locate and apply the appropriate `MessageConverter`. To accomplish that the framework needs some instructions
|
||||
from the user. One of these instructions is already provided by the signature of the handler method itself (`Person` type), so in theory, that should and in some
|
||||
cases is enough, but for the majority of the use cases in order to select the appropriate `MessageConverter` the framework needs an additional piece of information.
|
||||
That missing piece is `contentType`.
|
||||
|
||||
Spring Cloud Stream provides three simple mechanisms to define `contentType` and they all come with precedence order:
|
||||
|
||||
_1. ***HEADER*** - the `contentType` can be communicated through the Message itself. By simply providing `contentType` header you are declaring the content type to use to locate and
|
||||
_1. ***HEADER*** - the `contentType` can be communicated through the Message itself. By simply providing `contentType` header you are declaring the content type to use to locate and
|
||||
apply the appropriate MessageConverter._
|
||||
|
||||
_2. ***BINDING*** - the `contentType` can be set per destination binding via `spring.cloud.stream.bindings.input.content-type` property. NOTE: the segment `input` in the property name
|
||||
corresponds to the actual name of the destination which is “input” in our case. This approach allows one to declare per-binding the content type to use to locate and
|
||||
_2. ***BINDING*** - the `contentType` can be set per destination binding via `spring.cloud.stream.bindings.input.content-type` property. NOTE: the segment `input` in the property name
|
||||
corresponds to the actual name of the destination which is “input” in our case. This approach allows one to declare per-binding the content type to use to locate and
|
||||
apply the appropriate MessageConverter._
|
||||
|
||||
_3. ***DEFAULT*** - in the event `contentType` is not present in the Message header and/or binding, the default `application/json` content type will be used to
|
||||
_3. ***DEFAULT*** - in the event `contentType` is not present in the Message header and/or binding, the default `application/json` content type will be used to
|
||||
locate and apply the appropriate MessageConverter._
|
||||
|
||||
As mentioned, the above also demonstrates the order of precedence in the event there is a tie. For example, header provided content type takes precedence over any other content type.
|
||||
As mentioned, the above also demonstrates the order of precedence in the event there is a tie. For example, header provided content type takes precedence over any other content type.
|
||||
The same applies for content type set per binding which essentially allows one to override the default content type. But it also provides a sensible default which was determined from
|
||||
the community feedback.
|
||||
|
||||
Another reason for making `application/json` the default stems from the interoperability requirements driven by distributed microservices architectures where producer and consumer not only
|
||||
Another reason for making `application/json` the default stems from the interoperability requirements driven by distributed microservices architectures where producer and consumer not only
|
||||
run in different JVMs, but can also run on different non-JVM platforms.
|
||||
|
||||
Once the non-void handler method returns and unless the return value is already a `Message`, the new `Message` is constructed with return vlaue as the payload while inheriting
|
||||
headers from the input `Message` less the ones defined/filtered by `SpringIntegrationProperties.messageHandlerNotPropagatedHeaders`.
|
||||
By default, there is only one header set there - `contentType`. This means that the new `Message` will not have `contentType` header set, thus ensuring that the `contentType`
|
||||
Once the non-void handler method returns and unless the return value is already a `Message`, the new `Message` is constructed with return vlaue as the payload while inheriting
|
||||
headers from the input `Message` less the ones defined/filtered by `SpringIntegrationProperties.messageHandlerNotPropagatedHeaders`.
|
||||
By default, there is only one header set there - `contentType`. This means that the new `Message` will not have `contentType` header set, thus ensuring that the `contentType`
|
||||
can evolve. You can always opt out to returning a `Message` from the handler method where you can inject any header you wish.
|
||||
|
||||
If there is an internal pipeline the `Message` is sent to the next handler going through the same process of conversion, or if there is no internal
|
||||
@@ -1622,24 +1622,24 @@ If there is an internal pipeline the `Message` is sent to the next handler going
|
||||
|
||||
==== Content type vs. argument type
|
||||
|
||||
As it was mentioned, for the framework to select the appropriate MessageConverter it requires _argument type_ and optionally _content type_ information.
|
||||
The logic for selecting the appropriate `MessageConverter` resides with the argument resolvers (`HandlerMethodArgumentResolvers`), right before the invocation of the user
|
||||
defined handler method (that is when the actual argument type is known to the framework).
|
||||
If argument type does NOT match the type of the current payload the framework delegates to the stack of the
|
||||
pre-configured `MessageConverters` to see if any one of them can convert the payload. As you can see the `Object fromMessage(Message<?> message, Class<?> targetClass);`
|
||||
operation of the MessageConverter takes `targetClass` as one of its arguments. The framework also ensures that the provided `Message` always contains `contentType` header
|
||||
in the event one was not there already (injects the default one or the one set per binding).
|
||||
That is the mechanism by which framework determines if message can be converted to a target type - `contentType` and argumenyt type.
|
||||
As it was mentioned, for the framework to select the appropriate MessageConverter it requires _argument type_ and optionally _content type_ information.
|
||||
The logic for selecting the appropriate `MessageConverter` resides with the argument resolvers (`HandlerMethodArgumentResolvers`), right before the invocation of the user
|
||||
defined handler method (that is when the actual argument type is known to the framework).
|
||||
If argument type does NOT match the type of the current payload the framework delegates to the stack of the
|
||||
pre-configured `MessageConverters` to see if any one of them can convert the payload. As you can see the `Object fromMessage(Message<?> message, Class<?> targetClass);`
|
||||
operation of the MessageConverter takes `targetClass` as one of its arguments. The framework also ensures that the provided `Message` always contains `contentType` header
|
||||
in the event one was not there already (injects the default one or the one set per binding).
|
||||
That is the mechanism by which framework determines if message can be converted to a target type - `contentType` and argumenyt type.
|
||||
If no appropriate `MessageConverter` is found the exception is thrown at which time you can add custom `MessageConverter` (more on this later).
|
||||
|
||||
But what if the payload type matches the target type declared by the handler method? In this cases there is obviously nothing to convert and the
|
||||
payload will be passed unmodified. While this sounds pretty straight forward and logical, keep in mind handler methods that take `Message<?>` and/or `Object` as an
|
||||
But what if the payload type matches the target type declared by the handler method? In this cases there is obviously nothing to convert and the
|
||||
payload will be passed unmodified. While this sounds pretty straight forward and logical, keep in mind handler methods that take `Message<?>` and/or `Object` as an
|
||||
argument. By doing so you are essentially forfeiting the conversion process by declaring the target type to be `Object` which is an `instanceof` everything in Java.
|
||||
|
||||
In other words:
|
||||
[NOTE]
|
||||
====
|
||||
Do NOT expect Message to be converted into some type based on the `contentType` only. Remember that the `contentType` is complimentary to the target type.
|
||||
Do NOT expect Message to be converted into some type based on the `contentType` only. Remember that the `contentType` is complimentary to the target type.
|
||||
A hint if you wish which `MessageConverter` may or may not take into consideration.
|
||||
====
|
||||
|
||||
@@ -1655,12 +1655,12 @@ Object fromMessage(Message<?> message, Class<?> targetClass);
|
||||
Message<?> toMessage(Object payload, @Nullable MessageHeaders headers);
|
||||
----
|
||||
|
||||
It is important to understand the contract of these methods and their usage specifically in the context of Spring Cloud Stream.
|
||||
It is important to understand the contract of these methods and their usage specifically in the context of Spring Cloud Stream.
|
||||
|
||||
The `fromMessage` method converts incoming `Message` to an argument type. The payload of the `Message` could be _any type_ and it's
|
||||
up to the actual implementation of the `MessageConverter` to support multiple types. For example, some JSON converter may support the payload type as `byte[]`
|
||||
and `String` etc. This is important when application contains an internal pipeline (i.e., _input -> handler1 -> handler2 ->. . . -> output_) and the output of
|
||||
the upstream handler results in a `Message` which may not be in the initial wire format.
|
||||
The `fromMessage` method converts incoming `Message` to an argument type. The payload of the `Message` could be _any type_ and it's
|
||||
up to the actual implementation of the `MessageConverter` to support multiple types. For example, some JSON converter may support the payload type as `byte[]`
|
||||
and `String` etc. This is important when application contains an internal pipeline (i.e., _input -> handler1 -> handler2 ->. . . -> output_) and the output of
|
||||
the upstream handler results in a `Message` which may not be in the initial wire format.
|
||||
|
||||
However. . .
|
||||
|
||||
@@ -1677,34 +1677,34 @@ Message<byte[]> toMessage(Object payload, @Nullable MessageHeaders headers);
|
||||
|
||||
=== Provided MessageConverters
|
||||
|
||||
As it was mentioned earlier the framework already provides a stack of `MessageConverters` to handle most common use cases. Below is the ordered list of provided `MessageConverters`.
|
||||
As it was mentioned earlier the framework already provides a stack of `MessageConverters` to handle most common use cases. Below is the ordered list of provided `MessageConverters`.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is important to understand the importance of the order since the mechanism by which the framework locates the appropriate `MessageConverter` is by iterating through each and asking
|
||||
It is important to understand the importance of the order since the mechanism by which the framework locates the appropriate `MessageConverter` is by iterating through each and asking
|
||||
if it can convert using the first one that can convert.
|
||||
====
|
||||
|
||||
1. `ApplicationJsonMessageMarshallingConverter` - _variation of the `org.springframework.messaging.converter.MappingJackson2MessageConverter`. Supports conversion of the payload of the
|
||||
1. `ApplicationJsonMessageMarshallingConverter` - _variation of the `org.springframework.messaging.converter.MappingJackson2MessageConverter`. Supports conversion of the payload of the
|
||||
`Message` from `String` or `byte[]`._
|
||||
2. `TupleJsonMessageConverter` - _***[DEPRECATED]*** Supports conversion of the payload of the `Message` from `org.springframework.tuple.Tuple`._
|
||||
3. `ByteArrayMessageConverter` - _Supports conversion of the payload of the `Message` from `byte[]` to `byte[]` for cases when `contentType` is set to `application/octet-stream`.
|
||||
3. `ByteArrayMessageConverter` - _Supports conversion of the payload of the `Message` from `byte[]` to `byte[]` for cases when `contentType` is set to `application/octet-stream`.
|
||||
Essentially a pass through and exists primarily for backward compatibility._
|
||||
4. `ObjectStringMessageConverter` - _Supports conversion of any type to a `String`, when contentType is `text/plain`. Invokes Object’s `toString()` method or if payload is
|
||||
4. `ObjectStringMessageConverter` - _Supports conversion of any type to a `String`, when contentType is `text/plain`. Invokes Object’s `toString()` method or if payload is
|
||||
`byte[]` then new `String(byte[])`._
|
||||
5. `JavaSerializationMessageConverter` - _***[DEPRECATED]*** Supports conversion based on java serialization when `contentType` is `application/x-java-serialized-object`._
|
||||
6. `KryoMessageConverter` - _***[DEPRECATED]*** Supports conversion based on kryo serialization when `contentType` is `application/x-java-object`._
|
||||
7. `JsonUnmarshallingConverter` - _Similar to the `ApplicationJsonMessageMarshallingConverter`. Supports conversion of any type when `contentType` is `application/x-java-object`.
|
||||
Expects the actual type information to be embedded in the `contentType` as an attribute (e.g., `application/x-java-object;type=foo.bar.Baz`)._
|
||||
|
||||
In the event no appropriate converter is found the framework will throw an exception at which point you should check your code and configfuration and ensure you didn't miss anything
|
||||
(i.e., provide `contentType` via binding or header). However, most likely you are dealing with some uncommon case (custom `contentType` perhaps) and the current stack of provided `MessageConverters`
|
||||
In the event no appropriate converter is found the framework will throw an exception at which point you should check your code and configfuration and ensure you didn't miss anything
|
||||
(i.e., provide `contentType` via binding or header). However, most likely you are dealing with some uncommon case (custom `contentType` perhaps) and the current stack of provided `MessageConverters`
|
||||
doesn't know how to convert. And if that's the case you can add custom `MessageConverter`.
|
||||
|
||||
=== User defined Message Converters
|
||||
|
||||
Spring Cloud Stream exposes a mechanism to define and register additional `MessageConverters`. All you need to do is implement `org.springframework.messaging.converter.MessageConverter`,
|
||||
confiure it as `@Bean` and annotate it with `@StreamMessageConverter` and it will be added to the existing stack of `MessageConverters`. The `@StreamMessageConverter` qualifier annotation
|
||||
confiure it as `@Bean` and annotate it with `@StreamMessageConverter` and it will be added to the existing stack of `MessageConverters`. The `@StreamMessageConverter` qualifier annotation
|
||||
is to avoid picking up other converters that may be present on the _Application Context_.
|
||||
|
||||
[NOTE]
|
||||
|
||||
@@ -248,7 +248,7 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> _headers = (Map<String, Object>) dfa.getPropertyValue("headers");
|
||||
_headers.put(MessageHeaders.CONTENT_TYPE,
|
||||
"application/" + this.prefix + "." + schemaReference.getSubject()
|
||||
"application/" + this.prefix + "." + schemaReference.getSubject()
|
||||
+ ".v" + schemaReference.getVersion() + "+" + AVRO_FORMAT);
|
||||
|
||||
return schema;
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.messaging.Message;
|
||||
*
|
||||
* <p>
|
||||
* Expected usage is of the form (with appropriate static imports):
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* public class TransformProcessorApplicationTests {
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.integration.endpoint.Pausable;
|
||||
* @author Gary Russell
|
||||
* @author Marius Bogoevici
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @see org.springframework.cloud.stream.annotation.EnableBinding
|
||||
*/
|
||||
public interface Binding<T> extends Pausable {
|
||||
@@ -43,28 +43,28 @@ public interface Binding<T> extends Pausable {
|
||||
|
||||
/**
|
||||
* Stops the target component represented by this instance.
|
||||
* NOTE: At the time the instance is created the component is already started.
|
||||
* NOTE: At the time the instance is created the component is already started.
|
||||
* This operation is typically used by actuator to re-bind/re-start.
|
||||
*
|
||||
*
|
||||
* @see BindingsEndpoint
|
||||
*/
|
||||
default void start() {}
|
||||
|
||||
/**
|
||||
* Starts the target component represented by this instance.
|
||||
* NOTE: At the time the instance is created the component is already started.
|
||||
* NOTE: At the time the instance is created the component is already started.
|
||||
* This operation is typically used by actuator to re-bind/re-start.
|
||||
*
|
||||
*
|
||||
* @see BindingsEndpoint
|
||||
*/
|
||||
default void stop() {}
|
||||
|
||||
/**
|
||||
* Pauses the target component represented by this instance if and only if the component
|
||||
* Pauses the target component represented by this instance if and only if the component
|
||||
* implements {@link Pausable} interface
|
||||
* NOTE: At the time the instance is created the component is already started and active.
|
||||
* NOTE: At the time the instance is created the component is already started and active.
|
||||
* This operation is typically used by actuator to pause/resume.
|
||||
*
|
||||
*
|
||||
* @see BindingsEndpoint
|
||||
*/
|
||||
default void pause() {
|
||||
@@ -72,11 +72,11 @@ public interface Binding<T> extends Pausable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes the target component represented by this instance if and only if the component
|
||||
* Resumes the target component represented by this instance if and only if the component
|
||||
* implements {@link Pausable} interface
|
||||
* NOTE: At the time the instance is created the component is already started and active.
|
||||
* NOTE: At the time the instance is created the component is already started and active.
|
||||
* This operation is typically used by actuator to pause/resume.
|
||||
*
|
||||
*
|
||||
* @see BindingsEndpoint
|
||||
*/
|
||||
default void resume() {
|
||||
@@ -92,7 +92,7 @@ public interface Binding<T> extends Pausable {
|
||||
|
||||
/**
|
||||
* Returns the name of this binding (i.e., channel name)
|
||||
*
|
||||
*
|
||||
* @return binding name
|
||||
*/
|
||||
default String getName() {
|
||||
|
||||
@@ -43,9 +43,9 @@ public class ConsumerProperties {
|
||||
private boolean partitioned;
|
||||
|
||||
/**
|
||||
* When set to a value greater than equal to zero, allows customizing the instance
|
||||
* count of this consumer (if different from spring.cloud.stream.instanceCount).
|
||||
* When set to a negative value, it will default to spring.cloud.stream.instanceCount.
|
||||
* When set to a value greater than equal to zero, allows customizing the instance
|
||||
* count of this consumer (if different from spring.cloud.stream.instanceCount).
|
||||
* When set to a negative value, it will default to spring.cloud.stream.instanceCount.
|
||||
* See that property for more information.
|
||||
* Default: -1
|
||||
* NOTE: This setting will override the one set in 'spring.cloud.stream.instance-count'
|
||||
@@ -53,9 +53,9 @@ public class ConsumerProperties {
|
||||
private int instanceCount = -1;
|
||||
|
||||
/**
|
||||
* When set to a value greater than equal to zero, allows customizing the instance
|
||||
* index of this consumer (if different from spring.cloud.stream.instanceIndex).
|
||||
* When set to a negative value, it will default to spring.cloud.stream.instanceIndex.
|
||||
* When set to a value greater than equal to zero, allows customizing the instance
|
||||
* index of this consumer (if different from spring.cloud.stream.instanceIndex).
|
||||
* When set to a negative value, it will default to spring.cloud.stream.instanceIndex.
|
||||
* See that property for more information.
|
||||
* Default: -1
|
||||
* NOTE: This setting will override the one set in 'spring.cloud.stream.instance-index'
|
||||
@@ -63,61 +63,61 @@ public class ConsumerProperties {
|
||||
private int instanceIndex = -1;
|
||||
|
||||
/**
|
||||
* The number of attempts to process the message (including the first)
|
||||
* in the event of processing failures. This is a RetryTemplate configuration
|
||||
* The number of attempts to process the message (including the first)
|
||||
* in the event of processing failures. This is a RetryTemplate configuration
|
||||
* which is provided by the framework.
|
||||
* Default: 3. Set to 1 to disable retry. You can also provide custom RetryTemplate
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* it as @Bean inside your application configuration.
|
||||
*/
|
||||
private int maxAttempts = 3;
|
||||
|
||||
/**
|
||||
* The backoff initial interval on retry. This is a RetryTemplate configuration
|
||||
* The backoff initial interval on retry. This is a RetryTemplate configuration
|
||||
* which is provided by the framework.
|
||||
* Default: 1000 ms.
|
||||
* You can also provide custom RetryTemplate
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* it as @Bean inside your application configuration.
|
||||
*/
|
||||
private int backOffInitialInterval = 1000;
|
||||
|
||||
/**
|
||||
* The maximum backoff interval. This is a RetryTemplate configuration
|
||||
* The maximum backoff interval. This is a RetryTemplate configuration
|
||||
* which is provided by the framework.
|
||||
* Default: 10000 ms.
|
||||
* You can also provide custom RetryTemplate
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* it as @Bean inside your application configuration.
|
||||
*/
|
||||
private int backOffMaxInterval = 10000;
|
||||
|
||||
/**
|
||||
* The backoff multiplier.This is a RetryTemplate configuration
|
||||
* The backoff multiplier.This is a RetryTemplate configuration
|
||||
* which is provided by the framework.
|
||||
* Default: 2.0.
|
||||
* You can also provide custom RetryTemplate
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* in the event you want to take complete control of the RetryTemplate. Simply configure
|
||||
* it as @Bean inside your application configuration.
|
||||
*/
|
||||
private double backOffMultiplier = 2.0;
|
||||
|
||||
/**
|
||||
* When set to none, disables header parsing on input. Effective only
|
||||
* for messaging middleware that does not support message headers natively
|
||||
* and requires header embedding. This option is useful when consuming data
|
||||
* from non-Spring Cloud Stream applications when native headers are not
|
||||
* supported. When set to headers, uses the middleware’s native header mechanism.
|
||||
* When set to none, disables header parsing on input. Effective only
|
||||
* for messaging middleware that does not support message headers natively
|
||||
* and requires header embedding. This option is useful when consuming data
|
||||
* from non-Spring Cloud Stream applications when native headers are not
|
||||
* supported. When set to headers, uses the middleware’s native header mechanism.
|
||||
* When set to embeddedHeaders, embeds headers into the message payload.
|
||||
* Default: depends on binder implementation. Rabbit and Kafka binders currently
|
||||
* Default: depends on binder implementation. Rabbit and Kafka binders currently
|
||||
* distributed with spring cloud stream support headers natively.
|
||||
*/
|
||||
private HeaderMode headerMode;
|
||||
|
||||
/**
|
||||
* When set to true, the inbound message is deserialized directly by client library,
|
||||
* which must be configured correspondingly (e.g. setting an appropriate Kafka producer value serializer).
|
||||
* NOTE: This is binder specific setting which has no effect if binder does not support native
|
||||
* When set to true, the inbound message is deserialized directly by client library,
|
||||
* which must be configured correspondingly (e.g. setting an appropriate Kafka producer value serializer).
|
||||
* NOTE: This is binder specific setting which has no effect if binder does not support native
|
||||
* serialization/deserialization. Currently only Kafka binder supports it.
|
||||
* Default: 'false'
|
||||
*/
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Gary Russell
|
||||
* @author Marius Bogoevici
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @see org.springframework.cloud.stream.annotation.EnableBinding
|
||||
*/
|
||||
@JsonPropertyOrder({ "name", "group", "pausable", "state"})
|
||||
@@ -64,7 +64,7 @@ public class DefaultBinding<T> implements Binding<T> {
|
||||
* @param target the binding target
|
||||
* @param lifecycle {@link Lifecycle} that runs while the binding is active and will be stopped during unbinding
|
||||
* @param extBindingInfo additional information related to binding
|
||||
*
|
||||
*
|
||||
*/
|
||||
public DefaultBinding(String name, String group, T target, Lifecycle lifecycle) {
|
||||
Assert.notNull(target, "target must not be null");
|
||||
|
||||
@@ -45,7 +45,7 @@ public interface Bindable {
|
||||
* Binds all the inputs associated with this instance.
|
||||
* @param adapter instance of {@link BindingService}
|
||||
* @return collection of {@link Binding}s
|
||||
*
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
default Collection<Binding<Object>> createAndBindInputs(BindingService adapter) {
|
||||
|
||||
@@ -75,7 +75,7 @@ public class BinderAwareChannelResolver extends BeanFactoryMessageChannelDestina
|
||||
@SuppressWarnings("rawtypes")
|
||||
public BinderAwareChannelResolver(BindingService bindingService,
|
||||
AbstractBindingTargetFactory<? extends MessageChannel> bindingTargetFactory,
|
||||
DynamicDestinationsBindable dynamicDestinationsBindable, NewDestinationBindingCallback callback,
|
||||
DynamicDestinationsBindable dynamicDestinationsBindable, NewDestinationBindingCallback callback,
|
||||
GlobalChannelInterceptorProcessor globalChannelInterceptorProcessor) {
|
||||
this.dynamicDestinationsBindable = dynamicDestinationsBindable;
|
||||
Assert.notNull(bindingService, "'bindingService' cannot be null");
|
||||
|
||||
@@ -30,14 +30,14 @@ import java.util.stream.Collectors;
|
||||
public class BinderProperties {
|
||||
|
||||
/**
|
||||
* The binder type. It typically references one of the binders found on the classpath,
|
||||
* in particular a key in a META-INF/spring.binders file.
|
||||
* The binder type. It typically references one of the binders found on the classpath,
|
||||
* in particular a key in a META-INF/spring.binders file.
|
||||
* By default, it has the same value as the configuration name.
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Root for a set of properties that can be used to customize the environment of the binder.
|
||||
* Root for a set of properties that can be used to customize the environment of the binder.
|
||||
*/
|
||||
private Map<String, Object> environment = new HashMap<>();
|
||||
|
||||
@@ -47,7 +47,7 @@ public class BinderProperties {
|
||||
private boolean inheritEnvironment = true;
|
||||
|
||||
/**
|
||||
* Whether the binder configuration is a candidate for being considered a default binder,
|
||||
* Whether the binder configuration is a candidate for being considered a default binder,
|
||||
* or can be used only when explicitly referenced. Defaulys: true
|
||||
*/
|
||||
private boolean defaultCandidate = true;
|
||||
|
||||
@@ -61,7 +61,7 @@ public class BindingProperties {
|
||||
// Properties for both input and output bindings
|
||||
|
||||
/**
|
||||
* Specifies content-type that will be used by this binding in the event
|
||||
* Specifies content-type that will be used by this binding in the event
|
||||
* it is not specified in Message headers. Default: 'application/json'.
|
||||
*/
|
||||
private String contentType = DEFAULT_CONTENT_TYPE.toString();
|
||||
|
||||
@@ -178,7 +178,7 @@ public class BindingServiceConfiguration {
|
||||
public BinderAwareChannelResolver binderAwareChannelResolver(BindingService bindingService,
|
||||
AbstractBindingTargetFactory<? extends MessageChannel> bindingTargetFactory,
|
||||
DynamicDestinationsBindable dynamicDestinationsBindable,
|
||||
@Nullable BinderAwareChannelResolver.NewDestinationBindingCallback callback,
|
||||
@Nullable BinderAwareChannelResolver.NewDestinationBindingCallback callback,
|
||||
@Nullable GlobalChannelInterceptorProcessor globalChannelInterceptorProcessor) {
|
||||
return new BinderAwareChannelResolver(bindingService, bindingTargetFactory, dynamicDestinationsBindable,
|
||||
callback, globalChannelInterceptorProcessor);
|
||||
|
||||
@@ -54,20 +54,20 @@ public class BindingServiceProperties implements ApplicationContextAware, Initia
|
||||
private static final int DEFAULT_BINDING_RETRY_INTERVAL = 30;
|
||||
|
||||
/**
|
||||
* The instance id of the application: a number from 0 to instanceCount-1.
|
||||
* The instance id of the application: a number from 0 to instanceCount-1.
|
||||
* Used for partitioning and with Kafka.
|
||||
* NOTE: Could also be managed per individual binding
|
||||
* "spring.cloud.stream.bindings.foo.consumer.instance-index" where 'foo' is
|
||||
* NOTE: Could also be managed per individual binding
|
||||
* "spring.cloud.stream.bindings.foo.consumer.instance-index" where 'foo' is
|
||||
* the name of the binding.
|
||||
*/
|
||||
@Value("${INSTANCE_INDEX:${CF_INSTANCE_INDEX:0}}")
|
||||
private int instanceIndex;
|
||||
|
||||
/**
|
||||
* The number of deployed instances of an application.
|
||||
* The number of deployed instances of an application.
|
||||
* Default: 1.
|
||||
* NOTE: Could also be managed per individual binding
|
||||
* "spring.cloud.stream.bindings.foo.consumer.instance-count" where 'foo' is
|
||||
* NOTE: Could also be managed per individual binding
|
||||
* "spring.cloud.stream.bindings.foo.consumer.instance-count" where 'foo' is
|
||||
* the name of the binding.
|
||||
*/
|
||||
private int instanceCount = 1;
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
@Configuration
|
||||
|
||||
@@ -34,11 +34,11 @@ import org.springframework.messaging.converter.MappingJackson2MessageConverter;
|
||||
import org.springframework.messaging.converter.MessageConversionException;
|
||||
|
||||
/**
|
||||
* Variation of {@link MappingJackson2MessageConverter} to support marshalling and
|
||||
* unmarshalling of Messages's payload from 'String' or 'byte[]' to an instance of a 'targetClass'
|
||||
* Variation of {@link MappingJackson2MessageConverter} to support marshalling and
|
||||
* unmarshalling of Messages's payload from 'String' or 'byte[]' to an instance of a 'targetClass'
|
||||
* and and back to 'byte[]'
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
@@ -74,11 +74,11 @@ class ApplicationJsonMessageMarshallingConverter extends MappingJackson2MessageC
|
||||
Class<?> conversionHintType = ((MethodParameter)conversionHint).getParameterType();
|
||||
if (Message.class.isAssignableFrom(conversionHintType)) {
|
||||
/*
|
||||
* Ensures that super won't attempt to create Message as a result of conversion
|
||||
* Ensures that super won't attempt to create Message as a result of conversion
|
||||
* and stays at payload conversion only.
|
||||
* The Message will eventually be created in MessageMethodArgumentResolver.resolveArgument(..)
|
||||
*/
|
||||
conversionHint = null;
|
||||
conversionHint = null;
|
||||
}
|
||||
else if (((MethodParameter)conversionHint).getGenericParameterType() instanceof ParameterizedType) {
|
||||
ParameterizedTypeReference<Object> forType = ParameterizedTypeReference.forType(((MethodParameter)conversionHint).getGenericParameterType());
|
||||
|
||||
@@ -30,8 +30,8 @@ import org.springframework.messaging.converter.MessageConversionException;
|
||||
* as input.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*
|
||||
* @deprecated as of 2.0.
|
||||
*
|
||||
* @deprecated as of 2.0.
|
||||
*/
|
||||
// NOTE we need to revisit as to why do we need it in the first place, given that our first converter already handles JSON
|
||||
@Deprecated
|
||||
|
||||
@@ -26,10 +26,10 @@ import org.springframework.util.MimeType;
|
||||
/**
|
||||
* A {@link org.springframework.messaging.converter.MessageConverter} to convert a
|
||||
* non-String objects to a String, when expected content type is "text/plain".
|
||||
*
|
||||
*
|
||||
* It only performs conversions to internal format and is a wrapper around
|
||||
* {@link Object#toString()}.
|
||||
*
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*
|
||||
* @since 1.2
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.MimeTypeUtils;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Marius Bogoevici
|
||||
* @author Vinicius Carvalho
|
||||
*
|
||||
*
|
||||
* @deprecated as of 2.0. please use 'application/json' content type
|
||||
*/
|
||||
@Deprecated
|
||||
|
||||
@@ -32,11 +32,11 @@ import org.springframework.cloud.stream.binding.InputBindingLifecycle;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Actuator endpoint for binding control
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
@@ -91,7 +91,7 @@ public class BindingsEndpoint {
|
||||
private List<Binding<?>> gatherInputBindings() {
|
||||
List<Binding<?>> inputBindings = new ArrayList<>();
|
||||
for (InputBindingLifecycle inputBindingLifecycle : this.inputBindingLifecycles) {
|
||||
Collection<Binding<?>> lifecycleInputBindings =
|
||||
Collection<Binding<?>> lifecycleInputBindings =
|
||||
(Collection<Binding<?>>) new DirectFieldAccessor(inputBindingLifecycle).getPropertyValue("inputBindings");
|
||||
inputBindings.addAll(lifecycleInputBindings);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class BindingsEndpoint {
|
||||
|
||||
private enum State {
|
||||
STARTED,
|
||||
STOPPED,
|
||||
STOPPED,
|
||||
PAUSED,
|
||||
RESUMED;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.cloud.stream.internal;
|
||||
|
||||
/**
|
||||
* Contains the names of properties for the internal use of Spring Cloud Stream.
|
||||
*
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public abstract class InternalPropertyNames {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ApplicationMetricsProperties implements EnvironmentAware, Applicati
|
||||
private static final Bindable<Map<String, String>> STRING_STRING_MAP = Bindable.mapOf(String.class, String.class);
|
||||
|
||||
/**
|
||||
* The name of the metric being emitted. Should be an unique value per application.
|
||||
* The name of the metric being emitted. Should be an unique value per application.
|
||||
* Defaults to: ${spring.application.name:${vcap.application.name:${spring.config.name:application}}}
|
||||
*/
|
||||
@Value("${spring.application.name:${vcap.application.name:${spring.config.name:application}}}")
|
||||
|
||||
@@ -67,7 +67,7 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
/**
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
@@ -246,7 +246,7 @@ class DefaultDestinationPublishingMeterRegistry extends MeterRegistry implements
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private class Field {
|
||||
final String name;
|
||||
@@ -274,7 +274,7 @@ class DefaultDestinationPublishingMeterRegistry extends MeterRegistry implements
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static final class MessageChannelPublisher implements Consumer<String> {
|
||||
private final MetersPublisherBinding metersPublisherBinding;
|
||||
|
||||
@@ -37,9 +37,9 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.springframework.cloud.stream.annotation.Output;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
* @since 2.0
|
||||
|
||||
@@ -19,9 +19,9 @@ package org.springframework.cloud.stream.micrometer;
|
||||
import io.micrometer.core.instrument.step.StepRegistryConfig;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -336,7 +336,7 @@ public class ContentTypeTckTests {
|
||||
assertEquals("x-java-object", contentType.getSubtype());
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* This test simply demonstrates how one can override an existing MessageConverter for a given contentType.
|
||||
* In this case we are demonstrating how Kryo converter can be overriden ('application/x-java-object' maps to Kryo).
|
||||
*/
|
||||
@@ -625,8 +625,8 @@ public class ContentTypeTckTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* Even though this MessageConverter has nothing to do with Kryo it still shows how Kryo
|
||||
* conversion can be customized/overriden since it simply overriding a converter for
|
||||
* Even though this MessageConverter has nothing to do with Kryo it still shows how Kryo
|
||||
* conversion can be customized/overriden since it simply overriding a converter for
|
||||
* contentType 'application/x-java-object'
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
/**
|
||||
* Provides test channel binder and supporting classes
|
||||
*
|
||||
* THe test binder is backed by Spring Integration framework and is not intended
|
||||
*
|
||||
* THe test binder is backed by Spring Integration framework and is not intended
|
||||
* for uses outside of local testing.
|
||||
*
|
||||
*
|
||||
* The test binder implementation - {@link org.springframework.cloud.stream.binder.test.TestChannelBinder}
|
||||
* The test binder configuration - {@link org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration}
|
||||
* The example that shows how to use it - {@link org.springframework.cloud.stream.binder.test.SampleStreamApp}
|
||||
*
|
||||
* The example that shows how to use it - {@link org.springframework.cloud.stream.binder.test.SampleStreamApp}
|
||||
*
|
||||
*/
|
||||
package org.springframework.cloud.stream.binder.test;
|
||||
|
||||
@@ -52,7 +52,7 @@ public class CustomPartitionedProducerTest {
|
||||
|
||||
@Test
|
||||
public void testCustomPartitionedProducer() {
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSource.class,
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSource.class,
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.main.web-application-type=none",
|
||||
"--spring.cloud.stream.bindings.output.producer.partitionKeyExtractorClass=org.springframework.cloud.stream.partitioning.CustomPartitionKeyExtractorClass",
|
||||
@@ -83,7 +83,7 @@ public class CustomPartitionedProducerTest {
|
||||
|
||||
@Test
|
||||
public void testCustomPartitionedProducerByName() {
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSource.class,
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSource.class,
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.main.web-application-type=none",
|
||||
"--spring.cloud.stream.bindings.output.producer.partitionKeyExtractorName=customPartitionKeyExtractor",
|
||||
@@ -114,7 +114,7 @@ public class CustomPartitionedProducerTest {
|
||||
|
||||
@Test
|
||||
public void testCustomPartitionedProducerAsSingletons() {
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSource.class,
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSource.class,
|
||||
"--spring.jmx.enabled=false", "--spring.main.web-application-type=none");
|
||||
Source testSource = context.getBean(Source.class);
|
||||
DirectChannel messageChannel = (DirectChannel) testSource.output();
|
||||
@@ -141,8 +141,8 @@ public class CustomPartitionedProducerTest {
|
||||
}
|
||||
|
||||
public void testCustomPartitionedProducerMultipleInstances() {
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSourceMultipleStrategies.class,
|
||||
"--spring.jmx.enabled=false",
|
||||
ApplicationContext context = SpringApplication.run(CustomPartitionedProducerTest.TestSourceMultipleStrategies.class,
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.main.web-application-type=none",
|
||||
"--spring.cloud.stream.bindings.output.producer.partitionKeyExtractorName=customPartitionKeyExtractorOne",
|
||||
"--spring.cloud.stream.bindings.output.producer.partitionSelectorName=customPartitionSelectorTwo");
|
||||
@@ -170,11 +170,11 @@ public class CustomPartitionedProducerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=Exception.class)
|
||||
@Test(expected=Exception.class)
|
||||
// It actually throws UnsatisfiedDependencyException, but it is confusing when it comes to test
|
||||
// But for the purposes of the test all we care about is that it fails
|
||||
public void testCustomPartitionedProducerMultipleInstancesFailNoFilter() {
|
||||
SpringApplication.run(CustomPartitionedProducerTest.TestSourceMultipleStrategies.class,
|
||||
SpringApplication.run(CustomPartitionedProducerTest.TestSourceMultipleStrategies.class,
|
||||
"--spring.jmx.enabled=false", "--spring.main.web-application-type=none");
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.integration.handler.AbstractReplyProducingMessageHand
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user