{"id":13694712,"url":"https://github.com/hantsy/spring-webmvc-functional-sample","last_synced_at":"2026-02-23T23:35:37.886Z","repository":{"id":142092333,"uuid":"181004147","full_name":"hantsy/spring-webmvc-functional-sample","owner":"hantsy","description":"Spring MVC functional sample","archived":false,"fork":false,"pushed_at":"2024-01-31T08:57:22.000Z","size":87,"stargazers_count":16,"open_issues_count":1,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T13:40:18.285Z","etag":null,"topics":["functional-programming","kotlin","spring-boot","spring-mvc"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hantsy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-12T12:31:08.000Z","updated_at":"2024-04-16T13:27:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"c1bc103a-d507-4886-88f1-f239f1d3d34e","html_url":"https://github.com/hantsy/spring-webmvc-functional-sample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hantsy/spring-webmvc-functional-sample","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hantsy%2Fspring-webmvc-functional-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hantsy%2Fspring-webmvc-functional-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hantsy%2Fspring-webmvc-functional-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hantsy%2Fspring-webmvc-functional-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hantsy","download_url":"https://codeload.github.com/hantsy/spring-webmvc-functional-sample/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hantsy%2Fspring-webmvc-functional-sample/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29760734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T21:02:23.375Z","status":"ssl_error","status_checked_at":"2026-02-23T20:58:31.539Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","kotlin","spring-boot","spring-mvc"],"created_at":"2024-08-02T17:01:38.345Z","updated_at":"2026-02-23T23:35:37.870Z","avatar_url":"https://github.com/hantsy.png","language":"Java","funding_links":[],"categories":["Java"],"sub_categories":[],"readme":"# Functional programming in Spring MVC\nSpring 5.0 embraced ReactiveStreams specification, and introduced a new Reactive Stack as an alternative of the traditional Servlet stack.  And it also brought a new functional programming model to developers, but it is only supported in the Reactive stack.\n\nThe good news is that in the coming 5.2 the functional like APIs are being ported back to the Servlet stack. For those developers who are stick on Servlet stack and want to experience the new programming model, it is absolutely a startling news.\n\nIn this post, let's  take a glance at the new functional feature in Spring MVC.\n\nCreate a Spring Boot project using [Spring initializr](http://start.spring.io), add **Web**, **JPA**,  **Lombok**,  and **H2**  starters as dependencies. \n\n\u003e NOTE: In the Spring Boot version tab, please select 2.2.0.BUILD-SNAPSHOT to get the new Spring 5.2.0.M1 in its dependencies.\n\n\n\nCreate a  simple JPA Entity `Post`. \n\n```java\n@Data\n@ToString\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\n@Entity\nclass Post {\n\n    @Id\n    @GeneratedValue(strategy = AUTO)\n    private Long id;\n    private String title;\n    private String content;\n\n}\n```\n\nAnd create a Repository for the `Post` Entity.\n\n```java\ninterface PostRepository extends JpaRepository\u003cPost, Long\u003e {}\n```\n\nDefine a  `RouterFuncation` bean to handle the routing rules.\n\n```java\n@Bean\npublic RouterFunction\u003cServerResponse\u003e routes(PostHandler postController) {\n    return route(GET(\"/posts\"), postController::all)\n        .andRoute(POST(\"/posts\"), postController::create)\n        .andRoute(GET(\"/posts/{id}\"), postController::get)\n        .andRoute(PUT(\"/posts/{id}\"), postController::update)\n        .andRoute(DELETE(\"/posts/{id}\"), postController::delete);\n}\n```\n\nThe codes are almost same as the ones  we have used in Reactive stack, but note here the `ServerRequest`, `ServerResponse` and `RouterFunction` are imported from the new package:`org.springframework.web.servlet.function`.\n\nLet's have a look at the details of `PostHandler`.\n\n```java\n@Component\nclass PostHandler {\n\n    private final PostRepository posts;\n\n    public PostHandler(PostRepository posts) {\n        this.posts = posts;\n    }\n\n    public ServerResponse all(ServerRequest req) {\n        return ServerResponse.ok().body(this.posts.findAll());\n    }\n\n    public ServerResponse create(ServerRequest req) throws ServletException, IOException {\n\n        var saved = this.posts.save(req.body(Post.class));\n        return ServerResponse.created(URI.create(\"/posts/\" + saved.getId())).build();\n    }\n\n    public ServerResponse get(ServerRequest req) {\n        return this.posts.findById(Long.valueOf(req.pathVariable(\"id\")))\n            .map(post -\u003e ServerResponse.ok().body(post))\n            .orElse(ServerResponse.notFound().build());\n    }\n\n    public ServerResponse update(ServerRequest req) throws ServletException, IOException {\n        var data = req.body(Post.class);\n\n        return this.posts.findById(Long.valueOf(req.pathVariable(\"id\")))\n            .map(\n                post -\u003e {\n                    post.setTitle(data.getTitle());\n                    post.setContent(data.getContent());\n                    return post;\n                }\n            )\n            .map(post -\u003e this.posts.save(post))\n            .map(post -\u003e ServerResponse.noContent().build())\n            .orElse(ServerResponse.notFound().build());\n\n    }\n\n    public ServerResponse delete(ServerRequest req) {\n        return this.posts.findById(Long.valueOf(req.pathVariable(\"id\")))\n            .map(\n                post -\u003e {\n                    this.posts.delete(post);\n                    return ServerResponse.noContent().build();\n                }\n            )\n            .orElse(ServerResponse.notFound().build());\n    }\n\n}\n```\n\nIt is very similar to the codes of Reactive stack, and but the methods return a `ServerResponse` instead of `Mono\u003cServerResponse\u003e`. \n\nLike the RouterFunctionDSL  feature provided in Reactive stack, the routing rules also can be written in Kotlin DSL.\n\n```ko\n router {\n        \"/posts\".nest {\n            GET(\"\", postHandler::all)\n            GET(\"{id}\", postHandler::get)\n            POST(\"\", postHandler::create)\n            PUT(\"{id}\", postHandler::update)\n            DELETE(\"{id}\", postHandler::delete)\n        }\n\n    }\n```\n\n\n\nBesides these,   MockMvc also gets support of Kotlin DSL,  you can write your tests in a fluent style like the following.\n\n```kot\n  @Test\n  fun `Get all posts should ok`() {\n        mockMvc\n                .get(\"/posts\") {\n                    accept = APPLICATION_JSON\n                    headers {\n                        contentLanguage = Locale.ENGLISH\n                    }\n                }\n                .andExpect {\n                    status { isOk }\n                    content { contentType(APPLICATION_JSON_UTF8) }\n                    jsonPath(\"$[0].title\") { value(containsString(\"post\")) } \n                }\n                .andDo {\n                    print()\n                }\n    }\n```\n\nCheck out the [source codes](https://github.com/hantsy/spring-webmvc-functional-sample) from my Github , and compare it with [the codes](https://github.com/hantsy/spring-reactive-sample)  that I had written to demonstrate Reactive stack .\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhantsy%2Fspring-webmvc-functional-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhantsy%2Fspring-webmvc-functional-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhantsy%2Fspring-webmvc-functional-sample/lists"}