Skip to content

Commit

Permalink
Binding names docs refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
sobychacko committed Jan 18, 2024
1 parent bec9a1c commit 75de93a
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 112 deletions.
3 changes: 3 additions & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
** xref:spring-cloud-stream/programming-model.adoc[]
*** xref:spring-cloud-stream/destination-binders.adoc[]
*** xref:spring-cloud-stream/bindings.adoc[]
*** xref:spring-cloud-stream/binding-names.adoc[]
*** xref:spring-cloud-stream/functional-binding-names.adoc[]
*** xref:spring-cloud-stream/explicit-binding-creation.adoc[]
*** xref:spring-cloud-stream/binding_visualization_control.adoc[]
*** xref:spring-cloud-stream/producing-and-consuming-messages.adoc[]
*** xref:spring-cloud-stream/event-routing.adoc[]
Expand Down
13 changes: 13 additions & 0 deletions docs/modules/ROOT/pages/spring-cloud-stream/binding-names.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[binding-and-binding-names]]
== Binding and Binding names

Binding is an abstraction that represents a bridge between sources and targets exposed by the binder and user code,
This abstraction has a name and while we try to do our best to limit configuration required to run spring-cloud-stream applications,
being aware of such name(s) is necessary for cases where additional per-binding configuration is required.

Throughout this manual you will see examples of configuration properties such as `spring.cloud.stream.bindings.input.destination=myQueue`.
The `input` segment in this property name is what we refer to as _binding name_ and it could derive via several mechanisms.
The following sub-sections will describe the naming conventions and configuration elements used by spring-cloud-stream to control binding names.

NOTE: If your binding name has special characters, such as the `.` character, you need to surround the binding key with brackets (`[]`) and then wrap it in qoutes.
For example `spring.cloud.stream.bindings."[my.output.binding.key]".destination`.
112 changes: 0 additions & 112 deletions docs/modules/ROOT/pages/spring-cloud-stream/bindings.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,115 +33,3 @@ And in this context beans of type `Supplier`, `Function` or `Consumer` are treat
binding of to destinations exposed by the provided binder following certain naming conventions and
rules to avoid extra configuration.

[[binding-and-binding-names]]
== Binding and Binding names

Binding is an abstraction that represents a bridge between sources and targets exposed by the binder and user code,
This abstraction has a name and while we try to do our best to limit configuration required to run spring-cloud-stream applications,
being aware of such name(s) is necessary for cases where additional per-binding configuration is required.

Throughout this manual you will see examples of configuration properties such as `spring.cloud.stream.bindings.input.destination=myQueue`.
The `input` segment in this property name is what we refer to as _binding name_ and it could derive via several mechanisms.
The following sub-sections will describe the naming conventions and configuration elements used by spring-cloud-stream to control binding names.

NOTE: If your binding name has special characters, such as the `.` character, you need to surround the binding key with brackets (`[]`) and then wrap it in qoutes.
For example `spring.cloud.stream.bindings."[my.output.binding.key]".destination`.

[[functional-binding-names]]
=== Functional binding names

Unlike the explicit naming required by annotation-based support (legacy) used in the previous versions of spring-cloud-stream, the functional
programming model defaults to a simple convention when it comes to binding names, thus greatly simplifying application configuration.
Let's look at the first example:

[source, java]
----
@SpringBootApplication
public class SampleApplication {
@Bean
public Function<String, String> uppercase() {
return value -> value.toUpperCase();
}
}
----

In the preceding example we have an application with a single function which acts as message handler. As a `Function` it has an
input and output.
The naming convention used to name input and output bindings is as follows:

* input - `<functionName> + -in- + <index>`
* output - `<functionName> + -out- + <index>`

The `in` and `out` corresponds to the type of binding (such as _input_ or _output_).
The `index` is the index of the input or output binding. It is always 0 for typical single input/output function,
so it's only relevant for <<Functions with multiple input and output arguments>>.

So if for example you would want to map the input of this function to a remote
destination (e.g., topic, queue etc) called "my-topic" you would do so with the following property:
----
--spring.cloud.stream.bindings.uppercase-in-0.destination=my-topic
----
Note how `uppercase-in-0` is used as a segment in property name. The same goes for `uppercase-out-0`.

***Descriptive Binding Names***

Some times to improve readability you may want to give your binding a more descriptive name (such as 'account', 'orders' etc).
Another way of looking at it is you can map an _implicit binding name_ to an _explicit binding name_. And you can do it with
`spring.cloud.stream.function.bindings.<binding-name>` property.
This property also provides a migration path for existing applications that rely on custom interface-based
bindings that require explicit names.

For example,
----
--spring.cloud.stream.function.bindings.uppercase-in-0=input
----

In the preceding example you mapped and effectively renamed `uppercase-in-0` binding name to `input`. Now all configuration
properties can refer to `input` binding name instead (e.g., `--spring.cloud.stream.bindings.input.destination=my-topic`).

NOTE: While descriptive binding names may enhance the readability aspect of the configuration, they also create
another level of misdirection by mapping an implicit binding name to an explicit binding name. And since all subsequent
configuration properties will use the explicit binding name you must always refer to this 'bindings' property to
correlate which function it actually corresponds to. We believe that for most cases (with the exception of <<Functional Composition>>)
it may be an overkill, so, it is our recommendation to avoid using it altogether, especially
since not using it provides a clear path between binder destination and binding name, such as `spring.cloud.stream.bindings.uppercase-in-0.destination=sample-topic`,
where you are clearly correlating the input of `uppercase` function to `sample-topic` destination.

For more on properties and other configuration options please see <<Configuration Options>> section.

[[explicit-binding-creation]]
=== Explicit binding creation

In the previous section we explained how bindings are created implicitly driven by the names of `Function`, `Supplier` or `Consumer` beans provided by your application.
However, there are times when you may need to create binding explicitly where bindings are not tied to any function. This is typically done to
support integrations with other frameworks via `StreamBridge`.

Spring Cloud Stream allows you to define input and output bindings explicitly via `spring.cloud.stream.input-bindings` and `spring.cloud.stream.output-bindings`
properties. Noticed the plural in the property names allowing you to define multiple bindings by simply using `;` as a delimiter.
Just look at the following test case as an example:

----
@Test
public void testExplicitBindings() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(EmptyConfiguration.class))
.web(WebApplicationType.NONE)
.run("--spring.jmx.enabled=false",
"--spring.cloud.stream.input-bindings=fooin;barin",
"--spring.cloud.stream.output-bindings=fooout;barout")) {
. . .
}
}
@EnableAutoConfiguration
@Configuration
public static class EmptyConfiguration {
}
----

As you can see we have declared two input bindings and two output bindings while our configuration had no functions defined, yet we were able to successfully create these bindings and access their corresponding channels.


Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[[explicit-binding-creation]]
=== Explicit binding creation

In the previous section we explained how bindings are created implicitly driven by the names of `Function`, `Supplier` or `Consumer` beans provided by your application.
However, there are times when you may need to create binding explicitly where bindings are not tied to any function. This is typically done to
support integrations with other frameworks via `StreamBridge`.

Spring Cloud Stream allows you to define input and output bindings explicitly via `spring.cloud.stream.input-bindings` and `spring.cloud.stream.output-bindings`
properties. Noticed the plural in the property names allowing you to define multiple bindings by simply using `;` as a delimiter.
Just look at the following test case as an example:

----
@Test
public void testExplicitBindings() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(EmptyConfiguration.class))
.web(WebApplicationType.NONE)
.run("--spring.jmx.enabled=false",
"--spring.cloud.stream.input-bindings=fooin;barin",
"--spring.cloud.stream.output-bindings=fooout;barout")) {
. . .
}
}
@EnableAutoConfiguration
@Configuration
public static class EmptyConfiguration {
}
----

As you can see we have declared two input bindings and two output bindings while our configuration had no functions defined, yet we were able to successfully create these bindings and access their corresponding channels.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[[functional-binding-names]]
=== Functional binding names

Unlike the explicit naming required by annotation-based support (legacy) used in the previous versions of spring-cloud-stream, the functional
programming model defaults to a simple convention when it comes to binding names, thus greatly simplifying application configuration.
Let's look at the first example:

[source, java]
----
@SpringBootApplication
public class SampleApplication {
@Bean
public Function<String, String> uppercase() {
return value -> value.toUpperCase();
}
}
----

In the preceding example we have an application with a single function which acts as message handler. As a `Function` it has an
input and output.
The naming convention used to name input and output bindings is as follows:

* input - `<functionName> + -in- + <index>`
* output - `<functionName> + -out- + <index>`

The `in` and `out` corresponds to the type of binding (such as _input_ or _output_).
The `index` is the index of the input or output binding. It is always 0 for typical single input/output function,
so it's only relevant for <<Functions with multiple input and output arguments>>.

So if for example you would want to map the input of this function to a remote
destination (e.g., topic, queue etc) called "my-topic" you would do so with the following property:
----
--spring.cloud.stream.bindings.uppercase-in-0.destination=my-topic
----
Note how `uppercase-in-0` is used as a segment in property name. The same goes for `uppercase-out-0`.

***Descriptive Binding Names***

Some times to improve readability you may want to give your binding a more descriptive name (such as 'account', 'orders' etc).
Another way of looking at it is you can map an _implicit binding name_ to an _explicit binding name_. And you can do it with
`spring.cloud.stream.function.bindings.<binding-name>` property.
This property also provides a migration path for existing applications that rely on custom interface-based
bindings that require explicit names.

For example,
----
--spring.cloud.stream.function.bindings.uppercase-in-0=input
----

In the preceding example you mapped and effectively renamed `uppercase-in-0` binding name to `input`. Now all configuration
properties can refer to `input` binding name instead (e.g., `--spring.cloud.stream.bindings.input.destination=my-topic`).

NOTE: While descriptive binding names may enhance the readability aspect of the configuration, they also create
another level of misdirection by mapping an implicit binding name to an explicit binding name. And since all subsequent
configuration properties will use the explicit binding name you must always refer to this 'bindings' property to
correlate which function it actually corresponds to. We believe that for most cases (with the exception of <<Functional Composition>>)
it may be an overkill, so, it is our recommendation to avoid using it altogether, especially
since not using it provides a clear path between binder destination and binding name, such as `spring.cloud.stream.bindings.uppercase-in-0.destination=sample-topic`,
where you are clearly correlating the input of `uppercase` function to `sample-topic` destination.

For more on properties and other configuration options please see <<Configuration Options>> section.

0 comments on commit 75de93a

Please sign in to comment.