Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirection inside reactive Spring Webflux REST controller

I'm creating simple controller server for spring reactive project. While setting redirection to another location, I have found an error when calling http://localhost:8080/:

There was an unexpected error (type=Internal Server Error, status=500).
ModelAttributeMethodArgumentResolver does not support multi-value reactive type wrapper: interface reactor.netty.http.server.HttpServerResponse
java.lang.IllegalStateException: ModelAttributeMethodArgumentResolver does not support multi-value reactive type wrapper: interface reactor.netty.http.server.HttpServerResponse
    at org.springframework.util.Assert.state(Assert.java:94)
    at org.springframework.web.reactive.result.method.annotation.ModelAttributeMethodArgumentResolver.resolveArgument(ModelAttributeMethodArgumentResolver.java:112)
    at org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:123)
    at org.springframework.web.reactive.result.method.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:190)
    at org.springframework.web.reactive.result.method.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:133)
    at org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.lambda$handle$1(RequestMappingHandlerAdapter.java:200)
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44)
...

This is the controller code:

import reactor.core.publisher.Mono;
import reactor.netty.http.server.HttpServerResponse;

@RestController
public class BaseController {
    @GetMapping("/")
    public Mono<Void> indexController(HttpServerResponse response) {

        return response.sendRedirect("/api/v1");
    }
// ...
}

I expected it to be redirected from localhost:8080/ to localhost:8080/api/v1. But I've got the above exception.

like image 799
MohamedAmin Samet Avatar asked Sep 09 '19 12:09

MohamedAmin Samet


People also ask

How do I redirect a spring boot controller?

Try a URL http://localhost:8080/HelloWeb/index and you should see the following result if everything is fine with your Spring Web Application. Click the "Redirect Page" button to submit the form and to get the final redirected page.

Can I use Springmvc and WebFlux together?

There are several reasons for this: Spring MVC can't run on Netty. both infrastructure will compete for the same job (for example, serving static resources, the mappings, etc) mixing both runtime models within the same container is not a good idea and is likely to perform badly or just not work at all.

How use redirect attribute in Spring MVC?

You can use RedirectAttributes to store flash attributes and they will be automatically propagated to the "output" FlashMap of the current request. A RedirectAttributes model is empty when the method is called and is never used unless the method returns a redirect view name or a RedirectView.

How does Spring WebFlux work internally?

What is Spring WebFlux ? Spring WebFlux is parallel version of Spring MVC and supports fully non-blocking reactive streams. It support the back pressure concept and uses Netty as inbuilt server to run reactive applications. If you are familiar with Spring MVC programming style, you can easily work on webflux also.


2 Answers

Redirecting with Controller MVC good-old approach:

import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.net.URI;

@RestController
public class Controller {
    @GetMapping("/")
    public Mono<Void> indexController(ServerHttpResponse response) {
        response.setStatusCode(HttpStatus.PERMANENT_REDIRECT);
        response.getHeaders().setLocation(URI.create("/api/v1"));
        return response.setComplete();
    }
}

If someone would prefer functional Router/Handler approach might investigate: How to redirect a request in spring webflux?.

@Bean
RouterFunction<ServerResponse> routerFunction() {
    return route(GET("/"), req ->
            ServerResponse.temporaryRedirect(URI.create("/api/v1"))
                    .build());
}
like image 120
Xarvalus Avatar answered Nov 10 '22 01:11

Xarvalus


When using @RestController a ResponseEntity can work as well (here implemented using kotlin coroutines) :

@RestController
class SomeController() {
  suspend fun someMethod() : ResponseEntity<Unit> {
    return ResponseEntity
      .status(HttpStatus.TEMPORARY_REDIRECT)
      .location(URI.create("/api/v1"))
      .build()
  }
}
like image 27
Stuck Avatar answered Nov 10 '22 00:11

Stuck