Spring WebFlux PUT and DELETE Request

By Arvind Rai, September 19, 2020
This page will walk through Spring WebFlux PUT and DELETE request example. The Spring REST reactive endpoints can be created by using annotation based web framework as well as functional web framework. In functional web framework, the Spring RouterFunctions is the central entry point. The inner class RouterFunctions.Builder provides methods such as GET(), POST(), PUT(), DELETE() etc. The RouterFunctions.Builder is obtained via RouterFunctions.route() method.
On this page we will create a Spring Boot application to serve HTTP PUT and DELETE request using functional web framework. By default Spring Boot uses Reactor as reactive library and Netty as server.

Technologies Used

Find the technologies being used in our example.
1. Java 11
2. Spring 5.2.8.RELEASE
3. Spring Boot 2.3.2.RELEASE
4. Maven 3.5.2

Create PUT Request Entry Point

Find the PUT() method syntax from The RouterFunctions.Builder.
1.
RouterFunctions.Builder PUT(String pattern,
                            HandlerFunction<ServerResponse> handlerFunction) 
The above PUT() method adds a route to the specified handlerFunction that handles all HTTP PUT requests matching the specified URL pattern.
2.
RouterFunctions.Builder PUT(String pattern,
                            RequestPredicate predicate,
                            HandlerFunction<ServerResponse> handlerFunction) 
The above PUT() method adds a route to the specified handlerFunction that handles all HTTP PUT requests matching the specified URL pattern and predicate.

Find the sample code.
@Bean
public RouterFunction<ServerResponse> root(BookHandler bookHandler) {
	return RouterFunctions.route()
	  .PUT("/updateBook", bookHandler::updateBook)
	  .PUT("/updateWriter", RequestPredicates.contentType(MediaType.APPLICATION_JSON), bookHandler::updateWriter)		  
	  .build();
} 

Create DELETE Request Entry Point

Find the DELETE() method syntax from The RouterFunctions.Builder.
1.
RouterFunctions.Builder DELETE(String pattern,
                               HandlerFunction<ServerResponse> handlerFunction) 
The above DELETE() method adds a route to the specified handlerFunction that handles all HTTP DELETE requests matching the specified URL pattern.
2.
RouterFunctions.Builder DELETE(String pattern,
                               RequestPredicate predicate,
                               HandlerFunction<ServerResponse> handlerFunction) 
The above DELETE() method adds a route to the specified handlerFunction that handles all HTTP DELETE requests matching the specified URL pattern and predicate.

Find the sample code.
@Bean
public RouterFunction<ServerResponse> root(BookHandler bookHandler) {
	return RouterFunctions.route()
	   .DELETE("/books/{id}", bookHandler::deleteBookById)
	   .DELETE("/writers/{id}", RequestPredicates.accept(MediaType.TEXT_PLAIN), bookHandler::deleteWriterById)
	   .build();
} 

Create Handler

1. Find the handler code to handle HTTP PUT request.
public Mono<ServerResponse> updateBook(ServerRequest request) {
	return request.bodyToMono(Book.class)
			.flatMap(book -> Mono.just(bookService.updateBook(book)))
			.flatMap(book -> ServerResponse.ok()
					.contentType(MediaType.APPLICATION_JSON)
					.body(BodyInserters.fromValue(book)));
} 
The ServerRequest and ServerResponse are Spring APIs that represents server-side HTTP request and response respectively.

2. Find the handler code to handle HTTP DELETE request.
public Mono<ServerResponse> deleteBookById(ServerRequest request) {
	return Mono.just(bookService.deleteBookById(Integer.parseInt(request.pathVariable("id"))))
			.flatMap(val -> {
				return ServerResponse.noContent().build();
			});
} 

Create Client with WebClient

Spring provides WebClient that is non-blocking, reactive client to perform HTTP requests. To create the instance of WebClient, we need to use WebClient.create() method. To perform the HTTP requests, WebClient provides the methods such as get(), post(), put(), delete() and head() etc.
Find the client code used in our demo application.
BookWebClient.java
package com.concretepage;
import org.springframework.web.reactive.function.client.WebClient;
public class BookWebClient {
	private WebClient client = WebClient.create("http://localhost:8080");

	public void updateBookDemo() {
		  client.put()
			.uri("/update")
			.bodyValue(new Book(101, "Android"))
			.exchange()
		        .flatMap(res -> res.bodyToMono(Book.class))
			.subscribe(book -> System.out.println("PUT: " + book.getId() + ", " + book.getName())); 
	}
	public void deleteBookByIdDemo() {
		  int id = 102;
		  client.delete()
			.uri("/books/" + id)
			.exchange()	
		        .subscribe(res -> System.out.println("DELETE: " + res.statusCode()));
	}	
} 

Server Code using Spring Boot

pom.xml
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.3.2.RELEASE</version>
	<relativePath/>
</parent>
<properties>
	<java.version>11</java.version>
</properties>
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-webflux</artifactId>
	</dependency>
</dependencies> 
BookRouter.java
package com.concretepage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
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;
@Configuration
public class BookRouter {
	@Bean
	public RouterFunction<ServerResponse> root(BookHandler bookHandler) {
		return RouterFunctions.route()
		  .PUT("/update", RequestPredicates.contentType(MediaType.APPLICATION_JSON), bookHandler::updateBook)
		  .DELETE("/books/{id}", RequestPredicates.accept(MediaType.TEXT_PLAIN), bookHandler::deleteBookById)
		  .build();
	}
} 
BookHandler.java
package com.concretepage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
@Component
public class BookHandler {
	@Autowired
	private BookService bookService;
	public Mono<ServerResponse> updateBook(ServerRequest request) {
		return request.bodyToMono(Book.class)
				.flatMap(book -> Mono.just(bookService.updateBook(book)))
				.flatMap(book -> ServerResponse.ok()
						.contentType(MediaType.APPLICATION_JSON)
						.body(BodyInserters.fromValue(book)));
	}	
	public Mono<ServerResponse> deleteBookById(ServerRequest request) {
		return Mono.just(bookService.deleteBookById(Integer.parseInt(request.pathVariable("id"))))
				.flatMap(val -> {
					return ServerResponse.noContent().build();
				});
	}
} 
BookService.java
package com.concretepage;
import org.springframework.stereotype.Service;
@Service
public class BookService {
	public Boolean deleteBookById(int id) {
		System.out.println("Book deleted with id " + id);
		return true;
	}
	public Book updateBook(Book book) {
		return new Book(book.getId(), book.getName() +" - updated");
	}
} 
Book.java
package com.concretepage;
public class Book {
	private int id;
	private String name;
	public Book() {}
	public Book(int id, String name) {
		this.id = id;
		this.name = name;
	}
        //Sets and Gets
} 
Application.java
package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
		BookWebClient bwc = new BookWebClient();
		bwc.updateBookDemo();
		bwc.deleteBookByIdDemo();		
	}
} 
To run the application, download the code and go to root directory of the project using command prompt and run the command.
mvn spring-boot:run 
Find the print screen of the output.
Spring WebFlux PUT and DELETE Request

References

Spring RouterFunctions
Spring WebFlux

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us