Search code examples
javaspringrestjava-8spring-cloud

How to map functions to REST compliant endpoints with Spring Cloud Function


I have encountered with unusual and interesting technology and way of splitting the business and technical implementation using Spring Cloud Function which enables implementations of java.util.function classes act as an endpoint

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-function-web</artifactId>
</dependency>

In a nutshell, having a simple static List<Book> representing a repository:

private final static List<Book> books = Arrays.asList(
    new Book(1, "One"),
    new Book(2, "Two"),
    new Book(3, "Three"));    

The following @Bean enables the specified endpoints according the method name and its return type:

// GET localhost:8080/books -> returns all the books:
@Bean
public Supplier<List<Book>> books() {
    return () -> books;
}

// GET localhost:8080/book/2 -> returns a particular book
@Bean
public Function<Integer, List<Book>> book() {
    return id -> books.stream().filter(b -> b.getId() == id).collect(Collectors.toList());
}

// POST localhost:8080/newBook -> posts a new book and returns all of them
// Consumer<Book> would supply the POST with no output
@Bean
public Function<Book, List<Book>> newBook() {
    return book -> {
        books.add(book);
        return books;
    };
}

Questions:

  1. Is possible to achieve the full REST compliant solution using the one or more of classes from the java.util.function combined? I have been able to compose only those above. I am particularly interested in the following patterns:

    GET       /books
    GET       /books/1
    POST      /books
    PUT/PATCH /books/1
    DELETE    /books/1
    GET       /books/1/chapters/2/paragraphs/3
    
  2. How to avoid the method name clash for the endpoints since all the methods seem to have to follow a rule of empty parameter signature, and is not-autowirable otherwise. I started with https://www.baeldung.com/spring-cloud-function which looks rather like an RPC than REST.

  3. Is there a way to recognize the URL parameters?

    GET       /books?sort=name
    

Solution

  • Such way is neither explicitly said in their official documentation or blog post. I can't say it was designed for such use-case for sure.

    Whatever, in a section of the doc. It is mentionned the following :

    Functions can also be of Flux or Flux and Spring Cloud Function takes care of converting the data to and from the desired types, as long as it comes in as plain text or (in the case of the POJO) JSON. There is also support for Message where the message headers are copied from the incoming event, depending on the adapter. The web adapter also supports conversion from form-encoded data to a Map, and if you are using the function with Spring Cloud Stream then all the conversion and coercion features for message payloads will be applicable as well.

    Message can take input and ouput and it has also (as said in the doc) the ability encode data to map where you can store you query params or header params.

    Here the Project GitHub and the Official Documentation