Not so many people, using Spring MVC consider or even know the alternative way of describing the controllers (or better say handlers) in the project. I would like just quickly show how nice and concise could be this approach, and also, what is not less important, fun. This is the main reason why we all are here, right?

Wanna fun

Spring CLI

To show something, we need this “something”. Let’s quickly create the simple, sample MVC project in Spring. To do that I am going to use Spring Boot CLI.

1
spring init -a func-endpoints --build gradle -d web -g com.relaximus -l groovy func-endpoints

let’s open it:

1
idea build.gradle

Nothing super interesting yet, the Spring Boot CLI is just the console wrapper for the spring initializr

Func endpoints sample

Now we are ready to go. Let’s create something nice:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@SpringBootApplication
class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	@Bean
	public RouterFunction<ServerResponse> routerFunction() {
		return route()
                    .GET("/person/{id}", accept(APPLICATION_JSON), PersonHandler::getPersonFor)
                    .GET("/person", accept(APPLICATION_JSON), PersonHandler.listPeople())
                    .POST("/person", PersonHandler::createPersonFrom)
                    .build();
	}
}

Here we have created the RouterFunction, the main aim of which is to describe the mapping of the request to their appropriate handlers. This function registered as just a Spring bean. And the Handler is just the function, which receives the ServerRequest and returns the ServerResponse.

The documentation suggests doing it in slightly different way, but you will understand why I changed it a bit in the next section… And yes, forgive me, that’s groovy again :)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class PersonHandler {

    static HandlerFunction<ServerResponse> listPeople() {
        List<Person> people = [
                Person.builder()
                        .name("Alex")
                        .birthDate(new Date())
                        .hobbies(List.of("skiing", "tennis"))
                        .build()
        ];

        { ServerRequest request ->
            ServerResponse.ok()
                    .contentType(APPLICATION_JSON)
                    .body(people)
        }
    }

    static ServerResponse createPersonFrom(ServerRequest request) {
        ServerResponse.ok().build()
    }

    static ServerResponse getPersonFor(ServerRequest request) {
        ServerResponse.ok().build()
    }
}

@Builder
@CompileStatic
class Person {
    String name
    Date birthDate
    List<String> hobbies
}

Before proceeding to the next part I would like to notice a few things. Actually what is the difference with the usual approach through the @Controller and @RequestMapping annotations? Well, there is less magic here. You create the explicit mapping function routing request to the right handler. This moves the routing engine from the level of controllers to the level of configuration and brings you a bit more control over this in a big project. Besides you can disable the scanning for the controllers at all, and most like would get some startup performance improvement.

And last but not least, if you are using more advanced language, then just Java, the handlers could be very dry and self-explanatory - that’s what I am going to try. Let’s rewrite the routing function to groovy and use some of its features.

Nice improvements in Groovy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
@Configuration
class RouterConfig {
    @Bean
    def routerFunction() {
        route().with {
            GET('/person/{id}', accept(APPLICATION_JSON)) {
                getPersonFor it
            }

            GET ("/person",
                    accept(APPLICATION_JSON),
                    listPeople())

            POST("/person") {
                createPersonFrom it
            }

            build()
        }
    }
}

As you can see, it’s a huge playground for groovy enthusiasts, I just used the simplest example, but I had some fun already. Just used the basic things: * with construct, * arguments in one line with right names of the methods, * default variable name for the Closure - it.

And that’s it, but the routing function now looks much more interesting.

Let’s finally rung the code and check how it works:

1
gradle bootRun

check result

Conclusion

I am pretty sure, that you could feel a bit skeptical regarding this approach of creating the Controllers in Spring MVC.

But I think, that it deserves at least a try, especially if you are using the synthetically advanced language, which could make this functional nature of this approach even more powerful.

GitHub repo.