<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilkin</title>
    <description>The latest articles on DEV Community by Ilkin (@ilkin0).</description>
    <link>https://dev.to/ilkin0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F489373%2F4b1839aa-96c3-4186-8efc-2df2f9352ab9.jpeg</url>
      <title>DEV Community: Ilkin</title>
      <link>https://dev.to/ilkin0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ilkin0"/>
    <language>en</language>
    <item>
      <title>What is API Gateway exactly? Spring Cloud Gateway?</title>
      <dc:creator>Ilkin</dc:creator>
      <pubDate>Sun, 03 Mar 2024 20:57:21 +0000</pubDate>
      <link>https://dev.to/ilkin0/what-is-api-gateway-exactly-spring-cloud-gateway-486g</link>
      <guid>https://dev.to/ilkin0/what-is-api-gateway-exactly-spring-cloud-gateway-486g</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is an API Gateway?&lt;/li&gt;
&lt;li&gt;Simple Example for API Gateway&lt;/li&gt;
&lt;li&gt;Spring Cloud Gateway&lt;/li&gt;
&lt;li&gt;
API GW example with Spring Cloud Gateway

&lt;ul&gt;
&lt;li&gt;JAVA API&lt;/li&gt;
&lt;li&gt;Dynamic Routing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is an API Gateway?
&lt;/h2&gt;

&lt;p&gt;An application programming interface (API) gateway functions as a reverse proxy to receive all API calls, aggregates the services needed to fulfill them, and returns the appropriate result.&lt;br&gt;
All that clients must know is how to get to the API gateway. A consistent and steady point of access is provided by the&lt;br&gt;
API gateway, regardless of the offline status, or instability of the backend services.&lt;/p&gt;

&lt;p&gt;An API gateway not only services requests but also provides functionality to return requested data as the client's&lt;br&gt;
needs. Before forwarding an API request to the API endpoint for processing, an API gateway can apply the necessary pre and/or&lt;br&gt;
post-processing filters such as Single Sign-On (SSO), rate limiting, request validation, and tracing. An API gateway offers all these features and more, making APIs easier to maintain,&lt;br&gt;
secure, and design and use.&lt;br&gt;
At the end of the day, an API gateway simplifies external access and reduces communication complexity between&lt;br&gt;
microservices by acting as a single point of entry for several backend APIs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Simple Example for API Gateway
&lt;/h2&gt;

&lt;p&gt;The below diagram shows a simple and common way to use an API gateway:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxyg1wsh8ueoq5zk8669.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxyg1wsh8ueoq5zk8669.png" alt="API GW Example" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's break down this graph. The client wants to get all his Orders from the service and requests &lt;strong&gt;/getOrder&lt;/strong&gt; API.&lt;br&gt;
Client only knows this '/getOrder' and does not have any idea and access to all the rest services.&lt;/p&gt;

&lt;p&gt;First of all, we need to authenticate the user, let's think that we are using JWT for authentication. As soon as API GW&lt;br&gt;
receives the request(/getOrder), it tries to find the user and&lt;br&gt;
authenticate it to find whether the user has access to the specified API or not. So we are getting a JWT token from the&lt;br&gt;
header in API GW, and Requesting to AUTH service. AUTH service will decode JWT and request USER info, at the end of the auth flow, the AUTH service will return user access from the AUTH service and if the user has it, user info from the USER service. The second step will be returning the real requested data to the client, which is '/getOrder'. API GW starts to communicate to the ORDER service and returns the requested data.&lt;br&gt;
Even though we have communicated with &lt;strong&gt;API GW, AUTH, USER, ORDER&lt;/strong&gt; services separately. The user only aware of 1&lt;br&gt;
endpoint and do not have any idea of what or how we authenticate and return data. As from this example, API GW is a single-point&lt;br&gt;
of entry for the client.&lt;/p&gt;
&lt;h2&gt;
  
  
  Spring Cloud Gateway
&lt;/h2&gt;

&lt;p&gt;As the number of Microservices grows, the need for creating a gateway also increases. Modern Spring Cloud project also&lt;br&gt;
introduced API gateway solution for the Spring echo&lt;br&gt;
system, &lt;a href="https://spring.io/projects/spring-cloud-gateway"&gt;Spring Cloud Gateway&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This project provides libraries for building an API Gateway on top of Spring WebFlux or Spring WebMVC. Spring Cloud&lt;br&gt;
Gateway aims to provide a simple, yet effective way to route to APIs and provide cross-cutting concerns to them such&lt;br&gt;
as security, monitoring/metrics, and resiliency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This project is not only used for Gateway but also as a BFF framework(Backend for Frontend).&lt;br&gt;
It operates on a non-blocking API model and is built on Spring 5, Spring Boot 2, and Project Reactor / Webflux.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This project provides an API Gateway built on top of the Spring Ecosystem, including Spring 5, Spring Boot 2 and&lt;br&gt;
Project Reactor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Due to reactivity, it comes with Netty instead of Tomcat as a web server. In some cases, it might create ambiguity/issues when used with other Spring services.&lt;/p&gt;

&lt;p&gt;Even though this project focuses on the reactive server, there's an option to include a Servlet-based MVC and a non-reactive version of &lt;a href="https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway-server-mvc.html"&gt;this project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Spring Cloud GW provides all the necessary tools from out-of-box to create a GW. We have 2 options for creating and&lt;br&gt;
managing our Gateway.&lt;br&gt;
Java API and Dynamic Routing. Yes, this project not only provides Java APIs for creating our gateway with Java code but&lt;br&gt;
also we can create everything that we did with Java API with a simple YAML file. with this magic, we even do not have to know&lt;br&gt;
JAVA or SPRING to some extent. Let us continue with the above example.&lt;/p&gt;
&lt;h2&gt;
  
  
  API GW example with Spring Cloud Gateway
&lt;/h2&gt;

&lt;p&gt;What we will try to build is a simple Order/Product microservices, we will focus on 2 APIs:&lt;br&gt;
&lt;strong&gt;/getProducts&lt;/strong&gt; and &lt;strong&gt;makeOrder&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwcfvfodkpvd7bjcznr27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwcfvfodkpvd7bjcznr27.png" alt="Spring API GW Example" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have 2 microservices &lt;strong&gt;Orders&lt;/strong&gt; and &lt;strong&gt;Products&lt;/strong&gt;, and 2 API endpoints respectively: &lt;strong&gt;/orders and /products&lt;/strong&gt;.&lt;br&gt;
The client is aware of 2 APIs: &lt;strong&gt;orders/makeOrder and products/getProducts&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  JAVA API
&lt;/h3&gt;

&lt;p&gt;Let's start with Gateway. First, we will build with a Java API approach. Gateway is a lightweight, reactive(Netty-based), and simple Java app. Gateway consist of &lt;strong&gt;routes&lt;/strong&gt;, &lt;strong&gt;predicates&lt;/strong&gt; and&lt;br&gt;
&lt;strong&gt;filters&lt;/strong&gt; to customize these routes.&lt;/p&gt;

&lt;p&gt;We create a custom Config class to apply our customizations. The project provides us with a special Bean - &lt;strong&gt;RouteLocator&lt;/strong&gt; to&lt;br&gt;
easily configure our all incoming HTTP requests.&lt;br&gt;
This will be our main entry point for request locating.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Bean
    public RouteLocator gatewayRoutes(RouteLocatorBuilder routeLocatorBuilder) {
        return routeLocatorBuilder
                .routes()
                .route(
                        ConfigurationConstants.AUTH_SERVICE_ID,
                        getRoute(ConfigurationConstants.AUTH_SERVICE_ROOT, msAuthRoot))
                .route(
                        ConfigurationConstants.PRODUCT_SERVICE_ID,
                        getRoute(ConfigurationConstants.PRODUCTS_SERVICE_ROOT, msProductRoot))
                .route(
                        ConfigurationConstants.ORDER_SERVICE_ID,
                        getRoute(ConfigurationConstants.ORDERS_SERVICE_ROOT, msOrderRoot))
                .build();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we are building RoutLocate we are providing the &lt;strong&gt;route()&lt;/strong&gt; method, which will accept ID for the route and a Function&lt;br&gt;
to apply all necessary changes to the route. Below is a custom method to make it easier and more reusable route function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    private Function&amp;lt;PredicateSpec, Buildable&amp;lt;Route&amp;gt;&amp;gt; getRoute(String root, String uri) {
        return r -&amp;gt;
                r.path(root.concat("/**"))
                        .filters(filterSpec -&amp;gt; getGatewayFilterSpec(filterSpec, root))
                        .uri(uri);
    }

    private GatewayFilterSpec getGatewayFilterSpec(GatewayFilterSpec f, String serviceUri) {
        return f.rewritePath(
                        serviceUri.concat("(?&amp;lt;segment&amp;gt;.*)"), API_V1.concat(serviceUri).concat("${segment}"))
                .filter(jwtAuthenticationFilter);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we are passing to this routing method is root (e,g /products) and actual URI (e,g localhost:8082). What it means,&lt;br&gt;
when Client execute an API call to any endpoint(let assume our /products/getProducts) with '/products' root, first we&lt;br&gt;
are concatenating the path from the root (we are getting everything after root which is '/getProducts') and we are replacing the root with our internal API which is (e,g localhost:8082).&lt;/p&gt;

&lt;p&gt;So when we are finishing request, client root + '/products/getProducts' became internally server root + '&lt;br&gt;
/api/v1/products/getProducts'.&lt;/p&gt;

&lt;p&gt;The final version of the Config class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@Slf4j
@RequiredArgsConstructor
@Configuration
public class GatewayConfig {
    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    @Value("${ms.product.root}")
    private String msProductRoot;

    @Value("${ms.auth.root}")
    private String msAuthRoot;

    @Value("${ms.order.root}")
    private String msOrderRoot;

    @Bean
    public RouteLocator gatewayRoutes(RouteLocatorBuilder routeLocatorBuilder) {
        return routeLocatorBuilder
                .routes()
                .route(
                        ConfigurationConstants.AUTH_SERVICE_ID,
                        getRoute(ConfigurationConstants.AUTH_SERVICE_ROOT, msAuthRoot))
                .route(
                        ConfigurationConstants.PRODUCT_SERVICE_ID,
                        getRoute(ConfigurationConstants.PRODUCTS_SERVICE_ROOT, msProductRoot))
                .route(
                        ConfigurationConstants.ORDER_SERVICE_ID,
                        getRoute(ConfigurationConstants.ORDERS_SERVICE_ROOT, msOrderRoot))
                .build();
    }

    private Function&amp;lt;PredicateSpec, Buildable&amp;lt;Route&amp;gt;&amp;gt; getRoute(String root, String uri) {
        return r -&amp;gt;
                r.path(root.concat("/**"))
                        .filters(filterSpec -&amp;gt; getGatewayFilterSpec(filterSpec, root))
                        .uri(uri);
    }

    private GatewayFilterSpec getGatewayFilterSpec(GatewayFilterSpec f, String serviceUri) {
        return f.rewritePath(
                        serviceUri.concat("(?&amp;lt;segment&amp;gt;.*)"), API_V1.concat(serviceUri).concat("${segment}"))
                .filter(jwtAuthenticationFilter);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, this is pretty much how we handle the Gateway mechanism with Spring Cloud Gateway. But from the graph and API&lt;br&gt;
gateway section, we also discussed Authentication.&lt;br&gt;
We will create a JwtAuthenticationFilter, we will mock it instead of applying real implementation. before we rewrite our HTTP path, we can apply as many custom filters as we want.&lt;/p&gt;

&lt;p&gt;This is simply a reactive WebClient-based Auth implementation, To apply a Gateway filter we need to implement specific interface, &lt;strong&gt;GatewayFilter&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter implements GatewayFilter, Ordered {
  @Value("${security.auth.url}")
  private String authServiceBase;

  @Value("${security.auth.introspect-api}")
  private String authServiceIntrospect;

  @Override
  public Mono&amp;lt;Void&amp;gt; filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpRequest request = exchange.getRequest();

      WebClient webClient = WebClient.builder().baseUrl(authServiceBase).build();

      return webClient
          .get()
          .uri(authServiceIntrospect)
          .retrieve()
          .bodyToMono(Boolean.class)
          .flatMap(
              credentials -&amp;gt; {
                log.info("Starting authentication, ACCESS: {}", credentials);
                return chain.filter(exchange);
              })
          .onErrorResume(
              ex -&amp;gt; onError(exchange, "Failed to authenticate token.", HttpStatus.UNAUTHORIZED));
  }

  private Mono&amp;lt;Void&amp;gt; onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {
    log.error("ERROR ON CALL: {}", err);
    exchange.getResponse().setStatusCode(httpStatus);
    exchange.getResponse().getHeaders().set(HttpHeaders.CONTENT_TYPE, "text/plain");
    return exchange
        .getResponse()
        .writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(err.getBytes())));
  }


  @Override
  public int getOrder() {
    return -1;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what is happening, basically, in every Client call, we are always adding this JwtFilter, as we are doing in&lt;br&gt;
traditional SpringSecurity. In this API call, we are calling the Auth microservice with WebClient, for the simplicity we are just returning a 'true' as access granted in every request, this is the AuthController:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Slf4j
@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {
    @GetMapping("/introspect")
    public ResponseEntity&amp;lt;Boolean&amp;gt; hasAccess(){
        log.info("Starting to AUTH process...");
        return ResponseEntity.ok(Boolean.TRUE);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have Custom Routing, Flexible and reactive authentication, and a lightweight Spring app. We have implemented our drawing into code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Routing
&lt;/h3&gt;

&lt;p&gt;I have mentioned a dynamic way to create these routers as well. It compiles to the same Java code, but this is the simple version of our routing class as a dynamic version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway-service&lt;/span&gt;
  &lt;span class="na"&gt;cloud&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;gateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;order-service&lt;/span&gt;
          &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8082&lt;/span&gt;
          &lt;span class="na"&gt;predicates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Path=/orders/**&lt;/span&gt;
          &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;response-timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
            &lt;span class="na"&gt;connect-timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;product-service&lt;/span&gt;
          &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8083&lt;/span&gt;
          &lt;span class="na"&gt;predicates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Path=/product/**&lt;/span&gt;
          &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;response-timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;
            &lt;span class="na"&gt;connect-timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above YAML file, we can see we have created 2 Route, for each route we are giving uri, and Predicate which will&lt;br&gt;
be listened to capture requests. This Predicate can be customized based on app needs, or we can listen to query params as well. We can add metadata, I have added custom response and connect/timeout parameters for each Route in the example. This is just one of the Predicate/Filters, there's much more such as custom Circuit Breaker, Caching (With Redis as well), fallback URI, route-based Load Balancing, etc. Please check the official Spring documentation for the full details.&lt;/p&gt;

&lt;p&gt;Results of our Gateway:&lt;br&gt;&lt;br&gt;
Internal &lt;strong&gt;products&lt;/strong&gt; endpoint: localhost:8082/api/v1/products/getProducts&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9v7sgo1lcurt3eoh8kxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9v7sgo1lcurt3eoh8kxd.png" alt="spring-gw-ex1" width="603" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Internal &lt;strong&gt;orders&lt;/strong&gt; endpoint: localhost:8083/api/v1/orders/makeOrder&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr3hyemc1t4ebukq5oe4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flr3hyemc1t4ebukq5oe4.png" alt="spring-gw-ex2" width="569" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we talked about what is API Gateway, what is the common use case and why we need it. We talked about modern Spring Cloud project - Spring Cloud Gateway, which provides a simple, easy-to-use, and customizable way to create our Gateway.&lt;/p&gt;

&lt;p&gt;API gateway is a single point of entry for our application and all microservices. It makes not only routing easier but also we can make a single point for a common request/response model for the client. We can authenticate/validate our requests before routing them to our microservices, with that our services load will be much less, and they won't accept unrelated requests anymore. We can also include CircuitBreaker pattern and prevent API abuse for our endpoint, also Caching is a commonly used way for Gateways and much more.&lt;/p&gt;

&lt;p&gt;Nevertheless, we must not forget that, by introducing a Gateway, whether Spring Cloud or not, we are introducing an additional&lt;br&gt;
layer between the Client and our APIs, so with that, we have some tradeoffs as well, such as, we will get some response time gain due to an additional HTTP layer. As I mentioned, Gateway is a single point of entry, so it means we are creating a single point of failure as well, In case of Gateway is down, regardless of our other services, we will be unavailable at all. So Gateway becomes additional responsibility for the server.&lt;/p&gt;

&lt;p&gt;If we need to add custom filters to our routes, customize our routes, already have Spring ecosystem, and If APIs require more precise control API Gateway and Spring Cloud Gateway are very good choices and easy to pick up.&lt;/p&gt;

&lt;p&gt;The example project presented here can be found in&lt;br&gt;
my &lt;a href="https://github.com/ilkin0/spring-cloud-gateway-tutorial"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>apigateway</category>
      <category>springboot</category>
      <category>java</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Understanding @Async in Spring Boot</title>
      <dc:creator>Ilkin</dc:creator>
      <pubDate>Mon, 29 Jan 2024 09:18:11 +0000</pubDate>
      <link>https://dev.to/ilkin0/understanding-async-in-spring-boot-2hjp</link>
      <guid>https://dev.to/ilkin0/understanding-async-in-spring-boot-2hjp</guid>
      <description>&lt;h2&gt;
  
  
  Asynchronous approach
&lt;/h2&gt;

&lt;p&gt;With the high development of hardware &amp;amp; software, modern applications become much more complex and demanding. Due to&lt;br&gt;
high demand engineers always try to find new ways to improve their application performance and responsiveness. One solution to slow-paced applications is the implementation of the Asynchronous approach. Asynchronous processing is a technique that is a process or function that executes a task to run concurrently, without waiting for one task to complete it before starting another. In this article, I will try to explore the Asynchronous approach and @Async annotation in Spring Boot, trying to explain the differences between multi-threading and concurrency, and when to use or avoid it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Asynchronous approach&lt;/li&gt;
&lt;li&gt;Table of contents&lt;/li&gt;
&lt;li&gt;What is @Async in Spring?&lt;/li&gt;
&lt;li&gt;How is @Async different from multithreading and Concurrency?&lt;/li&gt;
&lt;li&gt;When to use @Async and when to avoid it.&lt;/li&gt;
&lt;li&gt;Using @Async in a Spring Boot application.&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is @Async in Spring?
&lt;/h2&gt;

&lt;p&gt;The @Async annotation in Spring enables asynchronous processing of a method call. It instructs the framework to execute the method in a separate thread, allowing the caller to proceed without waiting for the method to complete. This&lt;br&gt;
improves the overall responsiveness and throughput of an application.&lt;/p&gt;

&lt;p&gt;To use @Async, you must first enable asynchronous processing in your application by adding the @EnableAsync annotation&lt;br&gt;
to a configuration class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@EnableAsync&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, annotate the method you want to execute asynchronously with the @Async annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AsyncService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Async&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;asyncMethod&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Perform time-consuming task&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How is @Async different from multithreading and Concurrency?
&lt;/h2&gt;

&lt;p&gt;Sometimes It might seem confusing to differentiate multithreading and concurrency from parallel execution, however, both are related to parallel execution. Each of them has their use case and implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;@Async annotation is Spring Framework-specific abstraction, which enables asynchronous execution. It gives the ability to use async with ease, handling all hard work in the background, such as thread creation, management, and execution. This allows users to focus on business logic rather than low-level details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multithreading is a general concept, commonly referring to the ability of an OS or program to manage multiple threads concurrently. As @Async helps us to do all hard work automatically, in this case, we can handle all this work manually and create a multithreading environment. Java has necessary classes such as &lt;strong&gt;Thread&lt;/strong&gt; and &lt;strong&gt;ExecutorService&lt;/strong&gt; to create and work with multithreading.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concurrency is a much broader concept, and it covers both multithreading and parallel execution techniques. It is the&lt;br&gt;
ability of a system to execute multiple tasks simultaneously, on one or more processors across.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, @Async is a higher-level abstraction that simplifies asynchronous processing for developers, on the other hand, multithreading and concurrency are more about to manual management of parallel execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use @Async and when to avoid it.
&lt;/h2&gt;

&lt;p&gt;It seems very intuitive to use an asynchronous approach, however, it must be taken into account, there's do's and don'ts for this approach as well.&lt;/p&gt;

&lt;p&gt;Use @Async when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have independent, time-consuming tasks that can run concurrently without affecting the application's responsiveness.&lt;/li&gt;
&lt;li&gt;You want a simple and clean way to enable asynchronous processing without diving into low-level thread management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid using @Async when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The tasks you want to execute asynchronously have complex dependencies or need a lot of coordinating. In such cases, you might need to use more advanced concurrency APIs, like &lt;strong&gt;CompletableFuture&lt;/strong&gt;, or reactive programming libraries
like Project Reactor.&lt;/li&gt;
&lt;li&gt;You must have precise control over how threads are managed., such as custom thread pools or advanced synchronization mechanisms. In these cases, consider using Java's &lt;strong&gt;ExecutorService&lt;/strong&gt; or other concurrency utilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using @Async in a Spring Boot application.
&lt;/h2&gt;

&lt;p&gt;In this example, we will create a simple Spring Boot application that demonstrates the use of @Async.&lt;br&gt;
Let's create a simple Order management service.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a new Spring Boot project with minimum dependency requirements:&lt;br&gt;&lt;br&gt;
&lt;code&gt;org.springframework.boot:spring-boot-starter&lt;/code&gt;&lt;br&gt;
&lt;code&gt;org.springframework.boot:spring-boot-starter-web&lt;/code&gt;&lt;br&gt;
Web dependency is for REST endpoint demonstration purpose. @Async comes with boot starter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the @EnableAsync annotation to the main class or Application Config class, if we are using it.:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="nd"&gt;@EnableAsync&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AsyncDemoApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AsyncDemoApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@EnableAsync&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;For the optimal solution, what we can do is, create a custom Executor bean and customize it as per our needs in the
same Configuration class:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;   &lt;span class="nd"&gt;@Configuration&lt;/span&gt;
   &lt;span class="nd"&gt;@EnableAsync&lt;/span&gt;
   &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

     &lt;span class="nd"&gt;@Bean&lt;/span&gt;
     &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Executor&lt;/span&gt; &lt;span class="nf"&gt;getAsyncExecutor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="nc"&gt;ThreadPoolTaskExecutor&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ThreadPoolTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
       &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCorePoolSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMaxPoolSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setQueueCapacity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setThreadNamePrefix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AsyncThread-"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
       &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration, we have control over max and default thread pool size. As well as other useful customizations.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an OrderService class with @Async methods:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Async&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveOrderDetails&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Async&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;saveOrderDetailsFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Execute method with return type + "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello From CompletableFuture. Order: "&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completedFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@Async&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello From CompletableFuture CHAIN. Order: "&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;completedFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we did here is create 3 different Async methods. First &lt;code&gt;saveOrderDetails&lt;/code&gt; service is a straightforward asynchronous&lt;br&gt;
service, which will start doing the computing asynchronously. If we want to use modern asynchronous Java features&lt;br&gt;
like &lt;code&gt;CompletableFuture&lt;/code&gt;, we can achieve it with &lt;code&gt;saveOrderDetailsFuture&lt;/code&gt; service. With this service, we can call a thread to wait for the result of an @Async. It should be noted that &lt;code&gt;CompletableFuture.get()&lt;/code&gt; will block until the result is available. If we want to perform further asynchronous operations when the result is available, we can use &lt;code&gt;thenApply&lt;/code&gt;, &lt;code&gt;thenAccept&lt;/code&gt;, or other methods provided by CompletableFuture.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a REST controller to trigger the asynchronous method:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AsyncController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrderController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orderService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/process"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PROCESSING STARTED"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveOrderDetails&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/process/future"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;processFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExecutionException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PROCESSING STARTED"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;orderDetailsFuture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveOrderDetailsFuture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderDetailsFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/process/future/chain"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;processFutureChain&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExecutionException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PROCESSING STARTED"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;computeResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;computeResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;thenApply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;thenAccept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we access the &lt;code&gt;/process&lt;/code&gt; endpoint, the server will return a response right away, while&lt;br&gt;
the &lt;code&gt;saveOrderDetails()&lt;/code&gt; continues to execute in the background. After 2 seconds, the service will complete. Second endpoint - &lt;code&gt;/process/future&lt;/code&gt; will use our second option which is &lt;code&gt;CompletableFuture&lt;/code&gt; In this case after 5 seconds, the service will complete, and store the result in &lt;code&gt;CompletableFuture&lt;/code&gt; we can further use &lt;code&gt;future.get()&lt;/code&gt; to access the result. In the last endpoint -&lt;code&gt;/process/future/chain&lt;/code&gt;, we optimized and used asynchronous computations. Controller using the same service method for &lt;code&gt;CompletableFuture&lt;/code&gt;, however right after the future, we are using &lt;code&gt;thenApply&lt;/code&gt;, &lt;code&gt;thenAccept&lt;/code&gt; methods. The server returns a response right away, we do not need to wait for 5 seconds, and computation will be done background. The most important point, in this case, is a call to async service, in our case &lt;code&gt;compute()&lt;/code&gt; must be done from the outside of the same class. If we use @Async on a method and call it within the same class, it won't work. This is because Spring uses proxies to add asynchronous behavior, and calling the method internally bypasses the proxy. To make it work, we can either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move the @Async methods to a separate service or component.&lt;/li&gt;
&lt;li&gt;Use ApplicationContext to get the proxy and call the method on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The @Async annotation in Spring is a powerful tool for enabling asynchronous processing in applications. By using @Async, we don't need to go into the complexities of concurrency management and multithreading to enhance the responsiveness and performance of our application. But to decide when to use @Async or go with alternative concurrency&lt;br&gt;
utilities, it's important to know its limitations and use cases. This is &lt;a href="https://github.com/ilkin0/spring-boot-async"&gt;the link&lt;/a&gt; for the project used on this blog.&lt;/p&gt;

&lt;p&gt;You can check my blog website as well: &lt;a href="https://blog.ilkinmehdiyev.com/posts/understanding-async-java"&gt;https://blog.ilkinmehdiyev.com/posts/understanding-async-java&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>concurrency</category>
      <category>springboot</category>
      <category>multithread</category>
    </item>
  </channel>
</rss>
