<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Mario Casari - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Mario Casari - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:23:59 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/mcasari/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ OpenFeign vs WebClient: How to Choose a REST Client for Your Spring Boot Project ]]>
                </title>
                <description>
                    <![CDATA[ When building microservices with Spring Boot, you’ll have to decide how the services will communicate with one another. The basic choices in terms of protocols are Messaging and REST. In this article we’ll discuss tools based on REST, which is a comm... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/best-choice-openfeign-or-webclient/</link>
                <guid isPermaLink="false">6841f2c63a801418642db429</guid>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Casari ]]>
                </dc:creator>
                <pubDate>Thu, 05 Jun 2025 19:40:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749152217156/dc3e8896-b084-4bec-a549-b51a821f7d69.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When building microservices with Spring Boot, you’ll have to decide how the services will communicate with one another. The basic choices in terms of protocols are Messaging and <a target="_blank" href="https://www.freecodecamp.org/news/tag/rest-api/">REST</a>. In this article we’ll discuss tools based on REST, which is a common protocol for microservices. Two well-known tools are <a target="_blank" href="https://codingstrain.com/rest-clients-with-openfeign-how-to-implement-them/"><strong>OpenFeign</strong></a> and <a target="_blank" href="https://docs.spring.io/spring-framework/reference/web/webflux-webclient.html"><strong>WebClient</strong></a>.</p>
<p>You’ll learn how they differ in their approaches, use cases, and design. You’ll then have the necessary information to make a proper choice.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-introduction-to-openfeign">Introduction to OpenFeign</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-introduction-to-webclient">Introduction to WebClient</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-main-differences">Main Differences</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-performance-considerations">Performance Considerations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-cases">Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-introduction-to-openfeign">Introduction to OpenFeign</h2>
<p>OpenFeign is an HTTP client tool developed originally by Netflix and now maintained as an open-source community project. In the Spring Cloud ecosystem, OpenFeign allows you to define REST clients using annotated Java interfaces, reducing boilerplate code.</p>
<p>A basic OpenFeign client looks like this:</p>
<pre><code class="lang-java"><span class="hljs-meta">@FeignClient(name = "book-service")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">BookClient</span> </span>{
    <span class="hljs-meta">@GetMapping("/books/{id}")</span>
    <span class="hljs-function">User <span class="hljs-title">getBookById</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable("id")</span> Long id)</span></span>;
}
</code></pre>
<p>You can then inject <code>BookClient</code> like any Spring Bean:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookService</span> </span>{
    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> BookClient bookClient;

    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getBook</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">return</span> bookClient.getBookById(id);
    }
}
</code></pre>
<p>OpenFeign is well integrated with Spring Cloud Discovery Service (Eureka), Spring Cloud Config, and Spring Cloud LoadBalancer. This makes it perfect for service-to-service calls in a microservice architecture based on Spring Cloud. It has several important features.</p>
<ul>
<li><p>Declarative syntax: It uses interfaces and annotations to define HTTP clients, avoiding manual request implementation.</p>
</li>
<li><p>Spring Cloud integration: It integrates well with the components of Spring Cloud, like Service Discovery (Eureka), Spring Config, and Load Balancer.</p>
</li>
<li><p>Retry and fallback mechanisms: It can be easily integrated with Spring Cloud Circuit Breaker or Resilience4j.</p>
</li>
<li><p>Custom configurations: You can customize many aspects, like headers, interceptors, logging, timeouts, and encoders/decoders.</p>
</li>
</ul>
<h2 id="heading-introduction-to-webclient">Introduction to WebClient</h2>
<p>WebClient is a reactive HTTP client, and it’s part of the <a target="_blank" href="https://medium.com/@bolot.89/an-introduction-to-spring-webflux-reactive-programming-made-easy-f70050f4c6c6"><strong>Spring WebFlux</strong></a> module. It is mainly based on non-blocking asynchronous HTTP communication, but it can also deal with synchronous calls.</p>
<p>While OpenFeign follows a declarative design, WebClient offers an imperative, fluent API.</p>
<p>Here’s a basic example of using WebClient synchronously:</p>
<pre><code class="lang-java">WebClient client = WebClient.create(<span class="hljs-string">"http://book-service"</span>);

User user = client.get()
        .uri(<span class="hljs-string">"/books/{id}"</span>, <span class="hljs-number">1L</span>)
        .retrieve()
        .bodyToMono(Book.class)
        .block(); <span class="hljs-comment">// synchronous</span>
</code></pre>
<p>Or asynchronously:</p>
<pre><code class="lang-java">Mono&lt;User&gt; bookMono = client.get()
        .uri(<span class="hljs-string">"/books/{id}"</span>, <span class="hljs-number">1L</span>)
        .retrieve()
        .bodyToMono(Book.class);
</code></pre>
<p>Being designed to be non-blocking and reactive, WebClient gives its best with high-throughput, I/O intensive operations. This is particularly true if the entire stack is reactive.</p>
<h2 id="heading-main-differences">Main Differences</h2>
<h3 id="heading-programming-model">Programming Model</h3>
<ul>
<li><p><strong>OpenFeign</strong>: Declarative. You just have to define interfaces. The framework will provide implementations of those interfaces.</p>
</li>
<li><p><strong>WebClient</strong>: Programmatic. You use an imperative, fluent API to implement HTTP calls.</p>
</li>
</ul>
<h3 id="heading-synchronousasynchronous-calls">Synchronous/Asynchronous Calls</h3>
<ul>
<li><p><strong>OpenFeign</strong>: Based on synchronous calls. You require customization or third-party extensions to implement asynchronous behavior.</p>
</li>
<li><p><strong>WebClient</strong>: Asynchronous and non-blocking. It fits well with systems based on a reactive stack.</p>
</li>
</ul>
<h3 id="heading-integration-with-spring-cloud">Integration with Spring Cloud</h3>
<ul>
<li><p><strong>OpenFeign</strong>: It integrates well with the Spring Cloud stack, such as service discovery (Eureka), client-side load balancing, and circuit breakers.</p>
</li>
<li><p><strong>WebClient</strong>: It integrates with Spring Cloud, but additional configuration is required for some features, like load balancing.</p>
</li>
</ul>
<h3 id="heading-boilerplate-code">Boilerplate Code</h3>
<ul>
<li><p><strong>OpenFeign</strong>: You have to define only the endpoint with Interfaces, and the rest is implemented automatically by the framework.</p>
</li>
<li><p><strong>WebClient</strong>: You have a little more code to write and more explicit configuration.</p>
</li>
</ul>
<h3 id="heading-error-handling">Error Handling</h3>
<ul>
<li><p><strong>OpenFeign</strong>: You require custom error handling or fallbacks by <a target="_blank" href="https://stackoverflow.com/questions/39349591/what-is-hystrix-in-spring">Hystrix</a> or <a target="_blank" href="https://codingstrain.com/how-to-implement-circuit-breaker-pattern-with-spring-cloud/">Resilience4j</a>.</p>
</li>
<li><p><strong>WebClient</strong>: Error handling is more flexible with operators like onStatus() and exception mapping.</p>
</li>
</ul>
<h2 id="heading-performance-considerations">Performance Considerations</h2>
<p>When high throughput is not the main concern, OpenFeign is a better choice, since it is well-suited for traditional, blocking applications where simplicity and developer productivity are more important than maximum throughput.</p>
<p>When you have a large number of concurrent requests, such as hundreds or thousands per second, with OpenFeign, you can encounter thread exhaustion problems unless you significantly increase the thread pool sizes. This results in higher memory consumption and increased CPU overhead. For a monolithic application with blocking operations, OpenFeign is better, because mixing blocking and non-blocking models is discouraged.</p>
<p>WebClient is more suitable if your application is I/O bound and has to handle heavy loads. Its non-blocking, reactive nature is excellent for those scenarios, because it can handle more concurrent requests with fewer threads. WebClient does not block a thread while waiting for a response, it releases it immediately to be reused for other work. It also provides a reactive feature called backpressure, used to control the data flow rate. This is useful when dealing with large data streams or when the speed at which clients consume data is too low. It's suited for applications that need to manage thousands of concurrent requests. It is more complex, though, and has a steeper learning curve.</p>
<h2 id="heading-use-cases">Use Cases</h2>
<p><strong>Use OpenFeign When:</strong></p>
<ul>
<li><p>You need to call other services in a Spring Cloud microservice architecture, with tight integration with Service Discovery and Spring Cloud LoadBalancer.</p>
</li>
<li><p>You prefer productivity and simplicity.</p>
</li>
<li><p>You’re bound to a synchronous, blocking model.</p>
</li>
</ul>
<p><strong>Use WebClient When:</strong></p>
<ul>
<li><p>You're using Spring WebFlux to develop the application.</p>
</li>
<li><p>You need full control over request/response handling.</p>
</li>
<li><p>You require high-performance, non-blocking communication.</p>
</li>
<li><p>You want more control over error handling and retry logic.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The architecture and performance requirements of your system guide the choice between OpenFeign and WebClient.</p>
<p>OpenFeign is ideal for synchronous REST calls in a Spring Cloud stack and helps in reducing boilerplate code. WebClient, on the other hand, gives its best for reactive and high-performance applications and is more flexible.</p>
<p>If you're building a traditional microservices system using Spring Boot and Spring Cloud, OpenFeign is most likely to be the obvious choice. If you're in the context of reactive programming or you have to handle thousands of concurrent connections, then WebClient would be a better choice.</p>
<p>Understanding both tools, their pros and cons, is important to make the proper choice.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Perform Load Testing in Spring Boot with Gatling ]]>
                </title>
                <description>
                    <![CDATA[ To evaluate the performance of a system, you need a tool that can simulate its behavior in production.  For this purpose, you can use a software tool based on Scala called Gatling. This article will teach you how to integrate it into a Spring Boot ap... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-integrate-spring-boot-with-gatling/</link>
                <guid isPermaLink="false">66bb4548cd114247c2941f32</guid>
                
                    <category>
                        <![CDATA[ Gatling ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Casari ]]>
                </dc:creator>
                <pubDate>Mon, 08 Jul 2024 19:46:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/pexels-markusspiske-177598.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>To evaluate the performance of a system, you need a tool that can simulate its behavior in production. </p>
<p>For this purpose, you can use a software tool based on <a target="_blank" href="https://www.scala-lang.org/">Scala</a> called <a target="_blank" href="https://gatling.io/">Gatling</a>. This article will teach you how to integrate it into a <a target="_blank" href="https://spring.io/projects/spring-boot">Spring Boot</a> application and perform a load test.</p>
<h2 id="heading-main-concepts">Main Concepts</h2>
<p>Gatling is a tool you can use to execute load and performance tests. It can be used as a standalone application or integrated into a Maven or Gradle-based project.</p>
<p>Gatling is based on Scala, the <a target="_blank" href="https://en.wikipedia.org/wiki/Netty_(software)">Netty</a> framework, and the <a target="_blank" href="https://doc.akka.io/docs/akka/current/typed/guide/index.html">Akka</a> toolkit. It has an asynchronous, non-blocking architecture, which allows for high performance with minimum wasting of resources.</p>
<p>You can define tests by Gatling's flexible domain-specific language. You can also use its recorder function with a Graphical User Interface to capture user interactions in the browser and generate Scala scripts that can be modified and launched to perform a simulation.</p>
<p>In this article, you will learn how to integrate Gatling in a Spring Boot web application based on Maven. You will define a load test by its DSL, and then run it using the Gatling Maven plugin.</p>
<p>With Gatling, you can perform performance tests in a variety of ways. For instance, you can implement:</p>
<ul><li><b>Load Testing</b>: to see how a system performs under a specific load</li><li><b>Stress Testing</b>: to find the breaking point of a system, raising the load progressively</li><li><b>Soak Testing</b>: running the system with a steady load for a long time to find its pitfalls</li><li><b>Spike Testing</b>: to see how the system performs when swiftly raising the load to a peak and then going down</li></ul>

<p>The basic components by which Gatling implements the features described above are:</p>
<ul><li><b>Scenarios</b>: a series of steps performed by a virtual user</li><li><b>Feeders</b>: how data is provided to feed the scenarios</li><li><b>Injection</b>: a sort of a blueprint that states how the test is performed, in terms of number of virtual users, how they change in time, and so on</li></ul>

<h2 id="heading-spring-boot-gatling-integration">Spring Boot Gatling Integration</h2>
<p>In this article, you will start with a simple Spring Boot web application and implement and run a load test over it. You can find the source code of this sample application on <a target="_blank" href="https://github.com/mcasari/codingstrain/tree/main/spring-cloud-sample-libraryapp/libraryapp-testing-gatling-test">GitHub</a>.</p>
<p>Imagine you have a library and want to insert new books by their title. You can implement this minimal requirement using JPA by defining a Book entity, a repository class, a service class, and a controller with a <a target="_blank" href="https://codingstrain.com/spring-boot-for-cloud-rest-api-development/">REST</a> service mapping.</p>
<p>The REST service is defined as a POST call to a /book endpoint that saves a new book object. You can see the implementation in the code below:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping("/library")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookController</span> </span>{

    Logger logger = LoggerFactory.getLogger(BookController.class);

    <span class="hljs-meta">@Autowired</span>
    BookService bookService;

    <span class="hljs-meta">@PostMapping(value = "/book", consumes = "application/json", produces = "application/json")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Book <span class="hljs-title">createPerson</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> Book book)</span> </span>{
        <span class="hljs-keyword">return</span> bookService.save(book);
    }

}
</code></pre>
<p>To perform a load test on the above REST endpoint, you need to integrate Gatling. You can do this by setting some Maven dependencies first:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.gatling<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>gatling-app<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.7.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>


<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.gatling.highcharts<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>gatling-charts-highcharts<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.7.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>    

<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.github.javafaker<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>javafaker<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>0.15<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</code></pre>
<p>Then you also need a Maven plugin to execute the test:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.gatling<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>gatling-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.2.9<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">simulationClass</span>&gt;</span>com.codingstrain.springcloud.sample.libraryapp.books.BookSaveSimulation<span class="hljs-tag">&lt;/<span class="hljs-name">simulationClass</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
</code></pre>
<h2 id="heading-load-test-implementation">Load Test Implementation</h2>
<p>To implement a test, you need to extend the <code>io.gatling.javaapi.core.Simulation</code> class, as in the <code>BookSaveSimulation</code> class below:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.core.CoreDsl.StringBody;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.core.CoreDsl.global;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.core.CoreDsl.rampUsersPerSec;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.http.HttpDsl.http;

<span class="hljs-keyword">import</span> java.time.Duration;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Iterator;
<span class="hljs-keyword">import</span> java.util.Map;
<span class="hljs-keyword">import</span> java.util.stream.Stream;

<span class="hljs-keyword">import</span> com.github.javafaker.Faker;

<span class="hljs-keyword">import</span> io.gatling.javaapi.core.CoreDsl;
<span class="hljs-keyword">import</span> io.gatling.javaapi.core.OpenInjectionStep.RampRate.RampRateOpenInjectionStep;
<span class="hljs-keyword">import</span> io.gatling.javaapi.core.ScenarioBuilder;
<span class="hljs-keyword">import</span> io.gatling.javaapi.core.Simulation;
<span class="hljs-keyword">import</span> io.gatling.javaapi.http.HttpDsl;
<span class="hljs-keyword">import</span> io.gatling.javaapi.http.HttpProtocolBuilder;


<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookSaveSimulation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Simulation</span> </span>{


    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">BookSaveSimulation</span><span class="hljs-params">()</span> </span>{

        setUp(buildPostScenario()
            .injectOpen(injection())
            .protocols(setupProtocol())).assertions(global().responseTime()
          .max()
          .lte(<span class="hljs-number">10000</span>), global().successfulRequests()
          .percent()
          .gt(<span class="hljs-number">90d</span>));
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ScenarioBuilder <span class="hljs-title">buildPostScenario</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> CoreDsl.scenario(<span class="hljs-string">"Load POST Test"</span>)
            .feed(feedData())
            .exec(http(<span class="hljs-string">"create-book"</span>).post(<span class="hljs-string">"/library/book"</span>)
            .header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"application/json"</span>)
                .body(StringBody(<span class="hljs-string">"{ \"title\": \"${title}\" }"</span>)));
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Iterator &amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; feedData() {
        Faker faker = <span class="hljs-keyword">new</span> Faker();
        Iterator&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; iterator;
        iterator = Stream.generate(() -&amp;gt; {
              Map&amp;lt;String, Objectglt; stringObjectMap = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
            stringObjectMap.put(<span class="hljs-string">"title"</span>, faker.book()
                .title());
              <span class="hljs-keyword">return</span> stringObjectMap;
          })
          .iterator();
        <span class="hljs-keyword">return</span> iterator;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> HttpProtocolBuilder <span class="hljs-title">setupProtocol</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> HttpDsl.http.baseUrl(<span class="hljs-string">"http://localhost:8080"</span>)
          .acceptHeader(<span class="hljs-string">"application/json"</span>)
          .maxConnectionsPerHost(<span class="hljs-number">10</span>)
            .userAgentHeader(<span class="hljs-string">"Performance Test"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> RampRateOpenInjectionStep <span class="hljs-title">injection</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">int</span> totalUsers = <span class="hljs-number">100</span>;
        <span class="hljs-keyword">double</span> userRampUpPerInterval = <span class="hljs-number">10</span>;
        <span class="hljs-keyword">double</span> rampUpIntervalInSeconds = <span class="hljs-number">30</span>;

        <span class="hljs-keyword">int</span> rampUptimeSeconds = <span class="hljs-number">300</span>;
        <span class="hljs-keyword">int</span> duration = <span class="hljs-number">300</span>;
        <span class="hljs-keyword">return</span> rampUsersPerSec(userRampUpPerInterval / (rampUpIntervalInSeconds)).to(totalUsers)
            .during(Duration.ofSeconds(rampUptimeSeconds + duration));
    }
}
</code></pre>
<p>The <code>BoookSaveSimulation</code> class uses its constructor to do all the settings using the parent class <code>setUp</code> method. It first implements a scenario. Since the test's purpose is to simulate a real situation in production, the scenario represents the steps performed by a configured number of virtual users interacting with the system.</p>
<p>The scenario in the example executes a POST call to the /library/book endpoint, sending a single title parameter in the payload. The invoked service will save a new book by the passed title value. A class named <code>com.github.javafaker.Faker</code> produces title values automatically and implements the feeder component described earlier in the <code>Main Concepts</code> section.</p>
<p>Then the <code>injectOpen</code> method defines how the virtual users are added to the simulation. The injectOpen method implements the injection part using the so-called open mode. There are two different models of injection, <code>open</code> and <code>closed</code>.</p>
<p>The open model simulates a scenario in which new users can be added constantly and independently from the execution state of the others. This is the model used in this article's example. On the other hand, in the closed model, new users can be added only when all the others have terminated their tasks. This helps simulate a steady load on the system.</p>
<p>The open injection configuration in the example sets a total number of 100 users that are added progressively 10 at a time, every 30 seconds. Once all users have been added, the execution continues for 300 seconds.</p>
<p>The protocols method sets up the base URL, the data type expected in the response, the maximum number of connections per host, and the User-Agent header.</p>
<p>The last part of this set-up phase defines a couple of assertions to consider the test passed: a maximum response time lower than 10 seconds and a percentage of successful requests greater than 90%.</p>
<h2 id="heading-how-to-run-the-test">How to Run the Test</h2>
<p>To run the test, you first have to start the Spring Boot web application. You can do this, for instance, by going to the project base directory and execute the following command: <code>mvn spring-boot:run</code>. </p>
<p>Once the application is started, you can run the Gatling simulation by executing <code>mvn gatling:test</code>.</p>
<h2 id="heading-how-to-see-the-results">How to See the Results</h2>
<p>Once the test is terminated, you will find an index.html in the /target/gatling directory with all the measurements and several graphs.</p>
<p>The figure below displays all the results. It shows a list of the assertions and their outcome. Then, you can see the total number of requests, and how many requests have a positive or negative result. You have useful information about the response time: minimum, maximum, average, and standard deviation, and you also have the 50th, 75th, 95th, and 99th percentiles.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Summary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Summary of the test results</em></p>
<p>A chart shows the number of requests, with positive and negative outcomes, in a particular response time range, as in the following figure.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/GlobalInfo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Number of requests in particular response time ranges</em></p>
<p>Another graph shows the number of requests per second and how it changes depending on the number of active users.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/RequestsPerSecond.png" alt="Image" width="600" height="400" loading="lazy">
<em>Number of request per second and active users over time</em></p>
<p>You can also see in the next figure how the percentiles change over time, and with the number of active users at each point in time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Percentiles.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Evaluating the performance of a system is a complex task. Gatling makes things easy enough to integrate this kind of task with continuous integration. It gives you a comprehensive view and allows you to tweak the tests to find weaknesses and suggest solutions.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
