1

My Spring Boot Webflux-application (Netty) outputs HTML using Thymeleaf-templates. In one handler-method I use WebClient to authenticate with an external id-provider. Now I'd like to store the resulting authentication token in a session-variable so I can reuse it with subsequent Controller/Handler methods. If I store the token in a model variable, Spring/Webflux resolves the Mono before rendering and provides the resulting token-String for use by the view (Thymeleaf template). But I can't find a way to store the token in a session variable. WebSession is enough for me as I won't run the application with multiple nodes.

Code I've tried (Kotlin):

@PostMapping("/login")
fun login(@Valid loginForm: LoginForm, model: Model, webSession: WebSession): String {
  val tokenMono: Mono<String> = loginService.login(loginForm.email, loginForm.password)
  model.addAttribute("token", tokenMono) // works and the token is available as a String in resulting view template
  webSession.addAttribute("token", tokenMono) // session-variable "token" is null in subsequent requests.
  return "login/success"
}
mewers
  • 41
  • 5

1 Answers1

0

The following seems to work:

@PostMapping("/login")
fun login(@Valid loginForm: LoginForm, webSession: WebSession): Mono<String> {
   return loginService.login(loginForm.email, loginForm.password)
     .doOnNext { token ->
        webSession.attributes["token"] = token
     }
     .map { token -> "login/success" }
}

Key learnings:

  • The template view-name ("login/success" here) can be wrapped in a Mono.
  • Everything that needs to be done after the retrieval of a reactive type needs to be wrapped in one of the onXXX functions of Mono (maybe then works, too).
  • This also works for redirecting to a handler method that needs something from the reactive type's result. So say the original Mono is a future result of an R2DB insert. If I wanted to redirect to the resulting view, I could use .map { entity -> "redirect:/entity/${entity.id}" }.
mewers
  • 41
  • 5