1

Is it possible to use 2 functions where the output of the first function it the input of the second one?

My functions:

@Configuration
public class StringStream {

    @Bean
    public Supplier<Flux<String>> stringSupplier() {
        return () -> Flux.interval(Duration.of(1L, ChronoUnit.SECONDS))
                .map(v -> RandomStringUtils.randomAlphabetic(10));
    }

    @Bean
    public Function<KStream<Bytes, String>, KStream<Bytes, String>> reverse() {
        return strings -> strings.mapValues(StringUtils::reverse);
    }

    @Bean
    public Function<KStream<Bytes, String>, KStream<Bytes, String>> uppercase() {
        return strings -> strings.mapValues((ValueMapper<String, String>) String::toUpperCase);
    }

    @Bean
    public Consumer<String> print() {
        return message -> LOGGER.info("==> {}", message);
    }
}

My configuration:

...
spring.cloud.stream:
  function:
    definition: stringSupplier;uppercase;reverse;print

spring.cloud.stream.bindings.stringSupplier-out-0:
  content-type: text/plain
  destination: strings-random

spring.cloud.stream.bindings.reverse-in-0:
  destination: strings-random
spring.cloud.stream.bindings.reverse-out-0:
  destination: strings-reversed

spring.cloud.stream.bindings.uppercase-in-0:
  destination: strings-reversed
spring.cloud.stream.bindings.uppercase-out-0:
  destination: strings-uppercase

spring.cloud.stream.bindings.print-in-0:
  destination: strings-uppercase

It only sends strings to strings-reversed. Is this a limitation or I am doing something wrong?

Ben Keil
  • 1,050
  • 1
  • 10
  • 30

1 Answers1

3

Yes, the solution is to use | operator to concatenate functions.

For example this configuration should concat all your operations..

spring.cloud.stream:
  function:
    definition: stringSupplier|uppercase|reverse|print

Under the hood spring-cloud-stream uses spring-cloud-function to provide function composition to the framework.

You can find more information in docs..
https://docs.spring.io/spring-cloud-function/docs/3.1.0/reference/html/spring-cloud-function.html#_declarative_function_composition

50qbits
  • 254
  • 2
  • 3
  • 1
    How does the binding then look like? – Ben Keil Jan 08 '21 at 17:14
  • 2
    For me it looks like something like this https://github.com/spring-cloud/spring-cloud-stream-samples/blob/master/multi-functions-samples/function-composition-kafka/src/main/resources/application.yml is not possible with Kafka – Ben Keil Jan 08 '21 at 19:39
  • it depends on what you want to achieve, I mean that you're use case is like this pipeline... supplier -> function (composite) -> kafka. With that in mind you only need and outboud kafka endpoint (output binding) because the internal messaging routing relies on spring-integration channels. – 50qbits Jan 11 '21 at 06:51