Spring weblux builds responsive RESTful Web Services

This guide will guide you through creating "Hello, Spring!" Use the rest ful web service of Spring WebFlux (the new version of Spring Boot 2.0), and then use the service with WebClient (the new version of Spring Boot 2.0).

1. What will you build

You will build a RESTful web service using Spring Webflux and the WebClient consumer of the service. You will be able to see the output in both systems. And:

http://localhost:8080/hello

2. What do you need

  • About 15 minutes
  • Favorite text editor or IDE
  • JDK 1.8 and above
  • Gradle 4+ or Maven 3.2+
  • You can also import the code directly into your IDE:
    • Spring Tool Suite (STS)
    • IntelliJ IDEA

3. How to complete this guide

With most Spring Getting Started Like the guide, you can start from scratch and complete each step, or you can skip the basic setup steps you are already familiar with. Either way, you'll end up with working code.

To start from scratch, go to“ Start with Spring Initializr".

To skip these basic steps, perform the following steps:

When you are finished, you can check your results with the code GS reactive rest Service / complete

4. Start with Spring Initializr

You can use this Pre initialized items And click Generate to download the ZIP file. The project is configured to fit the examples in this tutorial.

Manually initialize the project:

  • Navigate to https://start.spring.io . This service will pull in all the dependencies required by the application and complete most of the setup work for you.
  • Choose Gradle or Maven and the language you want to use. This guide assumes that you have chosen Java.
  • Click Dependencies and select Spring Reactive Web.
  • Click 'Generate'.
  • Download the resulting ZIP file, which is an archive of the web application configured with your choice.

5. Create WebFlux Handler

We will start with a Greeting POJO, which will be serialized into JSON by our RESTful service:
src/main/java/hello/Greeting.java

package hello;


public class Greeting {

  private String message;

  public Greeting() {
  }

  public Greeting(String message) {
    this.message = message;
  }

  public String getMessage() {
    return this.message;
  }

  public void setMessage(String message) {
    this.message = message;
  }

  @Override
  public String toString() {
    return "Greeting{" +
        "message='" + message + '\'' +
        '}';
  }
}

In the Spring Reactive method, we use a handler to process the request and create the response, as shown below:
src/main/java/hello/GreetingHandler.java

package hello;

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 GreetingHandler {

  public Mono<ServerResponse> hello(ServerRequest request) {
    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
      .body(BodyInserters.fromValue(new Greeting("Hello, Spring!")));
  }
}

This simple responsive class always returns a "Hello, Spring!" "Greetings. It can return many other contents, including the item flow returned from the database, the item flow generated by calculation, and so on. Note the reactivity Code: the Mono object that holds the ServerResponse body.

6. Create a Router

In this application, we use a router to handle the unique route we exposed (/hello), as follows:
src/main/java/hello/GreetingRouter.java

package hello;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
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;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;

@Configuration(proxyBeanMethods = false)
public class GreetingRouter {

  @Bean
  public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {

    return RouterFunctions
      .route(GET("/hello").and(accept(MediaType.APPLICATION_JSON)), greetingHandler::hello);
  }
}

7. Create WebClient

The Spring RestTemplate class is essentially blocked. Therefore, we don't want to use it in responsive applications. For responsive applications, Spring provides the webclient class, which is non blocking. We use a webclient based implementation to consume our RESTful services:

src/main/java/hello/GreetingClient.java

package hello;

import reactor.core.publisher.Mono;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;

@Component
public class GreetingClient {

  private final WebClient client;

  // Spring Boot auto-configures a `WebClient.Builder` instance with nice defaults and customizations.
  // We can use it to create a dedicated `WebClient` for our component.
  public GreetingClient(WebClient.Builder builder) {
    this.client = builder.baseUrl("http://localhost:8080").build();
  }

  public Mono<String> getMessage() {
    return this.client.get().uri("/hello").accept(MediaType.APPLICATION_JSON)
        .retrieve()
        .bodyToMono(Greeting.class)
        .map(Greeting::getMessage);
  }

}

The WebClient class uses the responsive feature to save the content of the message in the form of Mono (returned by the getMessage method). This is using the functional API (not the imperative API) to link reaction operators.

It may take some time to adapt to the responsive api, but WebClient has some interesting features that can also be used in traditional Spring MVC applications.

You can also use WebClient to communicate with non responsive and blocking services.

8. Make the application executable

We will use the main() method to drive the application and get the Greeting message from the endpoint.

src/main/java/hello/Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
    GreetingClient greetingClient = context.getBean(GreetingClient.class);
    // We need to block for the content here or the JVM might exit before the message is logged
    System.out.println(">> message = " + greetingClient.getMessage().block());
  }
}

@SpringBootApplication is a convenient annotation that adds all of the following:

  • @Configuration: mark the class as the bean definition source of the application context.
  • @EnableAutoConfiguration: tell Spring Boot to start adding beans according to classpath settings, other beans, and various property settings. For example, if spring webmvc is on the classpath, this annotation marks the application as a web application and activates key behaviors, such as setting up DispatcherServlet.
  • @ComponentScan: tell Spring to find other components, configurations and services in the hello package and let it find the controller.

The main() method uses springapplication of spring boot Run () method to start the application. Have you noticed that there is no line of XML and no web XML file. This web application is 100% pure Java, and you don't need to deal with configuring any pipelines or infrastructure.

9. Build an executable JAR

You can run the application from the command line using Gradle or Maven. You can also build a separate executable jar file that contains all the necessary dependencies, classes, and resources, and run it. Building an executable jar makes it easy to deliver, version and deploy services as applications throughout the development lifecycle and across different environments.

If you use Gradle, you can use./gradlew bootrun to run the application. Alternatively, you can use./gradlew build to build the JAR file, and then run the JAR file, as shown below:

java -jar build/libs/gs-reactive-rest-service-0.1.0.jar

If you use Maven, you can use./mvnw spring boot: run to run this application. Alternatively, you can use the./mvnw clean package to build the JAR file, and then run the JAR file, as shown below:

java -jar target/gs-reactive-rest-service-0.1.0.jar

Show log output. The service should start and run in a few seconds.

Once the service is started, you will see a line of code:

>> message = Hello, Spring!

This line is from the responsive content that WebClient is using. Of course, you can do more interesting processing of the output than putting it into system Out.

10. Test application

Now that the application is running, you can test it. First, you can open the browser and access http://localhost:8080/hello , and see "Hello, Spring!" In this guide, we also created a test class to let you start testing with the WebTestClient class.

src/test/java/hello/GreetingRouterTest.java

package hello;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(SpringExtension.class)
//  We create a `@SpringBootTest`, starting an actual server on a `RANDOM_PORT`
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GreetingRouterTest {

  // Spring Boot will create a `WebTestClient` for you,
  // already configure and ready to issue requests against "localhost:RANDOM_PORT"
  @Autowired
  private WebTestClient webTestClient;

  @Test
  public void testHello() {
    webTestClient
      // Create a GET request to test an endpoint
      .get().uri("/hello")
      .accept(MediaType.APPLICATION_JSON)
      .exchange()
      // and use the dedicated DSL to test assertions against the response
      .expectStatus().isOk()
      .expectBody(Greeting.class).value(greeting -> {
        assertThat(greeting.getMessage()).isEqualTo("Hello, Spring!");
    });
  }
}

11. Summary

congratulations! You have developed a responsive Spring application, including a WebClient using RESTful services!

Want to write new guides or contribute to existing ones? Please check our Submission Guide.

Tags: Spring Spring MVC RESTful

Posted by shinagawa on Wed, 03 Aug 2022 22:06:38 +0530