Home > Enterprise >  SpringBoot Spring Cloud Function: Configurable function composition issue
SpringBoot Spring Cloud Function: Configurable function composition issue

Time:01-26

Small question regarding SpringBoot Spring Cloud function application please.

I have a very simple app which takes a word as input.

The business logic is written via functions. The "difficulty" is: the functions need to be configurable. Meaning, with just an application.properties change restart, the web app should be able to pick the correct business logic, i.e. the correct function composition to apply to the input, without code change.

Here is an example:

application.properties:

spring.cloud.function.definition=upper
#spring.cloud.function.definition=reverse
#spring.cloud.function.definition=upper|reverse

pom:

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-context</artifactId>
            <version>4.0.0</version>
        </dependency>

    </dependencies>
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.function.Function;

@Service
public class ReverseFunction {

    @Bean
    Function<String, String> reverse() {
        return s -> new StringBuilder(s).reverse().toString();
    }

}
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.function.Function;

@Service
public class UpperFunction {

    @Bean
    Function<String, String> upper() {
        return String::toUpperCase;
    }

}

And this is the business logic:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.function.Function;

@RestController
public class FunctionController {

    @GetMapping("/applyFunctionToWord")
    public String applyFunctionToWord(@RequestParam String word) {
        Function<String, String> function = ??? //configurable from application.properties
        return function.apply(word);
    }

}

In tutorials found online and from official documentation from Spring, it is said:

Function Composition
Function composition is a feature of SCF that lets you compose several functions together in a declarative way.
The following example shows how to do so:

--spring.cloud.function.definition=uppercase|reverse
Here, we effectively provided a definition of a single function that is itself a composition of a function named uppercase and a function named reverse. You can also argue that we’ve orchestrated a simple pipeline consisting of running the uppercase function and then sending its output to the reverse function. The term orchestration is important here, and we cover it in more detail later in the post.

https://spring.io/blog/2019/11/04/spring-cloud-stream-composed-functions-or-eip#:~:text=Function composition is a feature of SCF that,following example shows how to do so: --spring.cloud.function.definition=uppercase|reverse

What I tried:

I did configure the property in application.properties.

And as you can see, I did follow the guide naming the property: spring.cloud.function.definition. What is the correct machanism please?

Am I forced to fallback to something with @Value?

My app is not a Spring Cloud Stream app. It is not based on Kafka. It is just a basic web app where the business logic is a configurable composition functions.

Question:

How to have the webapp take into effect the value configured in spring.cloud.function.definition=, and apply it to the input please?

Thank you

CodePudding user response:

I would assume it should work using RoutingFunction, something like this:

@RestController
public class FunctionController {
  
  @Autowired
  RoutingFunction function;

  @GetMapping("/applyFunctionToWord")
  public String applyFunctionToWord(@RequestParam String word) {
    return (String)function.apply(word);
  }

}

CodePudding user response:

You need a @Value annotation and some logic like this

@RestController
public class FunctionController {

    @Value("${spring.cloud.function.definition}")
    String definition;

    @Autowired
    @Qualifier("reverse"); 
    Function reverse; 

    @Autowired
    @Qualifier("upper"); 
    Function upper; 

    @GetMapping("/applyFunctionToWord")
    public String applyFunctionToWord(@RequestParam String word) {
        Function<String, String> function = null
        switch (definition) {
        case "upper" :
            function = upper;
            break;
        case "reverse" :
            function = reverse;
            break;
        }
        return function.apply(word);
    }

}
  • Related