<?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>Forem: João Victor Martins</title>
    <description>The latest articles on Forem by João Victor Martins (@j_a_o_v_c_t_r).</description>
    <link>https://forem.com/j_a_o_v_c_t_r</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%2F441606%2F5f6864cf-c0c0-46b8-9072-9580948d5ee6.jpg</url>
      <title>Forem: João Victor Martins</title>
      <link>https://forem.com/j_a_o_v_c_t_r</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/j_a_o_v_c_t_r"/>
    <language>en</language>
    <item>
      <title>Scopes in Coroutines - coroutineScope x supervisorScope</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Mon, 07 Oct 2024 12:45:14 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/scopes-in-coroutines-coroutinescope-x-supervisorscope-lad</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/scopes-in-coroutines-coroutinescope-x-supervisorscope-lad</guid>
      <description>&lt;p&gt;As a Kotlin developer, coroutines are an essential tool for writing efficient and performant code. When you know how to work with this tool, you can enhance your app's performance with simpler code. Writing code with coroutines is less complex than using other tools for asynchronous development, but, like any technology, you need to be aware of best practices to avoid potential issues. There are several key concepts you should understand when working with coroutines, including builders, scopes, contexts, and flows. In this post, I aim to explain the differences between coroutineScope and supervisorScope, starting with an introduction to scopes in coroutines.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scopes
&lt;/h1&gt;

&lt;p&gt;According to Kotlin's documentation, CoroutineScope defines a scope for new coroutines. Every coroutine builder (such as launch, async, etc.) is an extension of CoroutineScope and inherits its coroutineContext, automatically propagating all its elements and cancellation.&lt;/p&gt;

&lt;p&gt;In simple terms, a scope is required to create coroutines and execute tasks. You can create scopes in several ways, one of which is using the runBlocking builder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fla5eacdo4sdh4lxocdxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fla5eacdo4sdh4lxocdxw.png" alt=" " width="596" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the IDE shows a CoroutineScope after the curly brace. Inside this scope, you can create multiple coroutines. runBlocking is the easiest way to bridge from the non-coroutine world to the coroutine world, but be cautious when using it in production. As its name suggests, it is a blocking operation, which means it will block the main thread. If you remove runBlocking, the code won't compile because the launch builder won't be within a scope.&lt;/p&gt;

&lt;p&gt;There are two other common ways to create scopes: using supervisorScope and coroutineScope. Both are the main subjects of this post, and I will explain each one in the following sections. &lt;/p&gt;

&lt;h2&gt;
  
  
  coroutineScope
&lt;/h2&gt;

&lt;p&gt;coroutineScope is a function, and according to Kotlin's documentation, it is designed for concurrent decomposition of work. If any child coroutine in this scope fails, the scope fails, cancelling all other children. This function returns as soon as the given block and all its child coroutines are completed. An example of using a scope looks like this:&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="n"&gt;suspend&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;suspend&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;coroutineScope&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;executeOneDay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;executeOneDay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;suspend&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;executeOneDay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&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="s"&gt;"entrou"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numberOfItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some error"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;delay&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="kt"&gt;int&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;runCatching&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;teste&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfItems&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}.&lt;/span&gt;&lt;span class="na"&gt;onFailure&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="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&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;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;teste&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&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="s"&gt;"chegou no teste $int"&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;The first difference to note is the suspend keyword in the method signature. The function must be suspend to create a scope with coroutineScope. Unlike runBlocking, it does not block execution; instead, it utilizes suspend and resume activities. Let’s break down what this code does: The main() function calls the call() function. Inside call(), a suspend function, I create two coroutines using the launch builder within coroutineScope. Each coroutine calls the executeOneDay(int: Int) function with different parameters: 3 and 1.&lt;/p&gt;

&lt;p&gt;In executeOneDay, if the parameter is 1, the code delays for 1 second and generates an error; if it’s anything other than 1, it delays for 2 seconds and returns the number. Since both coroutines run asynchronously, one will generate an error while the other will not. When you execute this code, you will see "entrou" printed twice in your terminal, followed by the error message, terminating the program. This occurs because, when one coroutine fails, coroutineScope cancels all other coroutines. This behavior is expected, but if you want different behavior, you can use supervisorScope.&lt;/p&gt;

&lt;h1&gt;
  
  
  supervisorScope
&lt;/h1&gt;

&lt;p&gt;According to Kotlin's documentation, with supervisorScope, a failure of a child coroutine does not cause the scope to fail and does not affect other children. If we modify the previous code to use supervisorScope, the result will change:&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="n"&gt;suspend&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;suspend&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;supervisorScope&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;executeOneDay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;executeOneDay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;suspend&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;executeOneDay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&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="s"&gt;"entrou"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;numberOfItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"some error"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;delay&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="kt"&gt;int&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;runCatching&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;teste&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numberOfItems&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;}.&lt;/span&gt;&lt;span class="na"&gt;onFailure&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="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;message&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;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;teste&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&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="s"&gt;"chegou no teste $int"&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;This code is identical to the previous example except for the use of supervisorScope. When you execute it, you will see the same output in the terminal: two "entrou" messages and the exception message. However, now you will also see the result from the teste(int: Int) method. This indicates that when using supervisorScope, even if one coroutine fails, the other continues to run. Changing just one function can significantly alter the behavior of your program.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;As I mentioned at the beginning of this post, coroutines are an essential tool for Kotlin developers, but to use them effectively, it’s important to understand their nuances. Both coroutineScope and supervisorScope have their place in production code, and knowing which to use depends on your specific scenario. I hope you found this information helpful! If you'd like to discuss this topic further, feel free to reach out to me on social media.&lt;/p&gt;

&lt;p&gt;Thank you! &lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://kotlinlang.org/docs/coroutines-basics.html#your-first-coroutine" rel="noopener noreferrer"&gt;https://kotlinlang.org/docs/coroutines-basics.html#your-first-coroutine&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/" rel="noopener noreferrer"&gt;https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding light-weight threads with Coroutines and Project Loom</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Wed, 01 Nov 2023 13:14:05 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/understanding-coroutines-and-project-loom-2j6l</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/understanding-coroutines-and-project-loom-2j6l</guid>
      <description>&lt;p&gt;Coroutines were added to Kotlin in version 1.3. Since then, people have talked a lot about light-weight threads. In September, Java 21 was released, and with it, was introduced the JEP 444 - Virtual Threads, as part of Project Loom. Both have the same goal, which is to reduce dramatically the effort of writing, maintaining, and observing high-throughput concurrent applications. There are many articles about those subjects, but sometimes, people get confused. How does it work? What is virtual thread? Coroutines and Project loom are the same? My intention with this post is to show you how light-weight threads work and some relations in both projects. &lt;/p&gt;

&lt;h1&gt;
  
  
  Virtual Threads
&lt;/h1&gt;

&lt;p&gt;To understand how virtual threads work, we should understand the relation between OS Threads and JVM Threads. For each JVM Thread, we need an OS Thread. For instance, when our application needs to process something, it creates a JVM thread that will use an OS Thread. The problem is that sometimes these threads get in a iddle state. Suppose that our application receives a request to save a piece of information in the database. During the process of save, the thread will wait until the database returns. It does not look like a big problem, but according to our application grows, this become a problem. Threads are expensive and limited, so if the number of requests grows, it's necessary more threads. And what happens when the threads achieve the limit? It's necessary to scale the machine or increase the server instance to get more threads. Now can you understand why this is a problem? When the thread waits, we pay a lot just for it. How can we treat this? The correct answer is virtual threads. With virtual threads, we have many JVM threads to one OS thread. The good news is that the virtual thread doesn't need to wait until the finish of an external resource (DB). What occurs is that the virtual thread will be detached from an OS thread and will be in a suspended state. When the process finishes, another virtual thread can get the response. Amazing, right? Rashmin wrote in your article &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because of their lightweight nature, unlike Platform Threads, Virtual Threads are very cheap to create and can be created in very large numbers. So unlike Platform Threads, Thread Pooling is not necessary to handle multiple tasks, a separate virtual thread could be created for each task.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that we know how virtual threads work, let's see how we can implement them using Project Loom and Coroutines. &lt;/p&gt;

&lt;h1&gt;
  
  
  Coroutines
&lt;/h1&gt;

&lt;p&gt;The standard library of Kotlin provides some resources to work with coroutines, but this support is designed in a minimalistic way. There are a few elements, like Continuation, suspendCoroutine, and the suspend keyword. To improve the development, it is a good idea to use kotlinx.coroutines library, which gives us a large number of elements like launch, async, and Deferred. The easiest way to work with coroutines is using runBlocking. Let's see an example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside of runBlocking, we can call suspend functions. But, be careful, according to the documentation &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;runBlocking runs a new coroutine and blocks the current thread until its completion. This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The better way to work with coroutines is by creating a scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;coroutineScope&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;getUserFromDB&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;getAddressFromAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getUserFromDB&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example above shows us that we just call a suspend function from another suspend function (or from a runBlocking function). From a suspend function I can call not suspend function, but in this way, we lose the power of coroutines. It's important to say that in our example, we needed to explicitly the corotineScope, but working with modern frameworks, like Spring, we can start from a Controller, for instance, with suspend functions, without declaring the scope. &lt;/p&gt;

&lt;h1&gt;
  
  
  Project Loom
&lt;/h1&gt;

&lt;p&gt;Project Loom aims to bring "easy-to-use, high-throughput, lightweight concurrency" to the JRE. One feature introduced by Project Loom is virtual threads and since Java 21, thanks the JEP444, we can use this kind of code&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="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;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;IntStream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;range&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&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;submit&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;i&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The task in this example is simple code — sleep for one second — and modern hardware can easily support 10,000 virtual threads running such code concurrently. Behind the scenes, the JDK runs the code on a small number of OS threads, perhaps as few as one.&lt;/p&gt;

&lt;p&gt;Things would be very different if this program used an ExecutorService that creates a new platform thread for each task, such as Executors.newCachedThreadPool(). The ExecutorService would attempt to create 10,000 platform threads, and thus 10,000 OS threads, and the program might crash, depending on the machine and operating system.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Asynchronous programming is a great option to improve the performance of our application. Generally, people use platform threads to work with this paradigm, but as we saw previously, platform threads are very expensive. Thinking about improving that, every day new projects are emerging, like coroutines, project loom, goroutines, and so on. All of them use the concept of light-weight threads, a resource cheaper than traditional threads. In this post, we saw a way to implement this concept with coroutines and project loom. To finish, I hope that you have enjoyed the read, and any doubts, criticism, or points to consider, let me know. &lt;/p&gt;

&lt;p&gt;References&lt;br&gt;
&lt;a href="https://openjdk.org/jeps/444" rel="noopener noreferrer"&gt;https://openjdk.org/jeps/444&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kotlinlang.org/docs/coroutines-basics.html#your-first-coroutine" rel="noopener noreferrer"&gt;https://kotlinlang.org/docs/coroutines-basics.html#your-first-coroutine&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashm1n.medium.com/revolutionized-concurrency-introduction-to-java-21-virtual-threads-d563693994d9" rel="noopener noreferrer"&gt;https://rashm1n.medium.com/revolutionized-concurrency-introduction-to-java-21-virtual-threads-d563693994d9&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html" rel="noopener noreferrer"&gt;https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>projectloom</category>
      <category>kotlin</category>
      <category>coroutines</category>
    </item>
    <item>
      <title>Talking about Kotlin Coroutines</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Tue, 14 Mar 2023 16:37:07 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/talking-about-kotlin-coroutines-7jf</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/talking-about-kotlin-coroutines-7jf</guid>
      <description>&lt;p&gt;Nowadays, most web applications need to be asynchronous to attend your requests. There are many JVM libraries to work with this paradigm. The most famous is RxJava and Reactor. We can use both libraries with Kotlin, but there is an option that is better. This option is Kotlin Coroutines and we will understand how it works in this post. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using Kotlin Coroutines
&lt;/h2&gt;

&lt;p&gt;Kotlin Coroutines introduce the ability to suspend a coroutine at some point and resume it in the future. We might run our code on the Main thread and suspend it when we request data from API. When the coroutine is suspendend, the thread is not blocked and is free to go (Moskata, 2022, p. 15)&lt;/p&gt;

&lt;h2&gt;
  
  
  Suspension Work
&lt;/h2&gt;

&lt;p&gt;Suspending functions are the essential feature of Kotlin Coroutines. When we suspend functions, it means that we can stop the process in the middle, do other things, and return to finish the previous process from the point where we stopped. How coroutines does do that? When one function is suspended, it returns an object called &lt;code&gt;Continuation&lt;/code&gt;, which is the responsible for marking the point where the function stopped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built in support vc library
&lt;/h2&gt;

&lt;p&gt;Coroutines consist of two components: Built-in support provided by the Kotlin Language and Kotlin coroutines library. Let's see the difference:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Built-in Support&lt;br&gt;
Elements are in the kotlin.coroutines package. &lt;br&gt;
Provides a few basic elements like Continuation or suspend keyword. &lt;/p&gt;

&lt;p&gt;Coroutines Library&lt;br&gt;
It is another dependency&lt;br&gt;
Elements are in the kotlinx.coroutines package&lt;br&gt;
Provides many elements like launch, async and so on (we will see about these elements). &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Builders
&lt;/h2&gt;

&lt;p&gt;One suspend function should call another suspend function that call another suspend function and so on. But when it starts? To move from normal world to coroutines world, we need a coroutines builder. We will know about 3 builders. Let's see.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;launch builder: Similar to work with thread. We start a coroutine and it will run independently.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nc"&gt;GlobalScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello,"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result of: &lt;br&gt;
Hello,&lt;br&gt;
(1 sec)&lt;br&gt;
World&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Without Thread.sleep this function would end immediately after launching the coroutines.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;runBlocking builder: You should never block threads, just suspend them, but there are some cases that is necessary. Like the last example, we needed to block the thread, because our program could end early. In this cases, we can use runBlocking.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello,"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result of: &lt;br&gt;
(1 sec)&lt;br&gt;
World&lt;br&gt;
Hello,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;async builder:
The async builder is similar to launch, but there is a return.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;runBlocking&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Deferred&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GlobalScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="mi"&gt;42&lt;/span&gt;   
          &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;resultInt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultInt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result of:&lt;br&gt;
42&lt;/p&gt;

&lt;p&gt;&lt;em&gt;async is very similar to launch, so if you replace one to another, still work fine, but don't do that, because async is about producing a value. If you don't need a value, use launch.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;As we can see, coroutines is a great option to use for asynchronous programing. My idea was to show some basic features for you start. There are many other features to cover and my intention is to write about in the next posts. &lt;/p&gt;

&lt;p&gt;References&lt;br&gt;
Moskata, M. Kotlin Coroutines Deep Dive, 2022&lt;/p&gt;

</description>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Using Circuit Breaker Pattern with Kotlin, Resilience4j and Retrofit</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Thu, 08 Dec 2022 16:58:12 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/using-circuit-breaker-pattern-with-kotlin-resilience4j-and-retrofit-22i2</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/using-circuit-breaker-pattern-with-kotlin-resilience4j-and-retrofit-22i2</guid>
      <description>&lt;p&gt;When we work with microservices, one of the main objectives is to achieve resilience. There are many ways to achieve that. Retry, bulkhead, circuit breaker, all of them improve the microservices resilience. My idea with this post is to write about circuit breaker and how it works. I will use resilience4j dependency to implement this mechanism. &lt;/p&gt;

&lt;h2&gt;
  
  
  Resilience4j
&lt;/h2&gt;

&lt;p&gt;Resilience4j is a lightweight fault tolerance library designed for functional programming. Resilience4j provides higher-order functions (decorators) to enhance any functional interface, lambda expression or method reference with a Circuit Breaker, Rate Limiter, Retry or Bulkhead. You can stack more than one decorator on any functional interface, lambda expression or method reference. The advantage is that you have the choice to select the decorators you need and nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Circuit Breaker
&lt;/h2&gt;

&lt;p&gt;The CircuitBreaker is implemented via a finite state machine with three normal states: CLOSED, OPEN and HALF_OPEN and two special states DISABLED and FORCED_OPEN.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnz3ek1trqi1pbt7cj13.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnz3ek1trqi1pbt7cj13.jpg" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The state of the CircuitBreaker changes from CLOSED to OPEN when the failure rate is equal or greater than a configurable threshold. For example when more than 50% of the recorded calls have failed.&lt;/p&gt;

&lt;p&gt;The CircuitBreaker also changes from CLOSED to OPEN when the percentage of slow calls is equal or greater than a configurable threshold. For example when more than 50% of the recorded calls took longer than 5 seconds. This helps to reduce the load on an external system before it is actually unresponsive.&lt;/p&gt;

&lt;p&gt;The failure rate and slow call rate can only be calculated, if a minimum number of calls were recorded. For example, if the minimum number of required calls is 10, then at least 10 calls must be recorded, before the failure rate can be calculated. If only 9 calls have been evaluated the CircuitBreaker will not trip open even if all 9 calls have failed.&lt;/p&gt;

&lt;p&gt;The CircuitBreaker rejects calls with a CallNotPermittedException when it is OPEN. After a wait time duration has elapsed, the CircuitBreaker state changes from OPEN to HALF_OPEN and permits a configurable number of calls to see if the backend is still unavailable or has become available again. &lt;/p&gt;

&lt;p&gt;If the failure rate or slow call rate is then equal or greater than the configured threshold, the state changes back to OPEN. If the failure rate and slow call rate is below the threshold, the state changes back to CLOSED.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;More details in: &lt;a href="https://resilience4j.readme.io/docs/circuitbreaker" rel="noopener noreferrer"&gt;https://resilience4j.readme.io/docs/circuitbreaker&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's code
&lt;/h2&gt;

&lt;p&gt;The first thing is to add the resilience4j-circuit-breaker on &lt;code&gt;pom.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-circuitbreaker --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.resilience4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;resilience4j-circuitbreaker&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to configure our circuit breaker. My idea is that the circuit opens when catch 70% of errors or 70% of the requests last more than 2 nanoseconds (it's necessary to force the circuit open). My reference will be 10 requests. So, if in 10 requests, we receive 70% of errors or 70% of requests are slow, the state of circuit changes. To do that with code, let's create a Kotlin class called &lt;code&gt;CircuitBreakerConfiguration&lt;/code&gt;.&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="c1"&gt;// imports omitted &lt;/span&gt;
&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerConfiguration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getConfiguration&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;slidingWindowType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SlidingWindowType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;COUNT_BASED&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;slidingWindowSize&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;slowCallRateThreshold&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;70.0f&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;failureRateThreshold&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;70.0f&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;waitDurationInOpenState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;slowCallDurationThreshold&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofNanos&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;permittedNumberOfCallsInHalfOpenState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getCircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerRegistry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getConfiguration&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;circuitBreaker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"circuit-breaker-car-service"&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;As we can see, we called the custom method of &lt;code&gt;CircuitBreakerConfig&lt;/code&gt; class and apply the configurations. We defined the type and the size of sliding window. The type was &lt;code&gt;COUNT_BASED&lt;/code&gt; and the size was 10. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;It's a good thing to understand about the sliding window. For that read the documentation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To define the percentage of slow calls and errors that will open the circuit, we used &lt;code&gt;slowCallRateThreshold&lt;/code&gt; and &lt;code&gt;failureRateThreshold&lt;/code&gt;, both with 70%. There are two configurations that we need to understand better. They are &lt;code&gt;waitDurationInOpenState&lt;/code&gt; and &lt;code&gt;permmitedNumberOfCallsInHalfOpenState&lt;/code&gt;. The wait duration in open state is responsible to configure how many time the open circuit will pass from OPEN to HALF_OPEN. In our case, will be 5 seconds. When the circuit is in HALF_OPEN state, is permitted to request to the service (API, microservices etc...) to validate if there is an error or if the system recovered. To know how many requests is necessary to validate, we use &lt;code&gt;permmitedNumberOfCallsInHalfOpenState&lt;/code&gt;. In our case is 3. If 70% of 3 requests fails or are more slow than 2 nanoseconds, the circuit will change FROM HALF_OPEN to OPEN and will wait more 5 seconds to change to HALF_OPEN again. The circuit won't permit requests to the service, returning &lt;code&gt;CallNotPermittedException&lt;/code&gt;. But, if the requests don't fail, the circuit change from HALF_OPEN to CLOSED and application will work normally. Now we need to test. &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's test
&lt;/h2&gt;

&lt;p&gt;The application where we implemented the circuit breaker is simple. As we use Spring Boot, we have a &lt;code&gt;RestController&lt;/code&gt; that calls a service. This service there are some methods and one of them calls an external service via HTTP. To do this request we use Retrofit, which a client HTTP that has good integration with resilience4j. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;I won't give many details about Retrofit, for that, I recommend to read the documentation: &lt;a href="https://square.github.io/retrofit/" rel="noopener noreferrer"&gt;https://square.github.io/retrofit/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The method that we need to enhance with circuit breaker is called &lt;code&gt;listCarsByModel&lt;/code&gt;&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="n"&gt;override&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;listCarsByModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;model:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;carHttpService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getByModel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;let&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;CarHttpToModelConverter:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;toModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some details about retrofit. &lt;code&gt;CarHttpService&lt;/code&gt; is an interface that has a &lt;code&gt;getByModel&lt;/code&gt; method. In execution time, when &lt;code&gt;execute( )&lt;/code&gt; method will call, retrofit will implement this interface. It is possible, because we have a configuration class fot that.&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="kd"&gt;class&lt;/span&gt; &lt;span class="nf"&gt;CarHttpConfiguration&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="nl"&gt;circuitBreakerConfiguration:&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreakerConfiguration&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;companion&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="no"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://localhost:8081/cars"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;buildClient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OkHttpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;buildRetrofit&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Retrofit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addConverterFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GsonConverterFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buildClient&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;carHttpService&lt;/span&gt;&lt;span class="o"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;CarHttpService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buildRetrofit&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;CarHttpService:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;java&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;In this class we defined a &lt;code&gt;buildRetrofit( )&lt;/code&gt; method, that is responsible for add some configurations. We pass the url that will be call &lt;em&gt;(you can change for other)&lt;/em&gt;. We add a converter factory that will be the responsible to convert the API information to our object, and a client. After that, we defined a function called &lt;code&gt;carHttpService&lt;/code&gt;, which is a bean. When &lt;code&gt;execute( )&lt;/code&gt; method is called, Retrofit uses this function to implement the interface and inject it into the service.&lt;/p&gt;

&lt;p&gt;Until now, we have just spoken about retrofit. But what we need to know is how we can integrate resilience4j circuit breaker and retrofit.  &lt;/p&gt;

&lt;p&gt;We need to add a new dependency in our &lt;code&gt;pom.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-retrofit --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.resilience4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;resilience4j-retrofit&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.7.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we just need to add one line in our retrofit configuration in &lt;code&gt;builRetrofit&lt;/code&gt; method.&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="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;buildRetrofit&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Retrofit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;//new line&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addCallAdapterFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CircuitBreakerCallAdapter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;circuitBreakerConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addConverterFactory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GsonConverterFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buildClient&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this line, we applied an adapter, that receives a &lt;code&gt;CircuitBreakerCallAdapter&lt;/code&gt; where we pass our circuit breaker configuration. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Without retrofit, we would have more manual work to do. This is the advantage of integrations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The next step will be to start the application and call the endpoint that does the HTTP request more than 10 times. As we configured our &lt;code&gt;slowCallDurationThreshold&lt;/code&gt; to 3 nanoseconds, the requests always last more time, so circuit should open. Once open, is possible to see this return&lt;/p&gt;

&lt;p&gt;&lt;code&gt;io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'circuit-breaker-car-service' is OPEN and does not permit further calls&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;As we can see, circuit breaker improves the resilience of our services. Besides, it helps the external system to recover, when doesn't permit that our system does any request to it. I hope that you liked the post. Doubts, suggestions, and critics, you can comment or call me on my social media. &lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>circuitbreaker</category>
      <category>resilience4j</category>
      <category>retrofit</category>
    </item>
    <item>
      <title>Testcontainers with MySQL and Redis with an Spring Boot Kotlin Application</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Thu, 07 Jul 2022 13:01:32 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/testcontainers-with-mysql-and-redis-with-an-spring-boot-kotlin-application-4bmf</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/testcontainers-with-mysql-and-redis-with-an-spring-boot-kotlin-application-4bmf</guid>
      <description>&lt;p&gt;&lt;em&gt;Microservices&lt;/em&gt; architecture gives us some facilities, such as independently deploy, services with a unique responsibility, working with different languages, and so on. However, it also brings us some new complexities, such as duplicated code, observability tools, distributed caches tools, and logs tools. When we think about all these resources working together, we can think "How can we test these resources?". For instance, if our service uses &lt;em&gt;Redis&lt;/em&gt; for cache, and &lt;em&gt;MySQL&lt;/em&gt; to save and retrieve data, how can we do integration tests? Doing these tests by yourself can be difficult, but we have some manners to create that without much effort. One option is using &lt;em&gt;TestContainers&lt;/em&gt;. To show you the tool, I will test a Spring Boot Kotlin Application as example.  &lt;/p&gt;

&lt;h2&gt;
  
  
  TestContainers
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Testcontainers&lt;/em&gt; is a Java library that supports &lt;em&gt;JUnit&lt;/em&gt; tests, providing lightweight, throwaway instances of common databases, &lt;em&gt;Selenium&lt;/em&gt; web browsers, or anything else that can run in a &lt;em&gt;Docker&lt;/em&gt; container.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Testcontainers&lt;/em&gt; make the following kinds of tests easier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Data access layer integration tests: use a containerized instance of a &lt;em&gt;MySQL&lt;/em&gt;, &lt;em&gt;PostgreSQL&lt;/em&gt; or &lt;em&gt;Oracle&lt;/em&gt; database to test your data access layer code for complete compatibility, but without requiring complex setup on developers' machines and safe in the knowledge that your tests will always start with a known DB state. Any other database type that can be containerized can also be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application integration tests: for running your application in a short-lived test mode with dependencies, such as databases, message queues or web servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UI/Acceptance tests: use containerized web browsers, compatible with &lt;em&gt;Selenium&lt;/em&gt;, for conducting automated UI tests. Each test can get a fresh instance of the browser, with no browser state, plugin variations or automated browser upgrades to worry about. And you get a video recording of each test session, or just each session where tests failed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Much more! Check out the various contributed modules or create your own custom container classes using &lt;code&gt;GenericContainer&lt;/code&gt; as a base.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's Code
&lt;/h2&gt;

&lt;p&gt;The application that will be used has a Car domain. We can perform operations of inserting new cars, searching for available cars, and changing existing cars. The system has a controller, a service, and a repository. An overview of the architecture follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4l5d935lxbkcvo5u645r.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4l5d935lxbkcvo5u645r.jpeg" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, when we do a POST request to an application, the data is saved on &lt;em&gt;MySQL&lt;/em&gt; DB. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6wrkjpgau8pdcdw9gxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6wrkjpgau8pdcdw9gxf.png" alt=" " width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnqujrdgj406xi269dfr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnqujrdgj406xi269dfr.png" alt=" " width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we do a GET request, the application retrieves the data that is saved on DB and adds the information to &lt;em&gt;Redis&lt;/em&gt; cache. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Redis is an open-source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker. Redis' speed makes it ideal for caching database queries, complex computations, API calls, and session state.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2f13gpr2vwrux19quov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk2f13gpr2vwrux19quov.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Data in Redis
&lt;/h2&gt;

&lt;p&gt;We need to guarantee that the cache was saved in &lt;em&gt;Redis&lt;/em&gt;. For this, we can use a tool called &lt;em&gt;RedisInsight&lt;/em&gt; to see the data. &lt;em&gt;RedisInsight&lt;/em&gt; provides an intuitive &lt;em&gt;Redis&lt;/em&gt; admin GUI and helps optimize your use of &lt;em&gt;Redis&lt;/em&gt; in your applications. It supports &lt;em&gt;Redis Open Source, Redis Stack, Redis Enterprise Software, Redis Enterprise Cloud, and Amazon ElastiCache&lt;/em&gt;. &lt;em&gt;RedisInsight&lt;/em&gt; now incorporates a completely new tech stack based on the popular &lt;em&gt;Electron&lt;/em&gt; and &lt;em&gt;Elastic UI&lt;/em&gt; frameworks. And it runs cross-platform, supported on &lt;em&gt;Linux&lt;/em&gt;, &lt;em&gt;Windows&lt;/em&gt;, and &lt;em&gt;MacOS&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncf1pq9d7m64b7aamkr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fncf1pq9d7m64b7aamkr0.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see, the cache's data is saved like a hash. And if we don't do POST and PUT operations to the application, this data always will be retrieved. &lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the application
&lt;/h2&gt;

&lt;p&gt;Now that we know how the application works, a controller test will be performed, where we will use &lt;em&gt;MockMVC&lt;/em&gt;. &lt;em&gt;MockMvc&lt;/em&gt; simulates a real request to the application, doing exactly what happens when the client calls an endpoint. This implies that at the time of running the tests, we need to have all external resources working. It is common for projects to use a real test-specific database instance to perform integration tests, however, as we saw earlier, we have a more elegant and modern way to do them, using &lt;em&gt;TestContainers&lt;/em&gt;. As the cached service method and the repository will be called in the controller flow, it will be necessary to upload two containers, one for &lt;em&gt;MySQL&lt;/em&gt; and the other for &lt;em&gt;Redis&lt;/em&gt;. Let's start developing our test.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is add the &lt;em&gt;TestContainers&lt;/em&gt; dependencies to the application's pom.xml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependencyManagement&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testcontainers&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;testcontainers-bom&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${testcontainers.version}&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;pom&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;import&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependencyManagement&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testcontainers&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testcontainers&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mysql&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need the &lt;em&gt;TestContainers&lt;/em&gt; &lt;code&gt;junit-jupiter&lt;/code&gt; dependency because it provides some resources for more efficient testing. As we are using &lt;em&gt;MySQL&lt;/em&gt; as a database, it's necessary a dependency that provides resources to create a &lt;em&gt;MySQL&lt;/em&gt; container for tests in a simplified way.&lt;/p&gt;

&lt;p&gt;We need to create the configuration class of the containers that will be created at test time. It will be called &lt;code&gt;DatabaseContainerConfiguration&lt;/code&gt; and will have the following content&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;@SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WebEnvironment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RANDOM_PORT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseContainerConfiguration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;companion&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@Container&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;mysqlContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MySQLContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Nothing&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"mysql:latest"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;withDatabaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdb"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;withUsername&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"joao"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;withPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"12345"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@Container&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;redisContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenericContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Nothing&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"redis:latest"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;withExposedPorts&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@JvmStatic&lt;/span&gt;
        &lt;span class="nd"&gt;@DynamicPropertySource&lt;/span&gt;
        &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;registry:&lt;/span&gt; &lt;span class="nc"&gt;DynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mysqlContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getJdbcUrl&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mysqlContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getPassword&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mysqlContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getUsername&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.redis.host"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;redisContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getContainerIpAddress&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.redis.port"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;redisContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getFirstMappedPort&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's break down the meaning of each of the above features:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@Container&lt;/code&gt;: is used in conjunction with the &lt;code&gt;@Testcontainers&lt;/code&gt; annotation to mark containers that should be managed by the &lt;em&gt;Testcontainers&lt;/em&gt; extension.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We'll see about the @TestContainers annotation yet&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MySQLContainer&amp;lt;Nothing&amp;gt;(...)&lt;/code&gt;: Class that supports the creation of a &lt;em&gt;MySQL&lt;/em&gt; container for testing. We passed a Nothing in the generics of &lt;code&gt;MySQLContainer&lt;/code&gt; because of the class signature - &lt;code&gt;public class MySQLContainer&amp;lt;SELF extends MySQLContainer&amp;lt;SELF&amp;gt;&amp;gt; extends JdbcDatabaseContainer&amp;lt;SELF&amp;gt;&lt;/code&gt; - as we can see, there is a recursive generic type, which with &lt;em&gt;Java&lt;/em&gt;, we can ignore and just instantiate the class without generics. Using &lt;em&gt;Kotlin&lt;/em&gt;, we don't have this option, but we have two ways to handle it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a subclass of &lt;code&gt;MySQLContainer&lt;/code&gt; and pass the child class to &lt;em&gt;generics&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Nothing&lt;/code&gt;, which by &lt;em&gt;Kotlin&lt;/em&gt; doc's is:&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Nothing has no instances. You can use Nothing to represent "a value that never exists": for example, if a function has the return type of Nothing, it means that it never returns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;code&gt;MySQLContainer&lt;/code&gt; constructor, the version that we want to use from the &lt;em&gt;MySQL&lt;/em&gt; image is informed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withDatabaseName&lt;/code&gt;: Method of the &lt;code&gt;MySQLContainer&lt;/code&gt; class that receives the name of the database as a parameter. This database will be created at runtime after the test container goes up.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withUsername&lt;/code&gt;: Method of the &lt;code&gt;MySQLContainer&lt;/code&gt; class that receives the database username as a parameter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withPassword&lt;/code&gt;: Method of the &lt;code&gt;MySQLContainer&lt;/code&gt; class that receives the password from the database as a parameter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GenericContainer&amp;lt;Nothing&amp;gt;()&lt;/code&gt;: As the name implies, it is a class that allows you to create a container in a generic way, which means that the methods contained in them can be reused for various resources, such as &lt;em&gt;Redis&lt;/em&gt;, &lt;em&gt;NoSQL&lt;/em&gt; Databases, among others. We are using it because &lt;em&gt;Redis&lt;/em&gt; does not have a specific class like &lt;em&gt;MySQL&lt;/em&gt;. As we are seeing in the code, to create a generic container, we just need to insert the image of the resource that we want to instantiate as a parameter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withExposedPorts&lt;/code&gt;: Method of the &lt;code&gt;GenericContainer&lt;/code&gt; class that receives the port that we will make available from the test container. This port will be used at runtime.&lt;/p&gt;

&lt;p&gt;The properties function is used to dynamically add &lt;em&gt;Redis&lt;/em&gt; and &lt;em&gt;MySQL&lt;/em&gt; properties to the application. Before &lt;em&gt;TestContainers&lt;/em&gt; uploads the two containers, the application will not be aware of them, so how would we carry out the integration tests? Using &lt;code&gt;@DynamicPropertySource&lt;/code&gt; &lt;em&gt;Kotlin&lt;/em&gt; understands that these properties will be dynamically set at runtime, so when uploading the &lt;em&gt;MySQL&lt;/em&gt; and &lt;em&gt;Redis&lt;/em&gt; container, the information that the application needs to know to reach them will be included.&lt;/p&gt;

&lt;p&gt;Now we have everything we need for &lt;em&gt;TestContainers&lt;/em&gt; to upload both containers. We just need to use the class where needed. As stated at the beginning of the section, we want to do an API test, where &lt;em&gt;MockMVC&lt;/em&gt; will make a request to the controller and thus follow the flow to the database. So let's create this test.&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;@Testcontainers&lt;/span&gt;
&lt;span class="nd"&gt;@AutoConfigureMockMvc&lt;/span&gt;
&lt;span class="nd"&gt;@SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WebEnvironment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RANDOM_PORT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarControllerTest&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DatabaseContainerConfiguration&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;lateinit&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="nl"&gt;mockMvc:&lt;/span&gt; &lt;span class="nc"&gt;MockMvc&lt;/span&gt;

    &lt;span class="n"&gt;companion&lt;/span&gt; &lt;span class="n"&gt;object&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;const&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/cars"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mockMvc&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="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;andExpect&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;isOk&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned before, we can see that we have an annotation in the class declaration, which is &lt;code&gt;@TestContainers&lt;/code&gt;. This annotation makes that, at runtime, the library identifies it and uploads the available containers through the &lt;code&gt;@Container&lt;/code&gt; annotation, which is in our &lt;code&gt;DatabaseContainerConfiguration&lt;/code&gt; class, which in turn was inherited by the test. This is enough for when we run the tests, the containers are instantiated.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The intention is not to talk about MockMVC, but according to the documentation, it is the main entry point for server-side Spring MVC testing support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One last detail before running the tests is that it will be necessary to configure the &lt;em&gt;migration&lt;/em&gt;. When the application goes up and reaches the containers, it is applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;migration&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;V01__create_car_table_add_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;bigint&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Golf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'VW'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;It's time to run the tests and remember, &lt;em&gt;docker&lt;/em&gt; must be active. Running the &lt;code&gt;mvn -B test&lt;/code&gt; command will run the tests. We can observe the containers going up at the time of the test execution, using the docker ps command in the terminal or the docker desktop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb52x3jx4o2tzcs8ztd46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb52x3jx4o2tzcs8ztd46.png" alt=" " width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the test execution logs, we can see the moment when the &lt;em&gt;MySQL&lt;/em&gt; container rises&lt;/p&gt;

&lt;p&gt;22:17:53.206 [main] DEBUG 🐳 [mysql:latest] - Trying to create JDBC connection using com.mysql.cj.jdbc.Driver to jdbc:mysql://localhost:52550/testdb?useSSL=false&amp;amp;allowPublicKeyRetrieval=true with properties: {password=12345, user=joao}&lt;br&gt;
22:17:53.582 [main] INFO 🐳 [mysql:latest] - Container is started (JDBC URL: jdbc:mysql://localhost:52550/testdb)&lt;br&gt;
22:17:53.583 [main] INFO 🐳 [mysql:latest] - Container mysql:latest started in PT23.428294S&lt;/p&gt;

&lt;p&gt;Just like &lt;em&gt;Redis&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;22:17:53.583 [main] DEBUG 🐳 [redis:latest] - Starting container: redis:latest&lt;br&gt;
22:17:53.583 [main] DEBUG 🐳 [redis:latest] - Trying to start container: redis:latest (attempt 1/1)&lt;br&gt;
22:17:53.583 [main] DEBUG 🐳 [redis:latest] - Starting container: redis:latest&lt;br&gt;
22:17:53.583 [main] INFO 🐳 [redis:latest] - Creating container for image: redis:latest&lt;/p&gt;

&lt;p&gt;And finally the expected result&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Tests Passed: 1 of 1 test - 631 ms&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Integration tests are very important for the application, and one of the main tasks is to validate if the application's connection with external resources is being done successfully. There are N ways to do them. We can use database integration tests, in-memory databases, real instances and as presented in the post, TestContainers. &lt;em&gt;TestContainers&lt;/em&gt;, with small settings, bring big advantages. Disposable containers, as they are only used at the time of test execution. External resource agnostic, with the &lt;code&gt;GenericContainer&lt;/code&gt; class we can do integration testing with any resource we uploaded in docker. An excellent testing tool.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is in collaboration with Redis.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Application's repository: &lt;a href="https://github.com/joao0212/car-service" rel="noopener noreferrer"&gt;https://github.com/joao0212/car-service&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;References: &lt;br&gt;
&lt;a href="https://www.testcontainers.org/" rel="noopener noreferrer"&gt;https://www.testcontainers.org/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>mysql</category>
      <category>redis</category>
      <category>testcontainer</category>
    </item>
    <item>
      <title>[PT-BR] Testcontainers com MySQL e Redis</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Thu, 16 Jun 2022 12:51:51 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/pt-br-testcontainers-com-mysql-e-redis-3j89</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/pt-br-testcontainers-com-mysql-e-redis-3j89</guid>
      <description>&lt;p&gt;No post passado, falei sobre testes de unidade e sobre como eles auxiliam na validação das regras de negócio do sistema. Neste post minha ideia é falar sobre testes de integração, que de acordo com o blog da kenzie (2021), é quando os módulos (unidades de código) são testados em grupo para garantir que não haja nenhuma quebra naquilo que foi feito unitariamente e naquilo que está sendo integrado junto. Para exemplificá-lo, realizaremos um teste de integração em uma aplicação existente, onde utilizaremos a biblioteca &lt;em&gt;TestContainers&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testcontainers
&lt;/h1&gt;

&lt;p&gt;De acordo com a documentação, &lt;em&gt;Testcontainers&lt;/em&gt; é uma biblioteca Java que suporta testes JUnit, fornecendo instâncias leves e descartáveis ​​de bancos de dados comuns, navegadores da Web Selenium ou qualquer outra coisa que possa ser executada em um contêiner do Docker.&lt;/p&gt;

&lt;p&gt;Os contêineres de teste facilitam os seguintes tipos de testes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Testes de integração da camada de acesso a dados: use uma instância conteinerizada de um banco de dados MySQL, PostgreSQL ou Oracle para testar seu código de camada de acesso a dados para compatibilidade completa.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testes de UI/Aceitação: use navegadores da Web em contêiner, compatíveis com Selenium, para realizar testes automatizados de UI. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Muito mais: Confira os vários módulos contribuídos ou crie suas próprias classes de contêiner personalizadas usando &lt;code&gt;GenericContainer&lt;/code&gt; como base.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Let's code
&lt;/h1&gt;

&lt;p&gt;A aplicação que será utilizada, possui um domínio Car. Podemos realizar operações de inserção de novos carros, de busca de carros disponíveis e de alteração de carros existentes. O sistema possui uma controller, um service e um repository. Na camada de serviço, no método de listar carros, usamos o &lt;em&gt;Redis&lt;/em&gt; para cache de informações e o banco de dados é um &lt;em&gt;MySQL&lt;/em&gt;. Segue overview da arquitetura.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrdgcdu7bvfbk9tvhdqn.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhrdgcdu7bvfbk9tvhdqn.jpeg" alt=" " width="411" height="241"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Será realizado um teste de controller, onde utilizaremos o &lt;em&gt;MockMVC&lt;/em&gt;. O &lt;em&gt;MockMvc&lt;/em&gt; simula uma requisição real à aplicação, fazendo exatamente o que ocorre quando o cliente chama um endpoint. Isso implica que no momento da execução dos testes, precisamos ter todos os recursos externos funcionando. É comum projetos utilizarem uma instância de banco de dados real, específica para testes, para realizar testes de integração, porém, como vimos anteriormente, temos uma maneira mais elegante e moderna para fazê-los, que é usando &lt;em&gt;TestContainers&lt;/em&gt;. Como no fluxo da controller será chamado o método do service cacheado e o repositório, será preciso subir dois contêineres, sendo um pro &lt;em&gt;MySQL&lt;/em&gt; e o outro para o &lt;em&gt;Redis&lt;/em&gt;. Vamos iniciar o desenvolvimento do nosso teste.&lt;/p&gt;

&lt;p&gt;A primeira ação que precisamos fazer é adicionar as dependências do &lt;em&gt;TestContainers&lt;/em&gt; no &lt;code&gt;pom.xml&lt;/code&gt; da aplicação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;# Resto do pom.xml omitido

&lt;span class="nt"&gt;&amp;lt;dependencyManagement&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testcontainers&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;testcontainers-bom&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${testcontainers.version}&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;pom&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;import&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependencyManagement&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testcontainers&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit-jupiter&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.testcontainers&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mysql&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Precisamos da dependência do &lt;code&gt;junit-jupiter&lt;/code&gt; do &lt;em&gt;TestContainers&lt;/em&gt;, pois ela nos fornece alguns recursos para maior eficiência dos testes e por estarmos usando o &lt;em&gt;MySQL&lt;/em&gt; como banco de dados, precisamos de uma dependência que nos forneça recursos para criar um container &lt;em&gt;MySQL&lt;/em&gt; para testes de forma simplificada.  &lt;/p&gt;

&lt;p&gt;Precisamos criar a classe configuração dos contêineres que serão criados no momento do teste. Ela será chamada de &lt;code&gt;DatabaseContainerConfiguration&lt;/code&gt; e terá o seguinte conteúdo&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="c1"&gt;// Imports omitidos&lt;/span&gt;

&lt;span class="nd"&gt;@SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WebEnvironment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RANDOM_PORT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseContainerConfiguration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;companion&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;@Container&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;mysqlContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MySQLContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Nothing&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"mysql:latest"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;withDatabaseName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"testdb"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;withUsername&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"joao"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;withPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"12345"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@Container&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;redisContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenericContainer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Nothing&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"redis:latest"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;withExposedPorts&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nd"&gt;@JvmStatic&lt;/span&gt;
        &lt;span class="nd"&gt;@DynamicPropertySource&lt;/span&gt;
        &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;properties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;registry:&lt;/span&gt; &lt;span class="nc"&gt;DynamicPropertyRegistry&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mysqlContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getJdbcUrl&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.password"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mysqlContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getPassword&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.datasource.username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;mysqlContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getUsername&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.redis.host"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;redisContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getContainerIpAddress&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"spring.redis.port"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;redisContainer:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getFirstMappedPort&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos detalhar o significado de cada um dos recursos acima:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@Container&lt;/code&gt;: é usada em conjunto com a anotação &lt;code&gt;@Testcontainers&lt;/code&gt; para marcar contêineres que devem ser gerenciados pela extensão &lt;em&gt;Testcontainers&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Ainda vamos ver sobre a anotação @TestContainers&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MySQLContainer&amp;lt;Nothing&amp;gt;(...)&lt;/code&gt;: Classe que da suporte a criação de um contêiner &lt;em&gt;MySQL&lt;/em&gt; para teste. Passamos um &lt;code&gt;Nothing&lt;/code&gt; no &lt;em&gt;generics&lt;/em&gt; de &lt;code&gt;MySQLContainer&lt;/code&gt; e isso ocorre por causa da assinatura da classe. &lt;code&gt;public class MySQLContainer&amp;lt;SELF extends MySQLContainer&amp;lt;SELF&amp;gt;&amp;gt; extends JdbcDatabaseContainer&amp;lt;SELF&amp;gt;&lt;/code&gt;, como podemos ver, há um tipo genérico recursivo, que com o Java, conseguimos ignorar e apenas instanciar a classe sem o &lt;em&gt;generics&lt;/em&gt;. Usando Kotlin, não temos essa opção, mas temos duas formas de tratar. 

&lt;ul&gt;
&lt;li&gt;Definir uma subclasse de &lt;code&gt;MySQLContainer&lt;/code&gt; e passar a classe filha para o &lt;em&gt;generics&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Usar o &lt;code&gt;Nothing&lt;/code&gt;, que pelo Kotlin doc's é: &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Nothing has no instances. You can use Nothing to represent "a value that never exists": for example, if a function has the return type of Nothing, it means that it never returns*. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como podemos ver no código, estamos usando a segunda opção. No construtor da classe, é informada a versão que queremos usar da imagem do &lt;em&gt;MySQL&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;withDatabaseName&lt;/code&gt;: Método da classe &lt;code&gt;MySQLContainer&lt;/code&gt; que recebe o nome da database como parâmetro. Essa database será criada em tempo de execução, após o contêiner de teste subir. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;withUsername&lt;/code&gt;: Método da classe &lt;code&gt;MySQLContainer&lt;/code&gt; que recebe o username da database como parâmetro. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;withPassword&lt;/code&gt;: Método da classe &lt;code&gt;MySQLContainer&lt;/code&gt; que recebe o password da database como parâmetro. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;GenericContainer&amp;lt;Nothing&amp;gt;()&lt;/code&gt;: Como o próprio nome já diz, é uma classe que permite criar um contêiner de forma genérica, isso significa que os métodos contidos neles, poderão ser reutilizados para vários recursos, como &lt;em&gt;Redis&lt;/em&gt;, Bancos &lt;em&gt;NoSQL&lt;/em&gt;, entre outros. Estamos o utilizando, pois o &lt;em&gt;Redis&lt;/em&gt; não possui uma classe específica como o &lt;em&gt;MySQL&lt;/em&gt;. Como estamos vendo no código, para criar um contêiner genérico, basta inserirmos como parâmetro a imagem do recurso que queremos instanciar. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;withExposedPorts&lt;/code&gt;: Método da classe &lt;code&gt;GenericContainer&lt;/code&gt; que recebe a porta que vamos disponibilizar do contêiner de teste. Essa porta será utilizada em tempo de execução.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A função &lt;code&gt;properties&lt;/code&gt; serve para adicionar as propriedades do &lt;em&gt;Redis&lt;/em&gt; e do &lt;em&gt;MySQL&lt;/em&gt; de forma dinâmica à aplicação. Ou seja, antes do &lt;em&gt;TestContainers&lt;/em&gt; subir os dois contêineres, a aplicação não vai ter conhecimento deles, logo como realizaríamos os testes de integração? Usando o &lt;code&gt;@DynamicPropertySource&lt;/code&gt; o Kotlin entende que essas propriedades serão setadas de forma dinâmica, em tempo de execução, assim, ao subir o contêiner do &lt;em&gt;MySQL&lt;/em&gt; e do &lt;em&gt;Redis&lt;/em&gt;, as informações que a aplicação precisa conhecer para alcançá-los serão incluídas. &lt;/p&gt;

&lt;p&gt;Agora temos tudo que precisamos para que o &lt;em&gt;TestContainers&lt;/em&gt; suba os dois contêineres. Precisamos apenas utilizar a classe onde necessário. Como informado no começo da seção, queremos fazer um teste de API, onde o &lt;em&gt;MockMVC&lt;/em&gt; fará uma requisição para a controller e assim seguirá o fluxo até o banco de dados. Então vamos criar esse teste.&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;@Testcontainers&lt;/span&gt;
&lt;span class="nd"&gt;@SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webEnvironment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SpringBootTest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WebEnvironment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RANDOM_PORT&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarControllerTest&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;DatabaseContainerConfiguration&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;lateinit&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="nl"&gt;webApplicationContext:&lt;/span&gt; &lt;span class="nc"&gt;WebApplicationContext&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;lateinit&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="nl"&gt;mockMvc:&lt;/span&gt; &lt;span class="nc"&gt;MockMvc&lt;/span&gt;

    &lt;span class="n"&gt;companion&lt;/span&gt; &lt;span class="n"&gt;object&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;const&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/cars"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@BeforeEach&lt;/span&gt;
    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mockMvc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MockMvcBuilders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;webAppContextSetup&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webApplicationContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DefaultMockMvcBuilder&lt;/span&gt;&lt;span class="o"&gt;?&amp;gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;SecurityMockMvcConfigurers&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;springSecurity&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="n"&gt;fun&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mockMvc&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="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;andExpect&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;isOk&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como falado anteriormente, podemos perceber que temos uma anotação na declaração da classe, que é a &lt;code&gt;@TestContainers&lt;/code&gt;. Essa anotação faz com que em tempo de execução, a biblioteca a identifique e suba os contêineres disponíveis pela a anotação &lt;code&gt;@Container&lt;/code&gt;, que está na nossa classe &lt;code&gt;DatabaseContainerConfiguration&lt;/code&gt;, que por sua vez foi herdada pelo teste. Isto é o suficiente para quando executarmos os testes, os contêineres sejam instanciados. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A intenção não é falar sobre o &lt;em&gt;MockMVC&lt;/em&gt;, mas de acordo com a documentação, ele é o ponto de entrada principal para suporte de teste Spring MVC do lado do servidor. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Um último detalhe antes de executar os testes, é que será necessário configurar as migrations, para que no momento que a aplicação subir e alcançar os contêineres, as mesmas sejam aplicadas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;migration&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;V01__create_car_table_add_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;sql&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;bigint&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Golf'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'VW'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chegou o momento de executar os testes e para isso o docker deve estar ativo. Executando o comando &lt;code&gt;mvn -B test&lt;/code&gt;, os testes serão executados. Podemos observar os contêineres subindo no momento da execução dos testes, utilizando o comando &lt;code&gt;docker ps&lt;/code&gt; no terminal ou o docker desktop. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4l2mcnuoc3noogwo9s1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4l2mcnuoc3noogwo9s1j.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos logs da execução dos testes, podemos ver o momento em que sobe o contêiner do &lt;em&gt;MySQL&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;22:17:53.206 [main] DEBUG 🐳 [mysql:latest] - Trying to create JDBC connection using com.mysql.cj.jdbc.Driver to jdbc:mysql://localhost:52550/testdb?useSSL=false&amp;amp;allowPublicKeyRetrieval=true with properties: {password=12345, user=joao}&lt;br&gt;
22:17:53.582 [main] INFO 🐳 [mysql:latest] - Container is started (JDBC URL: jdbc:mysql://localhost:52550/testdb)&lt;br&gt;
22:17:53.583 [main] INFO 🐳 [mysql:latest] - Container mysql:latest started in PT23.428294S&lt;/p&gt;

&lt;p&gt;Assim como o do &lt;em&gt;Redis&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;22:17:53.583 [main] DEBUG 🐳 [redis:latest] - Starting container: redis:latest&lt;br&gt;
22:17:53.583 [main] DEBUG 🐳 [redis:latest] - Trying to start container: redis:latest (attempt 1/1)&lt;br&gt;
22:17:53.583 [main] DEBUG 🐳 [redis:latest] - Starting container: redis:latest&lt;br&gt;
22:17:53.583 [main] INFO 🐳 [redis:latest] - Creating container for image: redis:latest&lt;/p&gt;

&lt;p&gt;E finalmente o resultado esperado&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9fb7e5y69a8a1tpgpxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9fb7e5y69a8a1tpgpxs.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Testes de integração possuem muita importância para aplicação, sendo uma das principais atribuições, validar se a conexão da aplicação com recursos externos estão sendo feitas de maneira bem sucedida. Existem N maneiras de fazê-los, podemos usar, por exemplo, para testes de integração com banco de dados, bancos de dados em memória, instâncias reais e como apresentado no post, &lt;em&gt;TestContainers&lt;/em&gt;. O &lt;em&gt;TestContainers&lt;/em&gt;, com pequenas configurações, traz grandes vantagens. Contêineres descartáveis, pois só são usados no momento da execução dos testes. Agnóstico ao recurso externo, com a classe &lt;code&gt;GenericContainer&lt;/code&gt;, podemos fazer o teste de integração com qualquer recurso que subimos no docker. Uma excelente ferramenta para testes. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Se você sentiu que faltou alguma coisa importante para explicar, ficou com alguma dúvida ou tem alguma sugestão, não deixe de me procurar. No mais, espero que você tenha uma boa leitura. Até a próxima.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Referências&lt;br&gt;
&lt;a href="https://kenzie.com.br/blog/teste-de-integracao/" rel="noopener noreferrer"&gt;https://kenzie.com.br/blog/teste-de-integracao/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.testcontainers.org/" rel="noopener noreferrer"&gt;https://www.testcontainers.org/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ptbr</category>
      <category>kotlin</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>[PR-BR] Testes de unidade com MockK e AssertJ</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Thu, 20 Jan 2022 14:15:58 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/pr-br-testes-de-unidade-com-mockk-e-assertj-cko</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/pr-br-testes-de-unidade-com-mockk-e-assertj-cko</guid>
      <description>&lt;p&gt;Sempre que estamos falando sobre boas práticas de desenvolvimento de software, um nome sempre aparece: testes de unidade. De acordo com Marco Tulio Valente (2020), testes de unidade são testes automatizados de pequenas unidades de código, normalmente classes, as quais são testadas de forma isolada do restante do sistema. Um teste de unidade é um programa que chama métodos de uma classe e verifica se eles retornam os resultados esperados. Esses testes podem ser feitos na maioria das linguagens de programação e cada uma delas possui bibliotecas e recursos para facilitar o desenvolvimento dos mesmos. A ideia do post é mostrar como fazer testes de unidade em kotlin usando mockK e AssertJ. &lt;/p&gt;

&lt;h1&gt;
  
  
  MockK
&lt;/h1&gt;

&lt;p&gt;Mockk é uma biblioteca de mocking para kotlin que traz uma série de recursos como &lt;em&gt;Spy, Relaxed mock, Partial mocking, Object mocks, Class mock&lt;/em&gt; entre outros. &lt;/p&gt;

&lt;h1&gt;
  
  
  AssertJ
&lt;/h1&gt;

&lt;p&gt;O AssertJ fornece um rico conjunto de asserções, mensagens de erro realmente úteis, melhora a legibilidade do código de teste e foi projetado para ser super fácil de usar em sua IDE favorita.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dependências
&lt;/h1&gt;

&lt;p&gt;Para criar testes de unidade com as bibliotecas informadas, é necessário adicionar as dependências no projeto. No caso do maven basta colocar o trecho a seguir no &lt;code&gt;pom.xml&lt;/code&gt; &lt;strong&gt;(verificar versões)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.mockk&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;mockk&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.12.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.assertj&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;assertj-core&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.21.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Mãos na massa
&lt;/h1&gt;

&lt;p&gt;Suponha que é necessário testar o comportamento de um método que lista produtos. O método possui dois fluxos. Quando é informado o nome do produto a ser listado, deve-se retornar apenas o produto especificado. Quando o nome do produto não é informado, deve-se retornar todos os produtos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Resto do código omitido&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;listar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nomeProduto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?):&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;nomeProduto&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByProdutoNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nomeProduto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O primeiro teste será para validar o comportamento do método quando é informado o nome do produto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.mockk.every&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.mockk.mockk&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.mockk.verify&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.assertj.core.api.Assertions.*&lt;/span&gt;
&lt;span class="c1"&gt;// Outros imports foram omitidos&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProdutoServiceTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ProdutoRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;produtoService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProdutoService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nd"&gt;@Test&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;`deve&lt;/span&gt; &lt;span class="n"&gt;listar&lt;/span&gt; &lt;span class="n"&gt;produto&lt;/span&gt; &lt;span class="n"&gt;por&lt;/span&gt; &lt;span class="nf"&gt;nome`&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;every&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByProdutoNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Geladeira"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

                &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;produtoService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

                &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exactly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;produtoRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exactly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;produtoRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByProdutoNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;isNotNull&lt;/span&gt;
                &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hasSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos entender alguns recursos apresentados. Como a ideia do teste de unidade é testar apenas o comportamento do método que contém a regra de negócio, toda a parte de repositório deverá ser mockada. Para mockar objetos com o mockK pode-se utilizar a inline function &lt;code&gt;mockk()&lt;/code&gt;. Há duas formas de utilizá-la, da forma que foi declarada acima ou com &lt;code&gt;mockk&amp;lt;ProdutoRepository&amp;gt;()&lt;/code&gt;. Com o repositório mockado, é necessário definir o seu comportamento. Para isto é criado o bloco &lt;code&gt;every&lt;/code&gt; que descreve qual resposta deve ser dada quando um método do repositório for chamado. No caso acima, sempre que o método &lt;code&gt;findByProdutoNome&lt;/code&gt; for chamado, será retornado uma lista de produtos que possui apenas um produto. O &lt;code&gt;verify&lt;/code&gt; será o bloco responsável por verificar se o mock foi invocado como esperado. Como o método possui dois fluxos, temos que garantir que quando for informado o nome do produto, o método do repositório &lt;code&gt;findAll()&lt;/code&gt; não seja chamado e sim o &lt;code&gt;findByProdutoNome()&lt;/code&gt;. Qualquer comportamento diferente deste deverá fazer o teste falhar. Tudo que foi falado até aqui são recursos do mockk e já seria suficiente para fazer o teste ser executado com sucesso. Porém para garantir que o resultado retornado está correto, podemos fazer asserções e é neste momento que o AssertJ vira protagonista. Para escrever uma asserção, você sempre precisa começar passando seu objeto para o método &lt;code&gt;assertThat()&lt;/code&gt; e então seguir com as asserções reais. No caso acima, estamos afirmando que o resultado não é nulo e a lista possui um elemento. Qualquer retorno diferente disso, significaria que o método &lt;code&gt;listar&lt;/code&gt; de &lt;code&gt;ProdutoService&lt;/code&gt; não está de acordo com o comportamento esperado, e mais uma vez o teste deverá falhar. Agora que entendemos todos os recursos utilizados no teste, podemos testar o outro fluxo, quando não é informado o nome do produto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.mockk.every&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.mockk.mockk&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.mockk.verify&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.assertj.core.api.Assertions.*&lt;/span&gt;
&lt;span class="c1"&gt;// Outros imports foram omitidos&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProdutoServiceTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ProdutoRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mockk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;produtoService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProdutoService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nd"&gt;@Test&lt;/span&gt;
        &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;`deve&lt;/span&gt; &lt;span class="n"&gt;listar&lt;/span&gt; &lt;span class="n"&gt;todos&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt; &lt;span class="nf"&gt;produtos`&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;every&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Geladeira"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Produto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Televisao"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

                &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;produtoService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

                &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exactly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;produtoRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exactly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;produtoRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByProdutoNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;isNotNull&lt;/span&gt;
                &lt;span class="nf"&gt;assertThat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hasSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Podemos ver que ambas as bibliotecas nos fornecem recursos poderosos para criar testes de unidades simples, elegantes e eficientes. Existem muitos outros recursos a serem explorados, o que não caberia em apenas um post. Para quem tiver interesse em continuar os estudos, abaixo, em referências, deixei alguns links que vão auxiliar. Espero que tenham gostado da leitura e qualquer dúvida, crítica ou sugestão, não deixem de comentar. Até a próxima!! &lt;/p&gt;

&lt;p&gt;Referências&lt;br&gt;
&lt;a href="https://mockk.io/" rel="noopener noreferrer"&gt;https://mockk.io/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://joel-costigliola.github.io/assertj/" rel="noopener noreferrer"&gt;https://joel-costigliola.github.io/assertj/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.baeldung.com/kotlin/mockk" rel="noopener noreferrer"&gt;https://www.baeldung.com/kotlin/mockk&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.baeldung.com/introduction-to-assertj" rel="noopener noreferrer"&gt;https://www.baeldung.com/introduction-to-assertj&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bibliografia&lt;br&gt;
Marco Tulio Valente. Engenharia de Software Moderna: Princípios e Práticas para Desenvolvimento de Software com Produtividade, 2020.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>test</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>[PT-BR] Minhas duas features preferidas do Java 17</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Tue, 28 Sep 2021 13:56:06 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/pt-br-minhas-duas-features-preferidas-do-java-17-5aa</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/pt-br-minhas-duas-features-preferidas-do-java-17-5aa</guid>
      <description>&lt;p&gt;No dia 14/09/2021, foi lançada a versão 17 do Java, sendo ela uma versão LTS &lt;em&gt;(Long Term Support)&lt;/em&gt;. Assim como nas últimas versões, a 17 trouxe algumas features bem divertidas. Minha ideia nesse post é mostrar as duas que mais me chamaram atenção, que são a &lt;strong&gt;409:Sealed Classes&lt;/strong&gt; e a &lt;strong&gt;406:Pattern Matching for Switch&lt;/strong&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Sealed Classes
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Sealed&lt;/em&gt; classes e interfaces restringem quais outras classes ou interfaces devem estendê-las e/ou implementa-las. O objetivo é permitir que o autor da classe ou interface tenha mais controle sobre a mesma, além de prover um jeito mais declarativo de restringir o uso da super classe. Um outro objetivo é o suporte a &lt;em&gt;pattern matchings&lt;/em&gt;.&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="n"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Automovel&lt;/span&gt; 
    &lt;span class="n"&gt;permits&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exemplo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;automovel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Carro&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;examplo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;automovel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Moto&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;Uma vez que eu defino quais classes irão poder estender de Automovel, qualquer outra classe diferente de Carro e Moto não deve ser permitida. É importante ressaltar, que as classes que irão estender uma &lt;em&gt;sealed class&lt;/em&gt;, deverão estar no mesmo módulo, caso esteja usando &lt;em&gt;JPMS (Java Platform Module System)&lt;/em&gt; ou no mesmo pacote, caso não esteja usando &lt;em&gt;JPMS&lt;/em&gt;. Para a classes que estendem, existem algumas regras. São elas: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Uma subclasse deve ser declarada como final para manter a hierarquia. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uma subclasse deve ser declarada como &lt;em&gt;sealed&lt;/em&gt; e permitir a extensão de um novo conjunto de classes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uma subclasse deve ser declarada como &lt;em&gt;non-sealed&lt;/em&gt; e assim permitir que qualquer classe a estenda. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Pattern Matching for Switch
&lt;/h1&gt;

&lt;p&gt;Estender a correspondência de padrões para &lt;em&gt;switch&lt;/em&gt; permite que uma expressão seja testada em relação a vários padrões, cada um com uma ação específica, de forma que consultas complexas orientadas a dados possam ser expressas de forma concisa e segura. O objetivo é melhorar a expressividade e a aplicabilidade das extensões e instruções &lt;em&gt;switch&lt;/em&gt;, além de certificar que todas as expressões e instruções existentes continuem a compilar sem alterações.&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="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printarTipoAutomovel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Automovel&lt;/span&gt; &lt;span class="n"&gt;automovel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;automovel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Carro&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;"É um carro"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Moto&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;"É uma moto"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
     &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;"Automóvel não identificado"&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;É importante ressaltar que a &lt;strong&gt;JEP 406: Pattern Matching for switch&lt;/strong&gt; está como preview, o que significa que ela pode ser retirada e não fazer parte das próximas versões do Java. &lt;/p&gt;

&lt;h1&gt;
  
  
  Concluindo
&lt;/h1&gt;

&lt;p&gt;O objetivo do post era trazer as features que mais me interessaram no Java 17, sendo essa uma escolha totalmente pessoal. Existem muitas outras features legais, que podem ser vistas em: &lt;a href="https://openjdk.java.net/projects/jdk/17/" rel="noopener noreferrer"&gt;https://openjdk.java.net/projects/jdk/17/&lt;/a&gt;. Espero que gostem da leitura. Dúvidas, sugestões e/ou críticas, estou à disposição. &lt;/p&gt;

&lt;p&gt;Referências&lt;br&gt;
&lt;a href="https://openjdk.java.net/jeps/409" rel="noopener noreferrer"&gt;https://openjdk.java.net/jeps/409&lt;/a&gt;&lt;br&gt;
&lt;a href="https://openjdk.java.net/jeps/406" rel="noopener noreferrer"&gt;https://openjdk.java.net/jeps/406&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>jdk17</category>
    </item>
    <item>
      <title>Partition and Clustering Key on Scylla DB</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Mon, 26 Jul 2021 16:33:57 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/partition-and-clustering-key-on-scylla-db-1l1e</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/partition-and-clustering-key-on-scylla-db-1l1e</guid>
      <description>&lt;p&gt;In the last 2 previous posts, we talked about &lt;em&gt;Scylla DB&lt;/em&gt;. Today I will keep talking about the database, more specifically how works &lt;em&gt;Primary Key&lt;/em&gt; on &lt;em&gt;Scylla&lt;/em&gt;. We will see that the &lt;em&gt;PK&lt;/em&gt; can be divided into two: &lt;em&gt;Partition Key&lt;/em&gt; and &lt;em&gt;Clustering Key&lt;/em&gt;. Let's get the difference between both and some differences in relation to a relational database.&lt;/p&gt;

&lt;h1&gt;
  
  
  Partition Key
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Partition Key&lt;/em&gt; is responsible for data distribution across the nodes. It determines which node will store a given row. It can be one or more columns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv48jx4qqwsxk6908dlge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv48jx4qqwsxk6908dlge.png" alt="Alt Text" width="512" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Clustering Key
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Clustering Key&lt;/em&gt; is responsible for sorting the rows within the partition. It can be zero or more columns.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem of Car Table
&lt;/h1&gt;

&lt;p&gt;Now that we know the difference about the &lt;em&gt;Composites Keys&lt;/em&gt;, let's remember how we modeling our &lt;em&gt;PK&lt;/em&gt; in Car table. In the &lt;em&gt;cqlsh&lt;/em&gt; after selecting the &lt;em&gt;Keyspace&lt;/em&gt;, use the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DESCRIBE car
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result will be.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE automobilies.car (
    id uuid PRIMARY KEY,
    brand text,
    color text,
    model text
) WITH bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
    AND comment = ''
    AND compaction = {'class': 'SizeTieredCompactionStrategy'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we can see, the unique &lt;em&gt;PK&lt;/em&gt; that we have is &lt;em&gt;id&lt;/em&gt; and could be calling of &lt;em&gt;Simple Primary Key&lt;/em&gt;. If we do a &lt;em&gt;select&lt;/em&gt; in the database, will retrieve only one car&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; select * from car;

 id                                   | brand | color | model
--------------------------------------+-------+-------+-------
 f714e8e5-b160-4341-807d-f4cd92b973a4 |    VW |   Red |  Golf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To improve our test, let's include more cars in the table. The same &lt;em&gt;model&lt;/em&gt; of car will have the same &lt;em&gt;id&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (e0625c94-e9c2-11eb-9a03-0242ac130003, 'Ford', 'Red', 'Focus');
cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (fbd04f2c-511a-43c5-b588-9e29ebcb5d7a, 'VW', 'Nardo Grey', 'Passat');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now the &lt;em&gt;select&lt;/em&gt; clause result in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; id                                   | brand | color      | model
--------------------------------------+-------+------------+--------
 fbd04f2c-511a-43c5-b588-9e29ebcb5d7a |    VW | Nardo Grey | Passat
 e0625c94-e9c2-11eb-9a03-0242ac130003 |  Ford |        Red |  Focus
 f714e8e5-b160-4341-807d-f4cd92b973a4 |    VW |        Red |   Golf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to find just a Golf car, we can query by &lt;em&gt;id&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; select * from car where id = f714e8e5-b160-4341-807d-f4cd92b973a4;

 id                                   | brand | color | model
--------------------------------------+-------+-------+-------
 f714e8e5-b160-4341-807d-f4cd92b973a4 |    VW |   Red |  Golf

(1 rows)

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

&lt;/div&gt;



&lt;p&gt;But what happening if we want to query by &lt;em&gt;id&lt;/em&gt; and &lt;em&gt;color&lt;/em&gt;? Well, maybe just need to add the &lt;em&gt;and&lt;/em&gt; in the query and choose &lt;em&gt;color&lt;/em&gt;, right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; select * from car where id = f714e8e5-b160-4341-807d-f4cd92b973a4 and color = 'Red';

InvalidRequest: Error from server: code=2200 [Invalid query] message="Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like we can see, when add &lt;em&gt;color&lt;/em&gt;, we get an error, but why? &lt;br&gt;
To answer this question, we need to understand how &lt;em&gt;Scylla&lt;/em&gt; saves data &lt;em&gt;(I will use an example with another domain)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fas7d3eshh5i5qtg4q8ho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fas7d3eshh5i5qtg4q8ho.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image above, we see that &lt;em&gt;Scylla&lt;/em&gt; uses a &lt;em&gt;PK&lt;/em&gt; to divide the partitions. When we use just &lt;em&gt;id&lt;/em&gt; for query, &lt;em&gt;Scylla&lt;/em&gt; knows exactly which node contains the data by hashing the ID (which is the partition key) and that is why we got results in the first query. In the second query, when we tried to filter for &lt;em&gt;color&lt;/em&gt;, wasn't possible, because we not defined &lt;em&gt;color&lt;/em&gt; as &lt;em&gt;Clustering Key&lt;/em&gt; or as &lt;em&gt;Partition Key&lt;/em&gt;. We would still know on which partition the data exists because we have the partition key, but we would have to do a linear scan of the entire data on that partition to find the specific row we are looking for &lt;em&gt;(using ALLOW FILTERING)&lt;/em&gt;, but performing this query would be inefficient and possibly very slow. To use &lt;em&gt;ALLOW FILTERING&lt;/em&gt; is like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; select * from car where id = f714e8e5-b160-4341-807d-f4cd92b973a4 and color = 'Red' ALLOW FILTERING;

 id                                   | brand | color | model
--------------------------------------+-------+-------+-------
 f714e8e5-b160-4341-807d-f4cd92b973a4 |    VW |   Red |  Golf

(1 rows)


cqlsh:automobilies&amp;gt; select * from car where id = f714e8e5-b160-4341-807d-f4cd92b973a4 and color = 'Green' ALLOW FILTERING;

---MORE---
(0 rows)

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

&lt;/div&gt;



&lt;p&gt;How we saw, this it's not good, so let's improve our data modeling. &lt;/p&gt;

&lt;h1&gt;
  
  
  Remodeling Car Table
&lt;/h1&gt;

&lt;p&gt;We should know for which attributes we will want to query to define our keys. How we want a query for &lt;em&gt;color&lt;/em&gt; and &lt;em&gt;id&lt;/em&gt;, both will be our &lt;em&gt;Pk&lt;/em&gt;, being &lt;em&gt;id&lt;/em&gt; a &lt;em&gt;Partition Key&lt;/em&gt; and &lt;em&gt;color&lt;/em&gt; a &lt;em&gt;Clustering Key&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; CREATE TABLE car (id uuid, brand text, color text, model text, PRIMARY KEY (id, color));

cqlsh:automobilies&amp;gt; DESCRIBE car;

CREATE TABLE automobilies.car (
    id uuid,
    color text,
    brand text,
    model text,
    PRIMARY KEY (id, color)
) WITH CLUSTERING ORDER BY (color ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'ALL'}
    AND comment = ''
    AND compaction = {'class': 'SizeTieredCompactionStrategy'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';

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

&lt;/div&gt;



&lt;p&gt;Now that we have a &lt;em&gt;Clustering Key&lt;/em&gt; we can &lt;em&gt;insert&lt;/em&gt; some cars with the same &lt;em&gt;id&lt;/em&gt;, but different colors and &lt;em&gt;Scylla&lt;/em&gt; will sort for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (f714e8e5-b160-4341-807d-f4cd92b973a4, 'VW', 'Red', 'Golf');
cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (e0625c94-e9c2-11eb-9a03-0242ac130003, 'Ford', 'Red', 'Focus');
cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (fbd04f2c-511a-43c5-b588-9e29ebcb5d7a, 'VW', 'Red', 'Passat');
cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (fbd04f2c-511a-43c5-b588-9e29ebcb5d7a, 'VW', 'Green', 'Passat');
cqlsh:automobilies&amp;gt; insert into car (id, brand, color, model) values (f714e8e5-b160-4341-807d-f4cd92b973a4, 'VW', 'Green', 'Golf');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our partition will stay like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03hs5yfh3jox5mjic2fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03hs5yfh3jox5mjic2fg.png" alt="Alt Text" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thus we have the partitions divided for &lt;em&gt;id&lt;/em&gt; and rows of cars sorted by color&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; select * from car;

 id                                   | color | brand | model
--------------------------------------+-------+-------+--------
 fbd04f2c-511a-43c5-b588-9e29ebcb5d7a | Green |    VW | Passat
 fbd04f2c-511a-43c5-b588-9e29ebcb5d7a |   Red |    VW | Passat
 e0625c94-e9c2-11eb-9a03-0242ac130003 |   Red |  Ford |  Focus
 f714e8e5-b160-4341-807d-f4cd92b973a4 | Green |    VW |   Golf
 f714e8e5-b160-4341-807d-f4cd92b973a4 |   Red |    VW |   Golf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can query by &lt;em&gt;id&lt;/em&gt; and &lt;em&gt;color&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cqlsh:automobilies&amp;gt; select * from car where id = fbd04f2c-511a-43c5-b588-9e29ebcb5d7a and color = 'Red';

 id                                   | color | brand | model
--------------------------------------+-------+-------+--------
 fbd04f2c-511a-43c5-b588-9e29ebcb5d7a |   Red |    VW | Passat

(1 rows)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In general, we saw how we define our &lt;em&gt;PK&lt;/em&gt; in &lt;em&gt;Scylla&lt;/em&gt;, can being &lt;em&gt;Partition Key&lt;/em&gt; and &lt;em&gt;Clustering Key&lt;/em&gt;. We need first think about our queries and after to model our tables. There are many others rules for work with these &lt;em&gt;PK's&lt;/em&gt;, but in a unique post is not possible to cover all subject matter. I recommend that you do the courses of &lt;a href="https://university.scylladb.com/" rel="noopener noreferrer"&gt;https://university.scylladb.com/&lt;/a&gt;. Well, this is what I wanted to introduce in this post, I really hope that you like it. Doubts, critics, and suggestions, I will be a disposition.  &lt;/p&gt;

</description>
      <category>database</category>
      <category>scylladb</category>
    </item>
    <item>
      <title>Integrating Scylla DB with Quarkus</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Wed, 26 May 2021 18:18:09 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/integrating-scylla-db-with-quarkus-519d</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/integrating-scylla-db-with-quarkus-519d</guid>
      <description>&lt;p&gt;Hello, everyone!! In the previous post, we talk about Scylla DB and some characteristics of the database. For those who have not seen it yet, this is the link &lt;a href="https://dev.to/j_a_o_v_c_t_r/working-with-scylla-database-3al9"&gt;https://dev.to/j_a_o_v_c_t_r/working-with-scylla-database-3al9&lt;/a&gt;. Today I intend to integrate the database with an application Java and to help us I decided to use Java + Quarkus. Quarkus is a Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best-of-breed Java libraries and standards. It is known as Supersonic Subatomic java because it is fast and small. To those interested, the link will be at the final of the post. Ok, now that we know our goal, let's start!!&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the application
&lt;/h1&gt;

&lt;p&gt;The first step is to create the application and for that, Quarkus gives us a simple interface that we can access at this link &lt;a href="https://code.quarkus.io/" rel="noopener noreferrer"&gt;https://code.quarkus.io/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0ptpmkx367vihz2crwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0ptpmkx367vihz2crwy.png" alt="Alt Text" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On this page we put information like &lt;em&gt;groupId&lt;/em&gt;, &lt;em&gt;artifactId&lt;/em&gt;, build tools, and select which dependencies we will use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favr8dypohiqj95jtogzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Favr8dypohiqj95jtogzp.png" alt="Alt Text" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's know about the selected dependencies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Datastack Apache Cassandra client: Driver to connect to Apache Cassandra databases. How we saw, Scylla DB is based on Cassandra, so we can use the same client.&lt;/li&gt;
&lt;li&gt;RESTEasy JSON-B: JSON-B serialization support for RESTEasy. We will use endpoints to interact with our application&lt;/li&gt;
&lt;li&gt;RESTEasy Mutiny: Mutiny support for RESTEasy server. If we want to call async resources (We don't use them in this example).&lt;/li&gt;
&lt;li&gt;SmallRye Health: Monitor service health.&lt;/li&gt;
&lt;li&gt;Micrometer Registry Prometheus: Enable Prometheus support for micrometer, so with this dependency, we can collect metrics for our application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, now we can generate our application in the Generate your application button. &lt;/p&gt;

&lt;p&gt;Let's import the application in our &lt;em&gt;IDE&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Quarkus gives us a &lt;em&gt;GET&lt;/em&gt; resource for testing, but we are not going to use it so we can delete it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3p8bgri3rqgxqr78h24n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3p8bgri3rqgxqr78h24n.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want test,  is enough execute mvn package quarkus:dev command, wait application is up and call &lt;a href="http://localhost:8080/hello-reasteasy" rel="noopener noreferrer"&gt;http://localhost:8080/hello-reasteasy&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can create our entity. &lt;em&gt;Entity&lt;/em&gt; class is a model for objects that we will work on. This object will be &lt;code&gt;Car&lt;/code&gt;. In the name of the class will use the annotation &lt;code&gt;@Entity&lt;/code&gt;. &lt;em&gt;The name of the class should be the same as the table of database&lt;/em&gt;. The object will have the fields &lt;em&gt;id&lt;/em&gt;, &lt;em&gt;brand&lt;/em&gt;, &lt;em&gt;color&lt;/em&gt;, and &lt;em&gt;model&lt;/em&gt;. How we saw in the previous post, the &lt;em&gt;id&lt;/em&gt; field is a &lt;em&gt;primary key&lt;/em&gt;, so we will use the annotation &lt;code&gt;@PartitionKey&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In the next post, I will talk about Scylla Primary Key and the differences in relation the relational databases&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuatj8eqk4hwec6yqn46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuatj8eqk4hwec6yqn46.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How we can see, the class does not compile, because we need to add some dependencies in our &lt;code&gt;pom.xml&lt;/code&gt;. This dependencies are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;com.datastax.oss:java-driver-core: A modern, feature-rich, and highly tunable Java client library for Apache Cassandra® (2.1+) and DataStax Enterprise (4.7+), and DataStax Astra, using exclusively Cassandra's binary protocol and Cassandra Query Language (CQL) v3.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;com.datastax.oss:java-driver-mapper-runtime: The mapper generates the boilerplate to execute queries and convert the results into application-level objects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;The dependencies can be downloaded in &lt;a href="https://mvnrepository.com/" rel="noopener noreferrer"&gt;https://mvnrepository.com/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And we need to change the original &lt;em&gt;maven-compiler-plugin&lt;/em&gt; in &lt;code&gt;pom.xml&lt;/code&gt; for the below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;plugin&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;3.8.0&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;source&amp;gt;${java.version}&amp;lt;/source&amp;gt;
                    &amp;lt;target&amp;gt;${java.version}&amp;lt;/target&amp;gt;
                    &amp;lt;annotationProcessorPaths&amp;gt;
                        &amp;lt;path&amp;gt;
                            &amp;lt;groupId&amp;gt;com.datastax.oss.quarkus&amp;lt;/groupId&amp;gt;
                            &amp;lt;artifactId&amp;gt;cassandra-quarkus-mapper-processor&amp;lt;/artifactId&amp;gt;
                            &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;
                        &amp;lt;/path&amp;gt;
                    &amp;lt;/annotationProcessorPaths&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is necessary because Quarkus need know the annotations in compile time for injecting the resources like &lt;em&gt;DAO&lt;/em&gt; and others. We'll see that soon.&lt;/p&gt;

&lt;p&gt;After including the dependencies in &lt;code&gt;pom.xml&lt;/code&gt;, we can import annotations and include &lt;em&gt;constructors&lt;/em&gt; and &lt;em&gt;getters/setters&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9o2fec5mpu49f12xk4h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9o2fec5mpu49f12xk4h.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;rest of the methods omitted!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The next step is to create the &lt;em&gt;Data Access Object&lt;/em&gt; or more commonly &lt;em&gt;DAO&lt;/em&gt;. Is enough for this post two methods, one &lt;em&gt;select&lt;/em&gt; method and one &lt;em&gt;insert&lt;/em&gt; method.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkok3sscjwqrdgbnva36p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkok3sscjwqrdgbnva36p.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The annotation &lt;code&gt;@Dao&lt;/code&gt; comes from the DataStax Object Mapper, which will also automatically generate an implementation of this &lt;em&gt;interface&lt;/em&gt; for us. &lt;code&gt;@Insert&lt;/code&gt; and &lt;code&gt;@Select&lt;/code&gt; generate an implementation of methods. Note also the special return type of the &lt;code&gt;findAll&lt;/code&gt; method, &lt;code&gt;PagingIterable&lt;/code&gt;: it’s the base type of result sets returned by the driver. &lt;/p&gt;

&lt;p&gt;Now let's create a &lt;em&gt;mapper&lt;/em&gt; that is responsible for constructing instances of &lt;em&gt;DAOs&lt;/em&gt;. In this case, will create an instance of &lt;code&gt;CarDAO&lt;/code&gt;. The name will be &lt;code&gt;CarMapper&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x3ga94wvvy61312s2gf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x3ga94wvvy61312s2gf.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To interact with the saved information or save new information in the database, we will create a &lt;em&gt;REST&lt;/em&gt; endpoint and for that will create a &lt;code&gt;CarResource&lt;/code&gt; class. For our example, we will need a &lt;em&gt;POST&lt;/em&gt; and a &lt;em&gt;GET&lt;/em&gt; method.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtp90fsna29s34j0tpif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtp90fsna29s34j0tpif.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In relation to the image above, let's talk about some details. The resource for access the application will be &lt;code&gt;cars&lt;/code&gt;. We should send JSON for the application and consume JSON of the application. To save or retrieve information, we need access to the database, so for that, we inject the &lt;code&gt;CarDAO&lt;/code&gt; in &lt;code&gt;CarResource&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The last step will be to configure the information of the database in the application. For that, we will use &lt;code&gt;application.properties&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiody4zjp0tm1dov2f5v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiody4zjp0tm1dov2f5v3.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we can see the information above when we up our node Scylla. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9160elcr75s6p500selq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9160elcr75s6p500selq.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start the application using &lt;code&gt;mvn package quarkus:dev&lt;/code&gt; command&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcarcsm794k55j0j8g192.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcarcsm794k55j0j8g192.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And to use our browser to do a request for the application &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjr0t5l3t1xm9kncebl8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjr0t5l3t1xm9kncebl8n.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Saving information&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcypr8u3xy47mki7n22fr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcypr8u3xy47mki7n22fr.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New saved information&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0rr7lgu4m10vpflmnjg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0rr7lgu4m10vpflmnjg.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tested requests, our application is complete and functional. We can now explore more features.&lt;/p&gt;

&lt;p&gt;The reason we put in our &lt;code&gt;pom.xml&lt;/code&gt; the &lt;code&gt;quarkus-smallrye-health&lt;/code&gt; dependency is automatically add a readiness health check to validate the connection to the Scylla cluster. We can access &lt;a href="http://localhost:8080/q/health/ready" rel="noopener noreferrer"&gt;http://localhost:8080/q/health/ready&lt;/a&gt; to know if our connection is healthy or not.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61mxej9evkksd91s8bmi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61mxej9evkksd91s8bmi.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now I will pause the docker that is running ScyllaDB&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kiq51j317bxy541i1aa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kiq51j317bxy541i1aa.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And test connection again&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy78r8r4oi3dcawq7x2xz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy78r8r4oi3dcawq7x2xz.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see the metrics of Scylla session and about individual Scylla nodes and for this is enough add a property &lt;code&gt;quarkus.cassandra.metrics.enabled=true&lt;/code&gt; in our &lt;code&gt;application.properties&lt;/code&gt; what we already did. To see metrics we can access &lt;a href="http://localhost:8080/metrics" rel="noopener noreferrer"&gt;http://localhost:8080/metrics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7s48ns07ledu4m21fxb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7s48ns07ledu4m21fxb.png" alt="Alt Text" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;My intention with this post is to show how we can integrate an application Java with Scylla DB and how easy that is using Quarkus. Some details can explorer yet, like primary key, but we can see this in the next post. I hope that you liked it and any doubt, critics, or suggestions tell me. Will be a pleasure to help you.&lt;/p&gt;

&lt;p&gt;References&lt;br&gt;
&lt;a href="https://quarkus.io/" rel="noopener noreferrer"&gt;https://quarkus.io/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://quarkus.io/guides/cassandra" rel="noopener noreferrer"&gt;https://quarkus.io/guides/cassandra&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>quarkus</category>
      <category>scylladb</category>
      <category>database</category>
    </item>
    <item>
      <title>Working with Scylla Database</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Sat, 24 Apr 2021 13:01:41 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/working-with-scylla-database-3al9</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/working-with-scylla-database-3al9</guid>
      <description>&lt;p&gt;Hello everyone! My intention today is to write about Scylla database. Scylla is a NoSQL database based on Cassandra. One difference between both is that Cassandra is developed in Java language and Scylla in C++ language. The goal of that is to avoid some Java processes that can impact the performance of the application, like garbage collector and &lt;em&gt;stop the world&lt;/em&gt;. After this introduction, let's see how we can use Scylla and know some details about it. &lt;/p&gt;

&lt;h1&gt;
  
  
  Downloading image
&lt;/h1&gt;

&lt;p&gt;For work with Scylla, we will use docker. The first step is to download the image. We can use the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name scylla-db-test -d scylladb/scylla:4.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we can use some tools of Scylla and guarantee that our database is healthy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it scylla-db-test nodetool status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of executing the command above is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address     Load       Tokens       Owns    Host ID                               Rack
UN  172.17.0.2  866.47 KB  256          ?       0b8a4db2-b8ea-49cf-b618-4eaf780ba7c7  rack1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is information about Datacenter, but this is not our focus in this post. At this moment, we should just know that our node &lt;em&gt;(more information about that in the next section)&lt;/em&gt; is Up and Normal &lt;strong&gt;(UN)&lt;/strong&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Playtime
&lt;/h1&gt;

&lt;p&gt;For executing commands in Scylla, there is a CLI called &lt;em&gt;cqlsh&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it scylla-db-test cqlsh

Connected to at 172.17.0.2:9042.
[cqlsh 5.0.1 | Cassandra 3.0.8 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing that we can do is create a &lt;em&gt;keyspace&lt;/em&gt;. Different from relational databases, Scylla doesn't have the database concept. In Scylla we work with &lt;em&gt;keyspace&lt;/em&gt;, which is a top-level container that stores tables. Besides creating a &lt;em&gt;keyspace&lt;/em&gt;, we need to configure other attributes like &lt;em&gt;replication strategy&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE KEYSPACE automobiles WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like I said previously, it's necessary to configure &lt;em&gt;replication strategy&lt;/em&gt; and how we can see, this is done with attribute &lt;em&gt;replication&lt;/em&gt;. Inside brackets has two configurations. The &lt;em&gt;replication_factor&lt;/em&gt; which means that the data inserted in a table of automobiles &lt;em&gt;keyspace&lt;/em&gt; will be replicated in 3 nodes. &lt;strong&gt;Nodes are instances of Scylla DB&lt;/strong&gt;. The other configuration is &lt;em&gt;class&lt;/em&gt; and defines the replication strategy class to use. There are 2 options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;'SimpleStrategy':&lt;/strong&gt; defines a replication factor for the whole cluster. The only sub-options supported is 'replication_factor' to define that replication factor and is mandatory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;'NetworkTopologyStrategy':&lt;/strong&gt; A replication strategy that lets you set the replication factor independently for each data center. The rest of the sub-options are key-value pairs where a key is a data-center name and its value is the associated replication factor or a single key-value with Auto-Expand Replication Factor. Recommended for production. &lt;strong&gt;(Just for knowledge, we won't talk about this option in this post)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we can create our table. The name will be &lt;em&gt;Car&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;USE automobiles ;

CREATE TABLE car (id uuid, brand text, model text, color text, PRIMARY KEY(id)) ;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How we can see, Scylla syntax is similar to SQL syntax, and to include data, we use the &lt;em&gt;insert&lt;/em&gt; clause.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT INTO car (id, brand, color, model) VALUES (123e4567-e89b-12d3-a456-426614174000, 'VW', 'Red', 'Golf');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see data in the table is just necessary to use the &lt;em&gt;select&lt;/em&gt; clause.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM car;

 id                                   | brand | color | model
--------------------------------------+-------+-------+-------
 123e4567-e89b-12d3-a456-426614174000 |    VW |   Red |  Golf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The idea of this post is to presenting Scylla DB and some operations that we can do. There are more details that I intended to present in the future, as partition key and clustering key, and how we can define our &lt;em&gt;primary key&lt;/em&gt; mixing up of both concepts. This is crucial for better performance at the moment that we need to filter our searches. For now, that is enough. I will see you in the next post. &lt;/p&gt;

&lt;p&gt;References &lt;br&gt;
&lt;a href="https://docs.scylladb.com/getting-started/dml/" rel="noopener noreferrer"&gt;https://docs.scylladb.com/getting-started/dml/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://university.scylladb.com/" rel="noopener noreferrer"&gt;https://university.scylladb.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>nosql</category>
      <category>scylla</category>
    </item>
    <item>
      <title>[PT-BR] Mark and Sweep e as gerações da heap</title>
      <dc:creator>João Victor Martins</dc:creator>
      <pubDate>Mon, 15 Mar 2021 20:40:54 +0000</pubDate>
      <link>https://forem.com/j_a_o_v_c_t_r/pt-br-mark-and-sweep-e-as-geracoes-da-heap-28dj</link>
      <guid>https://forem.com/j_a_o_v_c_t_r/pt-br-mark-and-sweep-e-as-geracoes-da-heap-28dj</guid>
      <description>&lt;p&gt;Um dos objetivos da &lt;strong&gt;JVM&lt;/strong&gt; é gerenciar a memória utilizada pelos nossos sistemas. Isto é feito através de processos que são executados ao longo do ciclo de vida da aplicação. O &lt;em&gt;garbage collector&lt;/em&gt; é um dos mais importantes. De forma resumida, ele é o responsável por liberar espaço na memória, coletando objetos que não estão mais sendo referenciados. A ideia deste post é explicar, em detalhes, como é feita esta coleta.&lt;/p&gt;

&lt;h1&gt;
  
  
  Garbage Collector
&lt;/h1&gt;

&lt;p&gt;Sempre que instanciamos um objeto na nossa aplicação, o mesmo é alocado em um espaço de memória chamado &lt;em&gt;heap&lt;/em&gt;. Com o passar do tempo muitos objetos perdem suas referências e não são mais úteis para o sistema. Com um acumulo de objetos não referenciados, o &lt;em&gt;garbage collector&lt;/em&gt; é invocado. O processo é chamado de &lt;em&gt;mark and sweep&lt;/em&gt; e envolve dois passos. No primeiro passo é necessário descobrir quais objetos ainda possuem referência. Uma vez descobertos estes objetos serão marcados. No segundo passo, todos os outros objetos que não foram marcados estarão prontos para a coleta e é nesse momento que ocorre uma varredura para liberação do espaço de memória. Um detalhe que não foi informado é que enquanto o processo é executado, a aplicação para de rodar, com o intuito de evitar concorrência com o &lt;em&gt;garbage collector&lt;/em&gt;. Essa parada é chamada de &lt;em&gt;stop the world&lt;/em&gt;. Se sempre que o &lt;em&gt;garbage collector&lt;/em&gt; for varrer a &lt;em&gt;heap&lt;/em&gt;, os objetos que possuem referência forem marcados, elevará o tempo da parada e os usuários sentirão que a aplicação não está respondendo naquele momento, o que não é interessante. Então como fazer para melhorar o processo de coleta?&lt;/p&gt;

&lt;h1&gt;
  
  
  Young e Old Generation
&lt;/h1&gt;

&lt;p&gt;Para evitar o problema visto anteriormente, a &lt;em&gt;heap&lt;/em&gt; foi dividida em gerações. Essas gerações são a &lt;em&gt;young generation&lt;/em&gt; e a &lt;em&gt;old generation&lt;/em&gt;. A &lt;em&gt;young&lt;/em&gt; possui um espaço menor e é dividida em 3 partes, que são o eden, s0 e s1 (survivor espaces). Todo novo objeto será criado no eden. Conforme aumenta a quantidade de objetos no eden, o &lt;em&gt;garbage collector&lt;/em&gt; é chamado, porém o processo de marcação e varredura leva menos tempo, pois conforme informado, há menos espaço destinado para a &lt;em&gt;young generation&lt;/em&gt;. Após a execução do &lt;em&gt;gc&lt;/em&gt;, os objetos que ainda possuem referência, serão alocados no espaço s0. Como novos objetos estão sendo criados no eden, quando o &lt;em&gt;gc&lt;/em&gt; é executado, ele irá olhar para os sobreviventes do eden e do s0 e os migrará para o espaço s1. Após esse processo inicial, todos os objetos criados no eden, poderão ser migrados para o s0 ou s1, sem ordem de precedência e o &lt;em&gt;gc&lt;/em&gt; atuará em todos estes espaços. Após um número &lt;em&gt;x&lt;/em&gt; de execuções (a depender da &lt;strong&gt;JVM&lt;/strong&gt; e configurações feitas pelos usuários) os objetos sobreviventes na &lt;em&gt;young generation&lt;/em&gt;, serão fragmentados e movidos para a &lt;em&gt;old generation&lt;/em&gt;. Na &lt;em&gt;old generation&lt;/em&gt; o processo de coleta será executado apenas quando necessário, ou seja, quando não possuir mais espaço e isso ocorrerá com menor frequência. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Percebemos que o &lt;em&gt;garbage collector&lt;/em&gt; é um processo extremamente importante para mantermos a performance da nossa aplicação. Porém, se fosse realizado a coleta em toda a &lt;em&gt;heap&lt;/em&gt;, por existir o &lt;em&gt;stop the world&lt;/em&gt;, a aplicação pararia de executar, para não concorrer com o &lt;em&gt;gc&lt;/em&gt; e isso causaria uma instisfação aos usuários do sistema, que iriam sentir que a aplicação não estaria respondendo naquele momento. Isso é evitado graças as gerações da &lt;em&gt;heap&lt;/em&gt;. Na &lt;em&gt;young generation&lt;/em&gt; o processo de coleta é executado com maior frequência, mas de forma muito rápida, pois é um espaço menor, fazendo com que não seja percebida pelos usuários. Já na &lt;em&gt;old generation&lt;/em&gt;, espaço que possui os objetos sobreviventes, o processo é executado apenas quando necessário, com uma frequência bem menor, e quando ocorre, apesar de ser sentido pelos usuários, não é tão prejudicial. O assunto do post de hoje foi curto, porém complexo, então toda crítica, dúvida ou sugestão serão bem-vindas. Espero que tenham gostado. Até o próximo. &lt;/p&gt;

</description>
      <category>java</category>
      <category>jvm</category>
      <category>ptbr</category>
    </item>
  </channel>
</rss>
