Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Spring WebFlux: Writing Filters

DZone's Guide to

Spring WebFlux: Writing Filters

Spring WebFlux's approach to writing filters is a bit different from how you might be used to it in Spring MVC. Let's explore the differences and see what's changed.

· Java Zone ·
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

Spring WebFlux is the new reactive web framework available as part of Spring 5+. The way filters were written in a traditional Spring MVC based application (Servlet Filter, HandlerInterceptor) is very different from the way a filter is written in a Spring WebFlux-based application, and this post will briefly go over the WebFlux approach to Filters.

Approach 1: WebFilter

The first approach using WebFilter broadly affects all endpoints and covers WebFlux endpoints written in a functional style as well the endpoints that are written using an annotation style. A WebFilter in Kotlin look like this:

@Bean
fun sampleWebFilter(): WebFilter {
    return WebFilter { e: ServerWebExchange, c: WebFilterChain ->
        val l: MutableList<String> = e.getAttributeOrDefault(KEY, mutableListOf())
        l.add("From WebFilter")
        e.attributes.put(KEY, l)
        c.filter(e)
    }
}


The WebFilter adds a request attribute with the value being a collection where the filter is just putting in a message that it has intercepted the request.

Approach 2: HandlerFilterFunction

The second approach is more focused and covers only endpoints written using functional style. Here, specific RouterFunctions can be hooked up with a filter, along the following lines.

Consider a Spring WebFlux endpoint defined the following way:

@Bean
fun route(): RouterFunction<*> = router {
    GET("/react/hello", { r ->
        ok().body(fromObject(
                Greeting("${r.attribute(KEY).orElse("[Fallback]: ")}: Hello")
        ))
    POST("/another/endpoint", TODO())

    PUT("/another/endpoint", TODO())
})

}


A HandlerFilterFunction that intercepts these APIs alone can be added in a highly focused way along these lines:

fun route(): RouterFunction<*> = router {
    GET("/react/hello", { r ->
        ok().body(fromObject(
                Greeting("${r.attribute(KEY).orElse("[Fallback]: ")}: Hello")
        ))
    })

    POST("/another/endpoint", TODO())

    PUT("/another/endpoint", TODO())

}.filter({ r: ServerRequest, n: HandlerFunction<ServerResponse> ->
    val greetings: MutableList<String> = r.attribute(KEY)
            .map { v ->
                v as MutableList<String>
            }.orElse(mutableListOf())

    greetings.add("From HandlerFilterFunction")

    r.attributes().put(KEY, greetings)
    n.handle(r)
})


Note that there is no need to be explicit about the types in Kotlin — I have added it just to be clear about the types in some of the lambda expressions.

Conclusion

The WebFilter approach and the HandlerFilterFunction are very different from the Spring-WebMVC-based approach of writing filters using Servlet Specs or using HandlerInterceptors. This post summarizes the new approaches. For more information, I have samples available in my git repo, which goes over these in more detail.

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:
java ,spring webflux ,filters ,reactive programming ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}