JAVA-14288 Rename spring-5-reactive-modules to spring-reactive-modules (#12659)
* JAVA-14288 Rename spring-5-reactive-modules to spring-reactive-modules * JAVA-14288 Remove failing module * JAVA-14288 Revert commenting spring-cloud-openfeign-2 module
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Baeldung: Static Content in Spring WebFlux</title>
|
||||
</head>
|
||||
<body>
|
||||
Example Spring Web Flux and web resources configuration
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
class Actor {
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
|
||||
public Actor() {
|
||||
}
|
||||
|
||||
public Actor(String firstname, String lastname) {
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toFormData;
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
public class FormHandler {
|
||||
|
||||
Mono<ServerResponse> handleLogin(ServerRequest request) {
|
||||
return request.body(toFormData())
|
||||
.map(MultiValueMap::toSingleValueMap)
|
||||
.filter(formData -> "baeldung".equals(formData.get("user")))
|
||||
.filter(formData -> "you_know_what_to_do".equals(formData.get("token")))
|
||||
.flatMap(formData -> ok().body(Mono.just("welcome back!"), String.class))
|
||||
.switchIfEmpty(ServerResponse.badRequest()
|
||||
.build());
|
||||
}
|
||||
|
||||
Mono<ServerResponse> handleUpload(ServerRequest request) {
|
||||
return request.body(toDataBuffers())
|
||||
.collectList()
|
||||
.flatMap(dataBuffers -> ok().body(fromValue(extractData(dataBuffers).toString())));
|
||||
}
|
||||
|
||||
private AtomicLong extractData(List<DataBuffer> dataBuffers) {
|
||||
AtomicLong atomicLong = new AtomicLong(0);
|
||||
dataBuffers.forEach(d -> atomicLong.addAndGet(d.readableByteCount()));
|
||||
return atomicLong;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = { "com.baeldung.functional" })
|
||||
public class FunctionalSpringBootApplication {
|
||||
|
||||
private static final Actor BRAD_PITT = new Actor("Brad", "Pitt");
|
||||
private static final Actor TOM_HANKS = new Actor("Tom", "Hanks");
|
||||
private static final List<Actor> actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS));
|
||||
|
||||
private RouterFunction<ServerResponse> routingFunction() {
|
||||
FormHandler formHandler = new FormHandler();
|
||||
|
||||
RouterFunction<ServerResponse> restfulRouter = route(GET("/"),
|
||||
serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"),
|
||||
serverRequest -> serverRequest.bodyToMono(Actor.class)
|
||||
.doOnNext(actors::add)
|
||||
.then(ok().build()));
|
||||
|
||||
return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld")))
|
||||
.andRoute(POST("/login"), formHandler::handleLogin)
|
||||
.andRoute(POST("/upload"), formHandler::handleUpload)
|
||||
.and(RouterFunctions.resources("/files/**", new ClassPathResource("files/")))
|
||||
.andNest(path("/actor"), restfulRouter)
|
||||
.filter((request, next) -> {
|
||||
System.out.println("Before handler invocation: " + request.path());
|
||||
return next.handle(request);
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean servletRegistrationBean() throws Exception {
|
||||
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler((WebHandler) toHttpHandler(routingFunction()))
|
||||
.filter(new IndexRewriteFilter())
|
||||
.build();
|
||||
ServletRegistrationBean registrationBean = new ServletRegistrationBean<>(new RootServlet(httpHandler), "/");
|
||||
registrationBean.setLoadOnStartup(1);
|
||||
registrationBean.setAsyncSupported(true);
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(FunctionalSpringBootApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Wrapper;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
|
||||
import org.springframework.boot.web.server.WebServer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
public class FunctionalWebApplication {
|
||||
|
||||
private static final Actor BRAD_PITT = new Actor("Brad", "Pitt");
|
||||
private static final Actor TOM_HANKS = new Actor("Tom", "Hanks");
|
||||
private static final List<Actor> actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS));
|
||||
|
||||
private RouterFunction<ServerResponse> routingFunction() {
|
||||
FormHandler formHandler = new FormHandler();
|
||||
|
||||
RouterFunction<ServerResponse> restfulRouter = route(GET("/actor"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/actor"), serverRequest -> serverRequest.bodyToMono(Actor.class)
|
||||
.doOnNext(actors::add)
|
||||
.then(ok().build()));
|
||||
|
||||
return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin)
|
||||
.andRoute(POST("/upload"), formHandler::handleUpload)
|
||||
.and(RouterFunctions.resources("/files/**", new ClassPathResource("files/")))
|
||||
.andNest(accept(MediaType.APPLICATION_JSON), restfulRouter)
|
||||
.filter((request, next) -> {
|
||||
System.out.println("Before handler invocation: " + request.path());
|
||||
return next.handle(request);
|
||||
});
|
||||
}
|
||||
|
||||
WebServer start() throws Exception {
|
||||
WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction());
|
||||
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler)
|
||||
.filter(new IndexRewriteFilter())
|
||||
.build();
|
||||
|
||||
Tomcat tomcat = new Tomcat();
|
||||
tomcat.setHostname("localhost");
|
||||
tomcat.setPort(9090);
|
||||
Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
|
||||
ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler);
|
||||
Wrapper servletWrapper = Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet);
|
||||
servletWrapper.setAsyncSupported(true);
|
||||
rootContext.addServletMappingDecoded("/", "httpHandlerServlet");
|
||||
|
||||
TomcatWebServer server = new TomcatWebServer(tomcat);
|
||||
server.start();
|
||||
return server;
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new FunctionalWebApplication().start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class IndexRewriteFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
|
||||
ServerHttpRequest request = serverWebExchange.getRequest();
|
||||
if (request.getURI()
|
||||
.getPath()
|
||||
.equals("/")) {
|
||||
return webFilterChain.filter(serverWebExchange.mutate()
|
||||
.request(builder -> builder.method(request.getMethod())
|
||||
.path("/test"))
|
||||
.build());
|
||||
}
|
||||
return webFilterChain.filter(serverWebExchange);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toFormData;
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class RootServlet extends ServletHttpHandlerAdapter {
|
||||
|
||||
public RootServlet() {
|
||||
this(WebHttpHandlerBuilder.webHandler((WebHandler) toHttpHandler(routingFunction()))
|
||||
.filter(new IndexRewriteFilter())
|
||||
.build());
|
||||
}
|
||||
|
||||
RootServlet(HttpHandler httpHandler) {
|
||||
super(httpHandler);
|
||||
}
|
||||
|
||||
private static final Actor BRAD_PITT = new Actor("Brad", "Pitt");
|
||||
private static final Actor TOM_HANKS = new Actor("Tom", "Hanks");
|
||||
private static final List<Actor> actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS));
|
||||
|
||||
private static RouterFunction<?> routingFunction() {
|
||||
|
||||
return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))).andRoute(POST("/login"), serverRequest -> serverRequest.body(toFormData())
|
||||
.map(MultiValueMap::toSingleValueMap)
|
||||
.map(formData -> {
|
||||
System.out.println("form data: " + formData.toString());
|
||||
if ("baeldung".equals(formData.get("user")) && "you_know_what_to_do".equals(formData.get("token"))) {
|
||||
return ok().body(Mono.just("welcome back!"), String.class)
|
||||
.block();
|
||||
}
|
||||
return ServerResponse.badRequest()
|
||||
.build()
|
||||
.block();
|
||||
}))
|
||||
.andRoute(POST("/upload"), serverRequest -> serverRequest.body(toDataBuffers())
|
||||
.collectList()
|
||||
.map(dataBuffers -> {
|
||||
AtomicLong atomicLong = new AtomicLong(0);
|
||||
dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer()
|
||||
.array().length));
|
||||
System.out.println("data length:" + atomicLong.get());
|
||||
return ok().body(fromValue(atomicLong.toString()))
|
||||
.block();
|
||||
}))
|
||||
.and(RouterFunctions.resources("/files/**", new ClassPathResource("files/")))
|
||||
.andNest(path("/actor"), route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class)
|
||||
.doOnNext(actors::add)
|
||||
.then(ok().build())))
|
||||
.filter((request, next) -> {
|
||||
System.out.println("Before handler invocation: " + request.path());
|
||||
return next.handle(request);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.reactive;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Spring5ReactiveApplication{
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Spring5ReactiveApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.reactive.controller;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.reactive.model.Foo;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
@RestController
|
||||
public class FooReactiveController {
|
||||
|
||||
@GetMapping("/foos/{id}")
|
||||
public Mono<Foo> getFoo(@PathVariable("id") long id) {
|
||||
return Mono.just(new Foo(id, randomAlphabetic(6)));
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/foos")
|
||||
public Flux<Foo> getAllFoos2() {
|
||||
final Flux<Foo> foosFlux = Flux.fromStream(Stream.generate(() -> new Foo(new Random().nextLong(), randomAlphabetic(6))));
|
||||
final Flux<Long> emmitFlux = Flux.interval(Duration.ofSeconds(1));
|
||||
return Flux.zip(foosFlux, emmitFlux).map(Tuple2::getT1);
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/foos2")
|
||||
public Flux<Foo> getAllFoos() {
|
||||
final Flux<Foo> flux = Flux.<Foo> create(fluxSink -> {
|
||||
while (true) {
|
||||
fluxSink.next(new Foo(new Random().nextLong(), randomAlphabetic(6)));
|
||||
}
|
||||
}).sample(Duration.ofSeconds(1)).log();
|
||||
|
||||
return flux;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.reactive.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class PathPatternController {
|
||||
|
||||
@GetMapping("/spring5/{*id}")
|
||||
public String URIVariableHandler(@PathVariable String id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
@GetMapping("/s?ring5")
|
||||
public String wildcardTakingExactlyOneChar() {
|
||||
return "/s?ring5";
|
||||
}
|
||||
|
||||
@GetMapping("/spring5/*id")
|
||||
public String wildcardTakingZeroOrMoreChar() {
|
||||
return "/spring5/*id";
|
||||
}
|
||||
|
||||
@GetMapping("/resources/**")
|
||||
public String wildcardTakingZeroOrMorePathSegments() {
|
||||
return "/resources/**";
|
||||
}
|
||||
|
||||
@GetMapping("/{baeldung:[a-z]+}")
|
||||
public String regexInPathVariable(@PathVariable String baeldung) {
|
||||
return baeldung;
|
||||
}
|
||||
|
||||
@GetMapping("/{var1}_{var2}")
|
||||
public String multiplePathVariablesInSameSegment(@PathVariable String var1, @PathVariable String var2) {
|
||||
return "Two variables are var1=" + var1 + " and var2=" + var2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.springframework.web.reactive.function.server.HandlerFilterFunction;
|
||||
import org.springframework.web.reactive.function.server.HandlerFunction;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
|
||||
public class ExampleHandlerFilterFunction implements HandlerFilterFunction<ServerResponse, ServerResponse> {
|
||||
|
||||
@Override
|
||||
public Mono<ServerResponse> filter(ServerRequest serverRequest, HandlerFunction<ServerResponse> handlerFunction) {
|
||||
if (serverRequest.pathVariable("name").equalsIgnoreCase("test")) {
|
||||
return ServerResponse.status(FORBIDDEN).build();
|
||||
}
|
||||
return handlerFunction.handle(serverRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
public class ExampleWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
|
||||
serverWebExchange.getResponse().getHeaders().add("web-filter", "web-filter-test");
|
||||
return webFilterChain.filter(serverWebExchange);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
@Component
|
||||
class PlayerHandler {
|
||||
|
||||
Mono<ServerResponse> getName(ServerRequest request) {
|
||||
Mono<String> name = Mono.just(request.pathVariable("name"));
|
||||
return ok().body(name, String.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
|
||||
@Configuration
|
||||
public class PlayerRouter {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> route(PlayerHandler playerHandler) {
|
||||
return RouterFunctions
|
||||
.route(GET("/players/{name}"), playerHandler::getName)
|
||||
.filter(new ExampleHandlerFilterFunction());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@RestController
|
||||
public class UserController {
|
||||
|
||||
@GetMapping(path = "/users/{name}")
|
||||
public Mono<String> getName(@PathVariable String name) {
|
||||
return Mono.just(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.reactive.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class Foo {
|
||||
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.baeldung.reactive.responseheaders.controllers;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/response-header")
|
||||
public class ResponseHeaderController {
|
||||
|
||||
@GetMapping("/response-entity")
|
||||
public Mono<ResponseEntity<String>> usingResponseEntityBuilder() {
|
||||
String responseHeaderKey = "Baeldung-Example-Header";
|
||||
String responseHeaderValue = "Value-ResponseEntityBuilder";
|
||||
String responseBody = "Response with header using ResponseEntity (builder)";
|
||||
|
||||
return Mono.just(ResponseEntity.ok()
|
||||
.header(responseHeaderKey, responseHeaderValue)
|
||||
.body(responseBody));
|
||||
}
|
||||
|
||||
@GetMapping("/server-http-response")
|
||||
public Mono<String> usingServerHttpResponse(ServerHttpResponse response) {
|
||||
String responseHeaderKey = "Baeldung-Example-Header";
|
||||
String responseHeaderValue = "Value-ServerHttpResponse";
|
||||
String responseBody = "Response with header using ServerHttpResponse";
|
||||
|
||||
response.getHeaders().add(responseHeaderKey, responseHeaderValue);
|
||||
return Mono.just(responseBody);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.reactive.responseheaders.filter;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
public class AddResponseHeaderWebFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
exchange.getResponse()
|
||||
.getHeaders()
|
||||
.add("Baeldung-Example-Filter-Header", "Value-Filter");
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.reactive.responseheaders.functional.handlers;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
public class ResponseHeaderHandler {
|
||||
|
||||
public Mono<ServerResponse> useHandler(final ServerRequest request) {
|
||||
String responseHeaderKey = "Baeldung-Example-Header";
|
||||
String responseHeaderValue = "Value-Handler";
|
||||
String responseBody = "Response with header using Handler";
|
||||
|
||||
return ServerResponse.ok()
|
||||
.header(responseHeaderKey, responseHeaderValue)
|
||||
.body(Mono.just(responseBody),String.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.reactive.responseheaders.functional.routers;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import com.baeldung.reactive.responseheaders.functional.handlers.ResponseHeaderHandler;
|
||||
|
||||
@Configuration
|
||||
public class ResponseHeadersRouterFunctions {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> responseHeaderRoute(@Autowired ResponseHeaderHandler handler) {
|
||||
return RouterFunctions.route(RequestPredicates.GET("/functional-response-header/single-handler"), handler::useHandler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
class Actor {
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
|
||||
public Actor() {
|
||||
}
|
||||
|
||||
public Actor(String firstname, String lastname) {
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.Wrapper;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
|
||||
import org.springframework.boot.web.server.WebServer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
public class ExploreSpring5URLPatternUsingRouterFunctions {
|
||||
|
||||
private RouterFunction<ServerResponse> routingFunction() {
|
||||
|
||||
return route(GET("/t?st"), serverRequest -> ok().body(fromValue("Path /t?st is accessed"))).andRoute(GET("/test/{*id}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("id"))))
|
||||
.andRoute(GET("/baeldung/*Id"), serverRequest -> ok().body(fromValue("/baeldung/*Id path was accessed")))
|
||||
.andRoute(GET("/{var1}_{var2}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("var1") + " , " + serverRequest.pathVariable("var2"))))
|
||||
.andRoute(GET("/{baeldung:[a-z]+}"), serverRequest -> ok().body(fromValue("/{baeldung:[a-z]+} was accessed and baeldung=" + serverRequest.pathVariable("baeldung"))))
|
||||
.and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/")))
|
||||
.and(RouterFunctions.resources("/resources/**", new ClassPathResource("resources/")));
|
||||
}
|
||||
|
||||
WebServer start() throws Exception {
|
||||
WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction());
|
||||
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler)
|
||||
.filter(new IndexRewriteFilter())
|
||||
.build();
|
||||
|
||||
Tomcat tomcat = new Tomcat();
|
||||
tomcat.setHostname("localhost");
|
||||
tomcat.setPort(9090);
|
||||
Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
|
||||
ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler);
|
||||
Wrapper servletWrapper = Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet);
|
||||
servletWrapper.setAsyncSupported(true);
|
||||
rootContext.addServletMappingDecoded("/", "httpHandlerServlet");
|
||||
|
||||
TomcatWebServer server = new TomcatWebServer(tomcat);
|
||||
server.start();
|
||||
return server;
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new FunctionalWebApplication().start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toFormData;
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
public class FormHandler {
|
||||
|
||||
Mono<ServerResponse> handleLogin(ServerRequest request) {
|
||||
return request.body(toFormData())
|
||||
.map(MultiValueMap::toSingleValueMap)
|
||||
.filter(formData -> "baeldung".equals(formData.get("user")))
|
||||
.filter(formData -> "you_know_what_to_do".equals(formData.get("token")))
|
||||
.flatMap(formData -> ok().body(Mono.just("welcome back!"), String.class))
|
||||
.switchIfEmpty(ServerResponse.badRequest()
|
||||
.build());
|
||||
}
|
||||
|
||||
Mono<ServerResponse> handleUpload(ServerRequest request) {
|
||||
return request.body(toDataBuffers())
|
||||
.collectList()
|
||||
.flatMap(dataBuffers -> ok().body(fromValue(extractData(dataBuffers).toString())));
|
||||
}
|
||||
|
||||
private AtomicLong extractData(List<DataBuffer> dataBuffers) {
|
||||
AtomicLong atomicLong = new AtomicLong(0);
|
||||
dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer()
|
||||
.array().length));
|
||||
return atomicLong;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
|
||||
import org.springframework.boot.web.server.WebServer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
public class FunctionalWebApplication {
|
||||
|
||||
private static final Actor BRAD_PITT = new Actor("Brad", "Pitt");
|
||||
private static final Actor TOM_HANKS = new Actor("Tom", "Hanks");
|
||||
private static final List<Actor> actors = new CopyOnWriteArrayList<>(Arrays.asList(BRAD_PITT, TOM_HANKS));
|
||||
|
||||
private RouterFunction<ServerResponse> routingFunction() {
|
||||
FormHandler formHandler = new FormHandler();
|
||||
|
||||
RouterFunction<ServerResponse> restfulRouter = route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class)
|
||||
.doOnNext(actors::add)
|
||||
.then(ok().build()));
|
||||
|
||||
return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin)
|
||||
.andRoute(POST("/upload"), formHandler::handleUpload)
|
||||
.and(RouterFunctions.resources("/files/**", new ClassPathResource("files/")))
|
||||
.andNest(path("/actor"), restfulRouter)
|
||||
.filter((request, next) -> {
|
||||
System.out.println("Before handler invocation: " + request.path());
|
||||
return next.handle(request);
|
||||
});
|
||||
}
|
||||
|
||||
WebServer start() throws Exception {
|
||||
WebHandler webHandler = (WebHandler) toHttpHandler(routingFunction());
|
||||
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler)
|
||||
.filter(new IndexRewriteFilter())
|
||||
.build();
|
||||
|
||||
Tomcat tomcat = new Tomcat();
|
||||
tomcat.setHostname("localhost");
|
||||
tomcat.setPort(9090);
|
||||
Context rootContext = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
|
||||
ServletHttpHandlerAdapter servlet = new ServletHttpHandlerAdapter(httpHandler);
|
||||
Tomcat.addServlet(rootContext, "httpHandlerServlet", servlet);
|
||||
rootContext.addServletMappingDecoded("/", "httpHandlerServlet");
|
||||
|
||||
TomcatWebServer server = new TomcatWebServer(tomcat);
|
||||
server.start();
|
||||
return server;
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
new FunctionalWebApplication().start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class IndexRewriteFilter implements WebFilter {
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
|
||||
ServerHttpRequest request = serverWebExchange.getRequest();
|
||||
if (request.getURI()
|
||||
.getPath()
|
||||
.equals("/")) {
|
||||
return webFilterChain.filter(serverWebExchange.mutate()
|
||||
.request(builder -> builder.method(request.getMethod())
|
||||
.contextPath(request.getPath()
|
||||
.toString())
|
||||
.path("/test"))
|
||||
.build());
|
||||
}
|
||||
return webFilterChain.filter(serverWebExchange);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.reactive.util;
|
||||
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
public class CpuUtils {
|
||||
|
||||
private static OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
|
||||
|
||||
static Double getUsage() {
|
||||
return (operatingSystemMXBean.getSystemCpuLoad() / operatingSystemMXBean.getAvailableProcessors()) * 100;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.websession;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = {"com.baeldung"})
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.websession.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
|
||||
|
||||
@Configuration
|
||||
//@EnableRedisWebSession
|
||||
public class RedisConfig {
|
||||
/**
|
||||
@Bean
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory();
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.websession.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.ReactiveMapSessionRepository;
|
||||
import org.springframework.session.ReactiveSessionRepository;
|
||||
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Configuration
|
||||
@EnableSpringWebSession
|
||||
public class SessionConfig {
|
||||
|
||||
@Bean
|
||||
public ReactiveSessionRepository reactiveSessionRepository() {
|
||||
return new ReactiveMapSessionRepository(new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.websession.configuration;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.config.EnableWebFlux;
|
||||
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||
|
||||
@Configuration
|
||||
@EnableWebFlux
|
||||
public class WebFluxConfig implements ApplicationContextAware, WebFluxConfigurer {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.websession.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
|
||||
|
||||
@Configuration
|
||||
@EnableWebFluxSecurity
|
||||
public class WebFluxSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public MapReactiveUserDetailsService userDetailsService() {
|
||||
UserDetails admin = User
|
||||
.withUsername("admin")
|
||||
.password(encoder().encode("password"))
|
||||
.roles("ADMIN")
|
||||
.build();
|
||||
|
||||
UserDetails user = User
|
||||
.withUsername("user")
|
||||
.password(encoder().encode("password"))
|
||||
.roles("USER")
|
||||
.build();
|
||||
|
||||
return new MapReactiveUserDetailsService(admin, user);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain webSessionSpringSecurityFilterChain(ServerHttpSecurity http) {
|
||||
http.authorizeExchange()
|
||||
.anyExchange().authenticated()
|
||||
.and()
|
||||
.httpBasic()
|
||||
.securityContextRepository(new WebSessionServerSecurityContextRepository())
|
||||
.and()
|
||||
.formLogin();
|
||||
|
||||
http.csrf().disable();
|
||||
|
||||
return http.build();
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder encoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.websession.controller;
|
||||
|
||||
import com.baeldung.websession.transfer.CustomResponse;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@RestController
|
||||
public class SessionController {
|
||||
|
||||
@GetMapping("/websession/test")
|
||||
public Mono<CustomResponse> testWebSessionByParam(
|
||||
@RequestParam(value = "id") int id,
|
||||
@RequestParam(value = "note") String note,
|
||||
WebSession session) {
|
||||
|
||||
session.getAttributes().put("id", id);
|
||||
session.getAttributes().put("note", note);
|
||||
|
||||
CustomResponse r = new CustomResponse();
|
||||
r.setId((int) session.getAttributes().get("id"));
|
||||
r.setNote((String) session.getAttributes().get("note"));
|
||||
|
||||
return Mono.just(r);
|
||||
}
|
||||
|
||||
@GetMapping("/websession")
|
||||
public Mono<CustomResponse> getSession(WebSession session) {
|
||||
|
||||
session.getAttributes().putIfAbsent("id", 0);
|
||||
session.getAttributes().putIfAbsent("note", "Howdy Cosmic Spheroid!");
|
||||
|
||||
CustomResponse r = new CustomResponse();
|
||||
r.setId((int) session.getAttributes().get("id"));
|
||||
r.setNote((String) session.getAttributes().get("note"));
|
||||
|
||||
return Mono.just(r);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.websession.transfer;
|
||||
|
||||
public class CustomResponse {
|
||||
|
||||
private int id;
|
||||
private String note;
|
||||
|
||||
public CustomResponse() {}
|
||||
|
||||
public CustomResponse(int id, String note) {
|
||||
this.id = id;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return note;
|
||||
}
|
||||
|
||||
public void setNote(String note) {
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.baeldung.websocket;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Event {
|
||||
private String eventId;
|
||||
private String eventDt;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.websocket;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import org.springframework.web.reactive.socket.WebSocketMessage;
|
||||
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
|
||||
import org.springframework.web.reactive.socket.client.WebSocketClient;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class ReactiveJavaClientWebSocket {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
WebSocketClient client = new ReactorNettyWebSocketClient();
|
||||
client.execute(
|
||||
URI.create("ws://localhost:8080/event-emitter"),
|
||||
session -> session.send(
|
||||
Mono.just(session.textMessage("event-spring-reactive-client-websocket")))
|
||||
.thenMany(session.receive()
|
||||
.map(WebSocketMessage::getPayloadAsText)
|
||||
.log())
|
||||
.then())
|
||||
.block(Duration.ofSeconds(10L));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.baeldung.websocket;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ReactiveWebSocketApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ReactiveWebSocketApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.websocket;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.reactive.socket.WebSocketHandler;
|
||||
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
|
||||
|
||||
@Configuration
|
||||
public class ReactiveWebSocketConfiguration {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("ReactiveWebSocketHandler")
|
||||
private WebSocketHandler webSocketHandler;
|
||||
|
||||
@Bean
|
||||
public HandlerMapping webSocketHandlerMapping() {
|
||||
Map<String, WebSocketHandler> map = new HashMap<>();
|
||||
map.put("/event-emitter", webSocketHandler);
|
||||
|
||||
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
|
||||
handlerMapping.setOrder(1);
|
||||
handlerMapping.setUrlMap(map);
|
||||
return handlerMapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketHandlerAdapter handlerAdapter() {
|
||||
return new WebSocketHandlerAdapter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.websocket;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.socket.WebSocketHandler;
|
||||
import org.springframework.web.reactive.socket.WebSocketMessage;
|
||||
import org.springframework.web.reactive.socket.WebSocketSession;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import static java.time.LocalDateTime.now;
|
||||
import static java.util.UUID.randomUUID;
|
||||
|
||||
@Component("ReactiveWebSocketHandler")
|
||||
public class ReactiveWebSocketHandler implements WebSocketHandler {
|
||||
|
||||
private static final ObjectMapper json = new ObjectMapper();
|
||||
|
||||
private Flux<String> eventFlux = Flux.generate(sink -> {
|
||||
Event event = new Event(randomUUID().toString(), now().toString());
|
||||
try {
|
||||
sink.next(json.writeValueAsString(event));
|
||||
} catch (JsonProcessingException e) {
|
||||
sink.error(e);
|
||||
}
|
||||
});
|
||||
|
||||
private Flux<String> intervalFlux = Flux.interval(Duration.ofMillis(1000L))
|
||||
.zipWith(eventFlux, (time, event) -> event);
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(WebSocketSession webSocketSession) {
|
||||
return webSocketSession.send(intervalFlux
|
||||
.map(webSocketSession::textMessage))
|
||||
.and(webSocketSession.receive()
|
||||
.map(WebSocketMessage::getPayloadAsText).log());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
logging.level.root=INFO
|
||||
@@ -0,0 +1 @@
|
||||
hello
|
||||
@@ -0,0 +1 @@
|
||||
test
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1 @@
|
||||
test
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Baeldung: Spring 5 Reactive Client WebSocket (Browser)</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="events"></div>
|
||||
<script>
|
||||
var clientWebSocket = new WebSocket("ws://localhost:8080/event-emitter");
|
||||
clientWebSocket.onopen = function() {
|
||||
console.log("clientWebSocket.onopen", clientWebSocket);
|
||||
console.log("clientWebSocket.readyState", "websocketstatus");
|
||||
clientWebSocket.send("event-me-from-browser");
|
||||
}
|
||||
clientWebSocket.onclose = function(error) {
|
||||
console.log("clientWebSocket.onclose", clientWebSocket, error);
|
||||
events("Closing connection");
|
||||
}
|
||||
clientWebSocket.onerror = function(error) {
|
||||
console.log("clientWebSocket.onerror", clientWebSocket, error);
|
||||
events("An error occured");
|
||||
}
|
||||
clientWebSocket.onmessage = function(error) {
|
||||
console.log("clientWebSocket.onmessage", clientWebSocket, error);
|
||||
events(error.data);
|
||||
}
|
||||
function events(responseEvent) {
|
||||
document.querySelector(".events").innerHTML += responseEvent + "<br>";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<display-name>Spring Functional Application</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>functional</servlet-name>
|
||||
<servlet-class>com.baeldung.functional.RootServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
<async-supported>true</async-supported>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>functional</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
</web-app>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.baeldung.reactive.Spring5ReactiveApplication;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Spring5ReactiveApplication.class)
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.baeldung.functional;
|
||||
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromResource;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.web.server.WebServer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
|
||||
public class FunctionalWebApplicationIntegrationTest {
|
||||
|
||||
private static WebTestClient client;
|
||||
private static WebServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
server = new FunctionalWebApplication().start();
|
||||
client = WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + server.getPort())
|
||||
.build();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void destroy() {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception {
|
||||
client.get()
|
||||
.uri("/test")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("helloworld");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception {
|
||||
client.get()
|
||||
.uri("/")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("helloworld");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(1);
|
||||
formData.add("user", "baeldung");
|
||||
formData.add("token", "you_know_what_to_do");
|
||||
|
||||
client.post()
|
||||
.uri("/login")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.body(BodyInserters.fromFormData(formData))
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("welcome back!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(2);
|
||||
formData.add("user", "baeldung");
|
||||
formData.add("token", "try_again");
|
||||
|
||||
client.post()
|
||||
.uri("/login")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.body(BodyInserters.fromFormData(formData))
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isBadRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception {
|
||||
Resource resource = new ClassPathResource("/baeldung-weekly.png");
|
||||
client.post()
|
||||
.uri("/upload")
|
||||
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||
.body(fromResource(resource))
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo(String.valueOf(resource.contentLength()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenActors_whenAddActor_thenAdded() throws Exception {
|
||||
client.get()
|
||||
.uri("/actor")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBodyList(Actor.class)
|
||||
.hasSize(2);
|
||||
|
||||
client.post()
|
||||
.uri("/actor")
|
||||
.body(fromValue(new Actor("Clint", "Eastwood")))
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk();
|
||||
|
||||
client.get()
|
||||
.uri("/actor")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBodyList(Actor.class)
|
||||
.hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResources_whenAccess_thenGot() throws Exception {
|
||||
client.get()
|
||||
.uri("/files/hello.txt")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("hello");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.baeldung.reactive;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.reactive.model.Foo;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
public class FluxUnitTest {
|
||||
|
||||
public static final Random RANDOM = new Random();
|
||||
|
||||
@Test
|
||||
public void whenFluxIsConstructed_thenCorrect() {
|
||||
final Flux<Foo> flux = Flux.<Foo> create(fluxSink -> {
|
||||
for (int i = 0 ; i < 100 ; i++) {
|
||||
fluxSink.next(new Foo(RANDOM.nextLong(), randomAlphabetic(6)));
|
||||
}
|
||||
}).sample(Duration.ofSeconds(1)).log();
|
||||
|
||||
flux.subscribe();
|
||||
|
||||
assertNotNull(flux);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.EntityExchangeResult;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@WithMockUser
|
||||
@AutoConfigureWebTestClient(timeout = "10000")
|
||||
public class PlayerHandlerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@Test
|
||||
public void whenPlayerNameIsBaeldung_thenWebFilterIsApplied() {
|
||||
EntityExchangeResult<String> result = webTestClient.get().uri("/players/baeldung")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class)
|
||||
.returnResult();
|
||||
|
||||
assertEquals(result.getResponseBody(), "baeldung");
|
||||
assertEquals(result.getResponseHeaders().getFirst("web-filter"), "web-filter-test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenPlayerNameIsTest_thenHandlerFilterFunctionIsApplied() {
|
||||
webTestClient.get().uri("/players/test")
|
||||
.exchange()
|
||||
.expectStatus().isForbidden();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.baeldung.reactive.filters;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.EntityExchangeResult;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@WithMockUser
|
||||
public class UserControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@Test
|
||||
public void whenUserNameIsBaeldung_thenWebFilterIsApplied() {
|
||||
EntityExchangeResult<String> result = webTestClient.get().uri("/users/baeldung")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class)
|
||||
.returnResult();
|
||||
|
||||
assertEquals(result.getResponseBody(), "baeldung");
|
||||
assertEquals(result.getResponseHeaders().getFirst("web-filter"), "web-filter-test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() {
|
||||
webTestClient.get().uri("/users/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.baeldung.reactive.responseheaders;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class ResponseHeaderLiveTest {
|
||||
|
||||
private static final String BASE_URL = "http://localhost:8080";
|
||||
private static final String ANNOTATION_BASE_URL = BASE_URL + "/response-header";
|
||||
private static final String FUNCTIONAL_BASE_URL = BASE_URL + "/functional-response-header";
|
||||
private static final String SERVICE_SINGLE_RESPONSE_HEADER = "Baeldung-Example-Header";
|
||||
private static final String SERVICE_FILTER_RESPONSE_HEADER = "Baeldung-Example-Filter-Header";
|
||||
private static final String SERVICE_FILTER_RESPONSE_HEADER_VALUE = "Value-Filter";
|
||||
|
||||
private static WebTestClient client;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
client = WebTestClient.bindToServer()
|
||||
.baseUrl(BASE_URL)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingResponseEntityBuilderRequest_thenObtainResponseWithCorrectHeaders() {
|
||||
client = WebTestClient.bindToServer()
|
||||
.baseUrl(BASE_URL)
|
||||
.build();
|
||||
ResponseSpec response = client.get()
|
||||
.uri(ANNOTATION_BASE_URL + "/response-entity")
|
||||
.exchange();
|
||||
|
||||
response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-ResponseEntityBuilder")
|
||||
.expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingServerHttpResponseRequest_thenObtainResponseWithCorrectHeaders() {
|
||||
ResponseSpec response = client.get()
|
||||
.uri(ANNOTATION_BASE_URL + "/server-http-response")
|
||||
.exchange();
|
||||
|
||||
response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-ServerHttpResponse")
|
||||
.expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingFunctionalHandlerRequest_thenObtainResponseWithCorrectHeaders() {
|
||||
ResponseSpec response = client.get()
|
||||
.uri(FUNCTIONAL_BASE_URL + "/single-handler")
|
||||
.exchange();
|
||||
|
||||
response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-Handler")
|
||||
.expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.web.server.WebServer;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
public class ExploreSpring5URLPatternUsingRouterFunctionsIntegrationTest {
|
||||
|
||||
private static WebTestClient client;
|
||||
private static WebServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
server = new ExploreSpring5URLPatternUsingRouterFunctions().start();
|
||||
client = WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + server.getPort())
|
||||
.build();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void destroy() {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenGetPathWithSingleCharWildcard_thenGotPathPattern() throws Exception {
|
||||
client.get()
|
||||
.uri("/test")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("Path /t?st is accessed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenMultipleURIVariablePattern_thenGotPathVariable() throws Exception {
|
||||
client.get()
|
||||
.uri("/test/ab/cd")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("/ab/cd");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenGetMultipleCharWildcard_thenGotPathPattern() throws Exception {
|
||||
|
||||
client.get()
|
||||
.uri("/baeldung/tutorialId")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("/baeldung/*Id path was accessed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenGetMultiplePathVaribleInSameSegment_thenGotPathVariables() throws Exception {
|
||||
|
||||
client.get()
|
||||
.uri("/baeldung_tutorial")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("baeldung , tutorial");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenGetRegexInPathVarible_thenGotPathVariable() throws Exception {
|
||||
|
||||
client.get()
|
||||
.uri("/abcd")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("/{baeldung:[a-z]+} was accessed and baeldung=abcd");
|
||||
|
||||
client.get()
|
||||
.uri("/1234")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is4xxClientError();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResources_whenAccess_thenGot() throws Exception {
|
||||
client.get()
|
||||
.uri("/files/test/test.txt")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("test");
|
||||
|
||||
client.get()
|
||||
.uri("/files/hello.txt")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRouter_whenAccess_thenGot() throws Exception {
|
||||
client.get()
|
||||
.uri("/resources/test/test.txt")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("test");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.baeldung.reactive.urlmatch;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import com.baeldung.reactive.Spring5ReactiveApplication;
|
||||
import com.baeldung.reactive.controller.PathPatternController;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Spring5ReactiveApplication.class)
|
||||
@WithMockUser
|
||||
public class PathPatternsUsingHandlerMethodIntegrationTest {
|
||||
|
||||
private static WebTestClient client;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
client = WebTestClient.bindToController(new PathPatternController())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHandlerMethod_whenMultipleURIVariablePattern_then200() {
|
||||
|
||||
client.get()
|
||||
.uri("/spring5/baeldung/tutorial")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("/baeldung/tutorial");
|
||||
|
||||
client.get()
|
||||
.uri("/spring5/baeldung")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("/baeldung");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHandlerMethod_whenURLWithWildcardTakingZeroOrMoreChar_then200() {
|
||||
|
||||
client.get()
|
||||
.uri("/spring5/userid")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("/spring5/*id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHandlerMethod_whenURLWithWildcardTakingExactlyOneChar_then200() {
|
||||
|
||||
client.get()
|
||||
.uri("/string5")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("/s?ring5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHandlerMethod_whenURLWithWildcardTakingZeroOrMorePathSegments_then200() {
|
||||
|
||||
client.get()
|
||||
.uri("/resources/baeldung")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("/resources/**");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHandlerMethod_whenURLWithRegexInPathVariable_thenExpectedOutput() {
|
||||
|
||||
client.get()
|
||||
.uri("/abc")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("abc");
|
||||
|
||||
client.get()
|
||||
.uri("/123")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is4xxClientError();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHandlerMethod_whenURLWithMultiplePathVariablesInSameSegment_then200() {
|
||||
|
||||
client.get()
|
||||
.uri("/baeldung_tutorial")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.is2xxSuccessful()
|
||||
.expectBody()
|
||||
.equals("Two variables are var1=baeldung and var2=tutorial");
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Reference in New Issue
Block a user