Giter Club home page Giter Club logo

spring-webmvc-functional-sample's Introduction

Functional programming in Spring MVC

Spring 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.

The 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.

In this post, let's take a glance at the new functional feature in Spring MVC.

Create a Spring Boot project using Spring initializr, add Web, JPA, Lombok, and H2 starters as dependencies.

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.

Create a simple JPA Entity Post.

@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
class Post {

    @Id
    @GeneratedValue(strategy = AUTO)
    private Long id;
    private String title;
    private String content;

}

And create a Repository for the Post Entity.

interface PostRepository extends JpaRepository<Post, Long> {}

Define a RouterFuncation bean to handle the routing rules.

@Bean
public RouterFunction<ServerResponse> routes(PostHandler postController) {
    return route(GET("/posts"), postController::all)
        .andRoute(POST("/posts"), postController::create)
        .andRoute(GET("/posts/{id}"), postController::get)
        .andRoute(PUT("/posts/{id}"), postController::update)
        .andRoute(DELETE("/posts/{id}"), postController::delete);
}

The 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.

Let's have a look at the details of PostHandler.

@Component
class PostHandler {

    private final PostRepository posts;

    public PostHandler(PostRepository posts) {
        this.posts = posts;
    }

    public ServerResponse all(ServerRequest req) {
        return ServerResponse.ok().body(this.posts.findAll());
    }

    public ServerResponse create(ServerRequest req) throws ServletException, IOException {

        var saved = this.posts.save(req.body(Post.class));
        return ServerResponse.created(URI.create("/posts/" + saved.getId())).build();
    }

    public ServerResponse get(ServerRequest req) {
        return this.posts.findById(Long.valueOf(req.pathVariable("id")))
            .map(post -> ServerResponse.ok().body(post))
            .orElse(ServerResponse.notFound().build());
    }

    public ServerResponse update(ServerRequest req) throws ServletException, IOException {
        var data = req.body(Post.class);

        return this.posts.findById(Long.valueOf(req.pathVariable("id")))
            .map(
                post -> {
                    post.setTitle(data.getTitle());
                    post.setContent(data.getContent());
                    return post;
                }
            )
            .map(post -> this.posts.save(post))
            .map(post -> ServerResponse.noContent().build())
            .orElse(ServerResponse.notFound().build());

    }

    public ServerResponse delete(ServerRequest req) {
        return this.posts.findById(Long.valueOf(req.pathVariable("id")))
            .map(
                post -> {
                    this.posts.delete(post);
                    return ServerResponse.noContent().build();
                }
            )
            .orElse(ServerResponse.notFound().build());
    }

}

It is very similar to the codes of Reactive stack, and but the methods return a ServerResponse instead of Mono<ServerResponse>.

Like the RouterFunctionDSL feature provided in Reactive stack, the routing rules also can be written in Kotlin DSL.

 router {
        "/posts".nest {
            GET("", postHandler::all)
            GET("{id}", postHandler::get)
            POST("", postHandler::create)
            PUT("{id}", postHandler::update)
            DELETE("{id}", postHandler::delete)
        }

    }

Besides these, MockMvc also gets support of Kotlin DSL, you can write your tests in a fluent style like the following.

  @Test
  fun `Get all posts should ok`() {
        mockMvc
                .get("/posts") {
                    accept = APPLICATION_JSON
                    headers {
                        contentLanguage = Locale.ENGLISH
                    }
                }
                .andExpect {
                    status { isOk }
                    content { contentType(APPLICATION_JSON_UTF8) }
                    jsonPath("$[0].title") { value(containsString("post")) } 
                }
                .andDo {
                    print()
                }
    }

Check out the source codes from my Github , and compare it with the codes that I had written to demonstrate Reactive stack .

spring-webmvc-functional-sample's People

Contributors

hantsy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.