<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Elattar Saad </title>
    <description>The latest articles on DEV Community by Elattar Saad  (@daasrattale).</description>
    <link>https://dev.to/daasrattale</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%2F420954%2Fa7064770-0c23-43a9-b83b-8d3be2b9bcba.jpeg</url>
      <title>DEV Community: Elattar Saad </title>
      <link>https://dev.to/daasrattale</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daasrattale"/>
    <language>en</language>
    <item>
      <title>Spring streaming response made easy</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Wed, 10 Sep 2025 19:34:52 +0000</pubDate>
      <link>https://dev.to/daasrattale/spring-streaming-response-made-easy-5ddh</link>
      <guid>https://dev.to/daasrattale/spring-streaming-response-made-easy-5ddh</guid>
      <description>&lt;p&gt;In certain scenarios, we need to retrieve large volumes of data, yet we often experience delays before the first pieces of the response are displayed. Fortunately, this is a well-known problem, and an effective solution exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  TechStack
&lt;/h2&gt;

&lt;p&gt;This project is built using: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 24.&lt;/li&gt;
&lt;li&gt;Spring boot 3.5.5 with WebFlux.&lt;/li&gt;
&lt;li&gt;Postgres (or any DB you want)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use case
&lt;/h2&gt;

&lt;p&gt;Simply, we need 1 million products (json objects) in the GET endpoint.&lt;/p&gt;

&lt;p&gt;this is a simple SQL script to create and fill the products table:&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="c1"&gt;-- Create table&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;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;products&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;SERIAL&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;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;255&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;price&lt;/span&gt; &lt;span class="nb"&gt;NUMERIC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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="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="c1"&gt;-- Insert 100,000 products&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;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="s1"&gt;'Product '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ROUND&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;RANDOM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)::&lt;/span&gt;&lt;span class="nb"&gt;numeric&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="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;generate_series&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="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next the entity and JPA repository:&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;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Product&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="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&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;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&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;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Double&lt;/span&gt; &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="o"&gt;()&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;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Product["&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"id="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"name="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s"&gt;"price="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sc"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.data.jpa.repository.JpaRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;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;blockquote&gt;
&lt;p&gt;Any database can be used here, I'm just used to postgres due to my daily work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Traditional endpoints
&lt;/h2&gt;

&lt;p&gt;Nothing fancy for our traditional endpoint, a simple find all GET:&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;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ProductController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;productRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAll&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;productRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&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;While using this endpoint, the client needs to wait before exploiting the first returned product, or even worse, the response size is too big to be handled properly:&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%2Fsaxyf26rsk4g14tlxaju.gif" 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%2Fsaxyf26rsk4g14tlxaju.gif" alt="Tradition endpoint" width="760" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming Response to the rescue
&lt;/h2&gt;

&lt;p&gt;Using StreamingResponseBody, we can stream our products one by one and save some time :)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GetMapping("/stream")
    public StreamingResponseBody getAllStreamed(HttpServletResponse response){
       response.setContentType("text/event-stream");
       return outputStream -&amp;gt; {
           productRepository.findAll()
                    .forEach(product -&amp;gt; {
                        try {
                            String json = new ObjectMapper().writeValueAsString(product) + "\n";
                            outputStream.write(json.getBytes());
                            outputStream.flush();
                        } catch (JsonProcessingException e) {
                            log.error("Error parsing product to json", e);
                        } catch (IOException e) {
                            log.error("Error writing object to stream", e);
                        }
                    });
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ffi9qdyonlmevgd7kdnrz.gif" 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%2Ffi9qdyonlmevgd7kdnrz.gif" alt="Stream endpoint" width="200" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  On another level
&lt;/h2&gt;

&lt;p&gt;You may already noticed that we loop over the products and write one by one to the output stream, this can be improved even more by streaming data end-2-end from the data source to the client; For that purpose solutions like Spring Webflux and JPA streams exist. &lt;br&gt;
(The resources are just below :D)&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Streaming with JPA &lt;code&gt;Stream&amp;lt;T&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vladmihalcea.com/spring-data-jpa-stream/" rel="noopener noreferrer"&gt;The best way to use Spring Data JPA Stream methods&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Server-Sent Events (SSE) / Reactive
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-webflux" rel="noopener noreferrer"&gt;Spring Boot WebFlux Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://projectreactor.io/docs/core/release/reference/" rel="noopener noreferrer"&gt;Project Reactor Flux Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read this article and more on my website: &lt;a href="https://www.saadelattar.me/article/spring-response-streams" rel="noopener noreferrer"&gt;https://www.saadelattar.me/article/spring-response-streams&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spring</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Blossoming Intelligence: How to Run Spring AI Locally with Ollama</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Sat, 11 May 2024 15:21:58 +0000</pubDate>
      <link>https://dev.to/daasrattale/blossoming-intelligence-how-to-run-spring-ai-locally-with-ollama-1k70</link>
      <guid>https://dev.to/daasrattale/blossoming-intelligence-how-to-run-spring-ai-locally-with-ollama-1k70</guid>
      <description>&lt;p&gt;Nobody can dispute that AI is here to stay. Among many of its benefits, developers are using its capability to boost their productivity. &lt;br&gt;
It is also planned to become accessible for a fee as a SaaS or any other service once it has gained the necessary trust from enterprises. &lt;br&gt;
Still, We can run pre-trained models locally and incorporate them into our current app.&lt;/p&gt;

&lt;p&gt;In this short article, we'll look at how easy it is to create a chat bot backend powered by Spring and Olama using the llama 3 model.&lt;/p&gt;

&lt;h2&gt;
  
  
  TechStack
&lt;/h2&gt;

&lt;p&gt;This project is built using: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java 21.&lt;/li&gt;
&lt;li&gt;Spring boot 3.2.5 with WebFlux.&lt;/li&gt;
&lt;li&gt;Spring AI 3.2.5.&lt;/li&gt;
&lt;li&gt;Ollama 0.1.36.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ollama Setup
&lt;/h2&gt;

&lt;p&gt;To install Ollama locally, you simply need to head to &lt;a href="https://ollama.com/download" rel="noopener noreferrer"&gt;https://ollama.com/download&lt;/a&gt; and install it using the proper executable to your OS.&lt;/p&gt;

&lt;p&gt;You check is installed by running the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ollama &lt;span class="nt"&gt;--version&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can directly pull a model from &lt;a href="https://ollama.com/library" rel="noopener noreferrer"&gt;Ollama Models&lt;/a&gt;) and run it using the ollama cli, in my case I used the llama3 model:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

ollama pull llama3 &lt;span class="c"&gt;# Should take a while.&lt;/span&gt;
ollama run llama3


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

&lt;/div&gt;

&lt;p&gt;Let's test it out with a simple prompt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxzwe25h6vn4yphoivsry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxzwe25h6vn4yphoivsry.png" alt="Image description" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To exist, use the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

/bye


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Talking Spring
&lt;/h2&gt;

&lt;p&gt;The Spring will have the following properties:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

spring.ai.ollama.base-url=http://localhost:11434
spring.ai.ollama.chat.model=llama3


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

&lt;/div&gt;

&lt;p&gt;Then is our chat package, will have a chat config bean to handle:&lt;/p&gt;

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

package io.daasrattale.generalknowledge.chat;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatConfig {


    @Bean
    public ChatClient chatClient() {
        return new OllamaChatClient(new OllamaApi())
                .withDefaultOptions(OllamaOptions.create()
                        .withTemperature(0.9f));
    }
}


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;FYI, Model temperature is a parameter that controls how random a language model's output is. &lt;br&gt;
A temperature is set to 0.9 to make the model more random and willing to take more risks on the answers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last step is to create a simple Chat rest controller:&lt;/p&gt;

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

package io.daasrattale.generalknowledge.chat;

import org.springframework.ai.ollama.OllamaChatClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/v1/chat")
public class ChatController {


    private final OllamaChatClient chatClient;

    public ChatController(OllamaChatClient chatClient) {
        this.chatClient = chatClient;
    }

    @GetMapping
    public Mono&amp;lt;ResponseEntity&amp;lt;String&amp;gt;&amp;gt; generate(@RequestParam(defaultValue = "Tell me to add a proper prompt in a funny way") String prompt) {
        return Mono.just(
                ResponseEntity.ok(chatClient.call(prompt))
        );
    }


}


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

&lt;/div&gt;

&lt;p&gt;Let's try and call a GET /v1/chat with an empty prompt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fyfnh5pnr607uuttm0tvs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fyfnh5pnr607uuttm0tvs.png" alt="Image description" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What about a simple general knowledge question:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhcws23jv7a05snocyb9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhcws23jv7a05snocyb9d.png" alt="Image description" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, let's ask for some code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F87sdfw5ocxjl6t85febe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F87sdfw5ocxjl6t85febe.png" alt="Image description" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The api url provided is not OK, still the rest of the code works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Using models locally with such ease and simplicity can be considered as a true added value, still, the used models must be heavily inspected.&lt;/p&gt;

&lt;p&gt;You can find the source code on this &lt;a href="https://github.com/daasrattale/spring-ai-ollama-chat-client" rel="noopener noreferrer"&gt;Github Repository&lt;/a&gt; make sure to star it if you find it useful :))&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://spring.io/projects/spring-ai" rel="noopener noreferrer"&gt;https://spring.io/projects/spring-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-ai/reference/api/clients/ollama-chat.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-ai/reference/api/clients/ollama-chat.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spring</category>
      <category>ai</category>
      <category>ollama</category>
      <category>llama3</category>
    </item>
    <item>
      <title>React 19: The long-expected features</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Wed, 17 Apr 2024 03:52:32 +0000</pubDate>
      <link>https://dev.to/daasrattale/react-19-the-long-expected-features-1kod</link>
      <guid>https://dev.to/daasrattale/react-19-the-long-expected-features-1kod</guid>
      <description>&lt;p&gt;React 19 introduces a number of new features that will undoubtedly make the life of react developers simpler. While the release is not yet stable, you can test out the new features using the canary version.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;

npm i react@canary react-dom@canary


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  React Forget
&lt;/h2&gt;

&lt;p&gt;The react compiler (called "React Forget") in version 19 is nothing short of game-changing. Whiles some solutions included their own compilers to maximize developer efficiency, React initially solely operated in the browser. &lt;/p&gt;

&lt;p&gt;Once a compiler is in place, React developers can concentrate on creating business features rather than worrying about things like momoization. &lt;br&gt;
Yes, you heard that righ the momoization hooks (useMemo and useCallback) and memo API will no longer be needed since&lt;br&gt;
the compiler will be handling that automatically and more efficiently without compromising the application performance nor the code base quality.&lt;/p&gt;

&lt;p&gt;The React compiler is already been deployed in Instagram web app Production. You can see it in action in this &lt;a href="https://www.youtube.com/watch?v=qOQClO3g8-Y" rel="noopener noreferrer"&gt;ReactAdvanced Conf talk&lt;/a&gt; by Joe Savona and Mofei Zhang.&lt;/p&gt;
&lt;h2&gt;
  
  
  Actions
&lt;/h2&gt;

&lt;p&gt;React 19 introduces the ability to run actions on either the server or the client using the directives "use client" &lt;br&gt;
or "use server". Previously, Server Actions were used to transport data from the client to the server. &lt;br&gt;
As a result, we now refer to them as "actions". &lt;/p&gt;

&lt;p&gt;If you're acquainted with &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJs&lt;/a&gt;, the directives will come as no surprise.&lt;/p&gt;

&lt;p&gt;To manage async actions, React provides a useFormStatus and useFormState hooks to handle the pending status and state to prevent multiple submissions of a form for instance.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hooks
&lt;/h2&gt;

&lt;p&gt;React 19 came with a set of new hooks that will either replace existing hooks or support the new of its features.&lt;/p&gt;
&lt;h3&gt;
  
  
  useFormStatus
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFormStatus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Submit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormStatus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// will return {pending, data, method, action}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Submit&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h3&gt;
  
  
  useFormState
&lt;/h3&gt;

&lt;p&gt;The actions can also return values, in that case we need use the useFormState hook.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFormState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&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="nx"&gt;previousState&lt;/span&gt; &lt;span class="o"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;StatefulForm&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formAction&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;increment&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;formAction&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formAction&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increment&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Know more about the &lt;a href="https://react.dev/reference/react-dom/hooks/useFormStatus" rel="noopener noreferrer"&gt;useFormStatus&lt;/a&gt; and &lt;a href="https://react.dev/reference/react-dom/hooks/useFormState" rel="noopener noreferrer"&gt;useFormState&lt;/a&gt; hooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  useOptimistic
&lt;/h3&gt;

&lt;p&gt;The useOptimistic hook can be used to provide the user with a temporary ui based on what they already submitted, &lt;br&gt;
for instance showing the newly sent message while the data is processed on the server.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useOptimistic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;deliverMessage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./actions.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sendMessage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;addOptimisticMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// we get the input of the user; used to build the temp ui.&lt;/span&gt;
    &lt;span class="nx"&gt;formRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// reset the form.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// sending the data to the server asynchronosly.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;optimisticMessages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addOptimisticMessage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useOptimistic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;sending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;optimisticMessages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;// getting the newly sent messages, mapping them into dom elements (optimistic UI).&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sending&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;small&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; (Sending...)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;small&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formAction&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Just a simple form with action and ref*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt; &lt;span class="na"&gt;placeholder&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;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Putting the Thread component in action by providing a state.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMessages&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello there!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sentMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deliverMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;setMessages&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sentMessage&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sendMessage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Know more about the &lt;a href="https://react.dev/reference/react/useOptimistic" rel="noopener noreferrer"&gt;useOptimistic&lt;/a&gt; hook.&lt;/p&gt;

&lt;h3&gt;
  
  
  useCallback and useMemo
&lt;/h3&gt;

&lt;p&gt;As previously stated the momoization will be handled by the React Compiler, therefor the useMemo, &lt;br&gt;
useCallback hooks and memo API won't make it to the version 19 of React.&lt;/p&gt;

&lt;h3&gt;
  
  
  use
&lt;/h3&gt;

&lt;p&gt;The use hook is here to clean more the react code base, it will replace two widly used hooks (thank God): useEffect and useContext.&lt;/p&gt;

&lt;p&gt;One of the famous use cases for the useEffect hook is data fetching, for this example we fetch the user details and return a UserProfile:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;


  &lt;span class="c1"&gt;// Using useEffect hook to fetch data.&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userDetails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUserDetails&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;getUserDetails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// async function&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setUserDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;},[])&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userDetails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Using use hook to fetch data.&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// another component for simplicity&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getUserDetails&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&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="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;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;The use hook will also be replacing the useContext hook:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c1"&gt;// Using useContext hook to consume the theme context.&lt;/span&gt;&lt;br&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;// Using use hook to consume the theme context&lt;/span&gt;&lt;br&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  ForwardRef&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;No more forwardRef! We can simply pass the ref down like any other prop without the use of forwardRef.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProfilePicture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;forwardRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;// src and alt are props&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;// On v19&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProfilePicture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;br&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  SEO&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;React will enable the usage of the &amp;lt;title&amp;gt;, &amp;lt;meta&amp;gt;, and &amp;lt;link&amp;gt; tags anywhere in the App, improving SEO performance. &lt;br&gt;
Previously, libraries like as &lt;a href="https://www.npmjs.com/package/react-helmet" rel="noopener noreferrer"&gt;react-helmet&lt;/a&gt; were used for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In my perspective, React v19 will deliver a lot of relevant and required enhancements, allowing developers to focus more on important features that matter!&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024#react-compiler" rel="noopener noreferrer"&gt;https://react.dev/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024#react-compiler&lt;/a&gt;&lt;br&gt;
&lt;a href="https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-optimizing-compiler" rel="noopener noreferrer"&gt;https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-optimizing-compiler&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=qOQClO3g8-Y" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=qOQClO3g8-Y&lt;/a&gt;&lt;br&gt;
&lt;a href="https://react.dev/reference/react/" rel="noopener noreferrer"&gt;https://react.dev/reference/react/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>react19</category>
      <category>compiler</category>
      <category>use</category>
    </item>
    <item>
      <title>Just a simple Songs API using Spring Reactive with Functional Endpoints, Docker and MongoDB</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Thu, 29 Feb 2024 00:55:13 +0000</pubDate>
      <link>https://dev.to/daasrattale/just-a-simple-songs-api-using-spring-reactive-with-functional-endpoints-docker-and-mongodb-2hp7</link>
      <guid>https://dev.to/daasrattale/just-a-simple-songs-api-using-spring-reactive-with-functional-endpoints-docker-and-mongodb-2hp7</guid>
      <description>&lt;p&gt;Blocking is a feature of classic servlet-based web frameworks like Spring MVC. Introduced in Spring 5, Spring WebFlux is a reactive framework that operates on servers like &lt;strong&gt;Netty&lt;/strong&gt; and is completely non-blocking.&lt;/p&gt;

&lt;p&gt;Two programming paradigms are supported by Spring WebFlux. Annotations (Aspect Oriented Programming) and WebFlux.fn (Functional Programming).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Spring WebFlux includes WebFlux.fn, a lightweight functional programming model in which functions are used to route and handle requests and contracts are designed for immutability. It is an alternative to the annotation-based programming model but otherwise runs on the same Reactive Core foundation." &lt;a href="https://docs.spring.io/spring-framework/reference/web/webflux-functional.html" rel="noopener noreferrer"&gt;Spring | Functional Endpoints&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Project Description
&lt;/h2&gt;

&lt;p&gt;As the title describe, this is a simple Songs API build using Spring, Docker and MongoDB, the endpoints are Functional Endpoints and will have the traditional ControllerAdvice as Exception handler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Dependencies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Java Version &lt;code&gt;21&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Spring Boot version &lt;code&gt;3.3.0-SNAPSHOT&lt;/code&gt; with Spring Reactive Starter.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://spring.io/blog/2023/06/21/docker-compose-support-in-spring-boot-3-1" rel="noopener noreferrer"&gt;Spring Docker Support&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Lombok (Optional).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Talking XML these are the project dependencies:&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;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.springframework.boot&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;spring-boot-starter-data-mongodb-reactive&lt;span class="nt"&gt;&amp;lt;/artifactId&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.springframework.boot&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;spring-boot-starter-webflux&lt;span class="nt"&gt;&amp;lt;/artifactId&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.springframework.boot&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;spring-boot-docker-compose&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;runtime&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;optional&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/optional&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.projectlombok&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;lombok&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;optional&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/optional&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.springframework.boot&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;spring-boot-starter-test&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;io.projectreactor&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;reactor-test&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;/dependencies&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Coding time!
&lt;/h2&gt;

&lt;p&gt;First, let's setup the docker compose file &lt;code&gt;/compose.yaml&lt;/code&gt; of the project (it should generated by spring via the docker support starter).&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mongodb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mongo:7.0.5'&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MONGO_INITDB_DATABASE=songsDB'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MONGO_INITDB_ROOT_PASSWORD=passw0rd'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MONGO_INITDB_ROOT_USERNAME=root'&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;27017'&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;With that set, let's create the Song class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;


&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.AllArgsConstructor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Builder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Getter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Setter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.data.annotation.Id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.data.mongodb.core.mapping.Document&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.UUID&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Document&lt;/span&gt;
&lt;span class="nd"&gt;@Getter&lt;/span&gt;
&lt;span class="nd"&gt;@Setter&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class="nd"&gt;@Builder&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Song&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="no"&gt;UUID&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;artist&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 SongRepository interface will be referring to the Song class in its DB ops:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.data.repository.reactive.ReactiveCrudRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;reactor.core.publisher.Flux&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.UUID&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SongRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ReactiveCrudRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Song&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;UUID&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;Flux&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Song&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAllByArtist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Song Functional Endpoint and Handler
&lt;/h2&gt;

&lt;p&gt;Now, it's time for the Song Router, it will be responsible for router the incoming requests for the /songs ressource:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.annotation.Bean&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.annotation.Configuration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.reactive.function.server.RouterFunction&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.reactive.function.server.ServerResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;springframework&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reactive&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RouterFunctions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SongRouterConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;SongHandler&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;SongRouterConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SongHandler&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RouterFunction&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;router&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/songs"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;builder&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="s"&gt;"/artist"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;handler:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;findAllByArtist&lt;/span&gt;&lt;span class="o"&gt;)&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="nl"&gt;handler:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Get endpoints' order is important&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;POST&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/new"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;handler:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&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;DELETE&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{id}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;handler:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;delete&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="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 you noticed the request are redirected to the SongHandler for a certain logic to be performed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you having trouble understanding the syntax, make sure to know more about Java functional interfaces, lambda and method references.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The SongsHandler will act as Service as well, will perform a business logic and communicate with the SongRepository for operations with the database.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.daasrattale.webfluxmongofunctionalendpoints.song.exceptions.InvalidParamException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.daasrattale.webfluxmongofunctionalendpoints.song.exceptions.InvalidUUIDException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.HttpStatus&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Service&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.reactive.function.server.ServerRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.reactive.function.server.ServerResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;reactor.core.publisher.Mono&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Optional&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.UUID&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SongHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;SongRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;SongHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SongRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ServerRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="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="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="nc"&gt;Song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAllByArtist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ServerRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;just&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;queryParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artist"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;switchIfEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidParamException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"artist"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;Optional:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;repository:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;findAllByArtist&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;songFlux&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                        &lt;span class="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="n"&gt;songFlux&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ServerRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&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;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bodyToMono&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;switchIfEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Song body not found"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt; &lt;span class="c1"&gt;// you can use that or create a custom exception (recommended)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doOnNext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;song&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomUUID&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;song&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CREATED&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="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;song&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Song&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ServerResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ServerRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;just&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pathVariable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;UUID:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;fromString&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doOnError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;throwable&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidUUIDException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;throwable&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="na"&gt;flatMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;songId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;ServerResponse&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                        &lt;span class="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="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;songId&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="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;blockquote&gt;
&lt;p&gt;Note: The &lt;code&gt;SongHandler&lt;/code&gt; can be annotated with @Component, since it performs a business logic I see it better have the @Service annotation instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Exception Handling
&lt;/h2&gt;

&lt;p&gt;As previously states, will be using the same old ControllerAdvice as Exception handler with two custom Exceptions as the following:&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Exceptions
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Getter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Getter&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvalidParamException&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;paramName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InvalidParamException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;paramName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;paramName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paramName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Getter&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Getter&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvalidUUIDException&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;cause&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InvalidUUIDException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;cause&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cause&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;h3&gt;
  
  
  Custom Exception Handler
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;io.daasrattale.webfluxmongofunctionalendpoints.song.exceptions.InvalidUUIDException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.extern.slf4j.Slf4j&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.ControllerAdvice&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Map&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@ControllerAdvice&lt;/span&gt;
&lt;span class="nd"&gt;@Slf4j&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SongExceptionHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;


    &lt;span class="nd"&gt;@ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvalidUUIDException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;InvalidUUIDException&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;badRequest&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="nc"&gt;Map&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="s"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid UUID"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                &lt;span class="s"&gt;"details"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCause&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getMessage&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="nd"&gt;@ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unhandled Error, message: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;internalServerError&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="nc"&gt;Map&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="s"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                &lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Unknown Error"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                                &lt;span class="s"&gt;"details"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&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="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;With all that been set, let's make use of our endpoint using Postman:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a new Song&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0f7tvnuyajf7x9asbuyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0f7tvnuyajf7x9asbuyz.png" alt="Image description" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting songs by artist:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F939xjmtqvw2uhh309q30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F939xjmtqvw2uhh309q30.png" alt="Image description" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting all songs:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fenvukk15y5l77rwwubey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fenvukk15y5l77rwwubey.png" alt="Image description" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deleting a song:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sorry not a big fan of Madonna tbh :|&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwu4g85olizwlc2897gnq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwu4g85olizwlc2897gnq.png" alt="Image description" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checking the result of the delete op:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fr1oxqh4z73h0xevyclel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fr1oxqh4z73h0xevyclel.png" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally,
&lt;/h2&gt;

&lt;p&gt;With that said, our functional songs endpoint will be good to go for further improvements and new features.&lt;br&gt;
This is simple, in real industrial projects, I can assure you things get complicated with more layers, for "getting started" purposes I avoided the use of advanced concepts such as validation, DTO, etc.&lt;/p&gt;

&lt;p&gt;You can find the full source &lt;a href="https://github.com/daasrattale/webflux-functional-endpoints" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also find more content on my personal &lt;a href="https://saadelattar.me" rel="noopener noreferrer"&gt;personal website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>docker</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Spring cloud: introduction to service discovery using netflix eureka</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Fri, 11 Feb 2022 23:16:18 +0000</pubDate>
      <link>https://dev.to/daasrattale/spring-cloud-introduction-to-service-discovery-using-netflix-eureka-3n7k</link>
      <guid>https://dev.to/daasrattale/spring-cloud-introduction-to-service-discovery-using-netflix-eureka-3n7k</guid>
      <description>&lt;p&gt;Micro-services are all good until they come with their distributed challenges which normally we don't face in monolithic based applications. Just like this one! &lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the problem
&lt;/h2&gt;

&lt;p&gt;In order to fully get the main purpose of the solution let us first understand the underlying problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fdtykjd163n264gromr38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fdtykjd163n264gromr38.png" alt="Image description" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the diagram above shows, we have to micro-services communicating via a certain network:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Micro-service I with the IP address &lt;strong&gt;10.10.10.10&lt;/strong&gt;, and port &lt;strong&gt;8080&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Micro-service II with the IP address &lt;strong&gt;20.20.20.20&lt;/strong&gt;, and port &lt;strong&gt;8090&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All working peacefully until the second micro-service changed its address and port for some reason.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgoalbpttrw926n56i3r0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgoalbpttrw926n56i3r0.png" alt="Image description" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As result the micro-service I cannot communicate with micro-service II since it doesn't have the new address and port (30.30.30.30:5000).&lt;br&gt;
To resolve this we need to provide &lt;strong&gt;manually&lt;/strong&gt; the micro-service I with the micro-service II's new address and port. &lt;strong&gt;What if we can do that automatically?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer is YES, and that's exactly what Netflix Eureka does.&lt;/p&gt;
&lt;h2&gt;
  
  
  Eureka under the hood
&lt;/h2&gt;

&lt;p&gt;The first thing MS2 will do is to register to the naming registry server (Eureka server) providing mainly its IP, port and status (UP or DOWN). [A]&lt;/p&gt;

&lt;p&gt;Before MS1 makes the call to MS2 [D], it will fetch the MS2 coordinates from the naming registry [B] which will allow the communication to happen even if MS2 changes its location a million times as long as its registers to the Eureka server. The server will respond with the required data. [C]&lt;/p&gt;

&lt;p&gt;You should also understand that by fetching the naming registry or registering to it, the micro-service becomes its client (Eureka client).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhcolkbw8euex1ce28c4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhcolkbw8euex1ce28c4q.png" alt="Image description" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's talk code
&lt;/h2&gt;

&lt;p&gt;For this tutorial I'll be using:&lt;/p&gt;

&lt;p&gt;Spring Boot 2.6.2&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;parent&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&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;spring-boot-starter-parent&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;2.6.2&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;relativePath/&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- lookup parent from repository --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Java 8 &amp;amp;&amp;amp; Spring cloud 2021.0.0 &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;properties&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;java.version&amp;gt;&lt;/span&gt;1.8&lt;span class="nt"&gt;&amp;lt;/java.version&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;spring-cloud.version&amp;gt;&lt;/span&gt;2021.0.0&lt;span class="nt"&gt;&amp;lt;/spring-cloud.version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;and of course the dependency management for the spring cloud modules&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.springframework.cloud&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;spring-cloud-dependencies&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;${spring-cloud.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Eureka server configuration
&lt;/h3&gt;

&lt;p&gt;The Eureka server require the Spring Cloud starter netflix eureka server dependency&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;org.springframework.cloud&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;spring-cloud-starter-netflix-eureka-server&lt;span class="nt"&gt;&amp;lt;/artifactId&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;Then, we need a set of properties as the following&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# Setting a name for out app&lt;/span&gt;
&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry-server&lt;/span&gt;

&lt;span class="c1"&gt;# Simply telling Eureka server to NOT fetch or register to any server since it's not a client.&lt;/span&gt;
&lt;span class="na"&gt;eureka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;register-with-eureka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;fetch-registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Finally, we need to declare our app as a registry service using the &lt;code&gt;@EnableEurekaServer&lt;/code&gt; annotation:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@SpringBootApplication
@EnableEurekaServer
public class RegistryEurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(RegistryEurekaServerApplication.class, args);
    }

}


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

&lt;/div&gt;
&lt;p&gt;You can find a user interface generated by Eureka, for our case is on &lt;a&gt;localhost:8099&lt;/a&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-cloud-eureka-dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-cloud-eureka-dashboard.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Eureka client configuration
&lt;/h3&gt;

&lt;p&gt;The Eureka client require the Spring Cloud starter netflix eureka client dependency&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;org.springframework.cloud&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;spring-cloud-starter-netflix-eureka-client&lt;span class="nt"&gt;&amp;lt;/artifactId&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;Also for this one, we need a set of properties:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# Setting a name for out app&lt;/span&gt;
&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry-eureka-client&lt;/span&gt;

&lt;span class="na"&gt;eureka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# To register to the eureka server&lt;/span&gt;
    &lt;span class="na"&gt;registerWithEureka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="c1"&gt;# To fetch the registry from the eureka server&lt;/span&gt;
    &lt;span class="na"&gt;fetchRegistry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="c1"&gt;# The location of the eureka server&lt;/span&gt;
    &lt;span class="na"&gt;serviceUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;defaultZone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8099/eureka/&lt;/span&gt;

  &lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# The instance hostname&lt;/span&gt;
    &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;

    &lt;span class="c1"&gt;# The instance unique id&lt;/span&gt;
    &lt;span class="na"&gt;instanceId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${eureka.instance.hostname}:${spring.application.name}&lt;/span&gt;

    &lt;span class="c1"&gt;# A bench of health information end-points provided by eureka&lt;/span&gt;
    &lt;span class="na"&gt;statusPageUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://${eureka.hostname}/&lt;/span&gt;
    &lt;span class="na"&gt;healthCheckUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://${eureka.hostname}/actuator/health&lt;/span&gt;
    &lt;span class="na"&gt;secureHealthCheckUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://${eureka.hostname}/actuator/health&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;Finally, we need to declare our app as a discovery client (Eureka client) using the &lt;code&gt;@EnableDiscoveryClient&lt;/code&gt; annotation:&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;@SpringBootApplication&lt;/span&gt;
&lt;span class="nd"&gt;@EnableDiscoveryClient&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistryEurekaClientApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RegistryEurekaClientApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Once, we start our client app, we will notice that it successfully registered to the running eureka server.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-cloud-eureka-register-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-cloud-eureka-register-1.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;And on the UI dashboard, you can see this:&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-cloud-eureka-register-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-cloud-eureka-register-2.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This may seem &lt;strong&gt;incomplete&lt;/strong&gt;, actually it is, since we're not fetching the eureka server for registered service instances and exploit them. That's the main purpose of the next article when we will be doing so using a &lt;strong&gt;reverse proxy&lt;/strong&gt; called &lt;strong&gt;Netflix Zuul&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;More articles &lt;a href="https://elattar.me/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
      <category>eureka</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Spring internal micro-service driven communication</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Sat, 01 Jan 2022 20:04:18 +0000</pubDate>
      <link>https://dev.to/daasrattale/spring-internal-micro-service-driven-communication-5co8</link>
      <guid>https://dev.to/daasrattale/spring-internal-micro-service-driven-communication-5co8</guid>
      <description>&lt;p&gt;During the solution architecture phase, especially when we're talking micro-services, we need a sort of internal exchange&lt;br&gt;
of data, they're many tools to do so, such as Spring rest template and web client, but I'm using the one I find the simplest of them all:&lt;br&gt;
Yes, &lt;strong&gt;OpenFeign&lt;/strong&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing OpenFeign
&lt;/h2&gt;

&lt;p&gt;First, we add the OpenFeign dependency (inside the pom.xml file), so it will be imported by Maven (our dependency manager). &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-cloud-starter-openfeign&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.1.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&amp;lt;dependencyManagement&amp;gt;
        &amp;lt;dependencies&amp;gt;
            &amp;lt;dependency&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.cloud&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-cloud-dependencies&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${spring-cloud.version}&amp;lt;/version&amp;gt;
                &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
                &amp;lt;scope&amp;gt;import&amp;lt;/scope&amp;gt;
            &amp;lt;/dependency&amp;gt;
        &amp;lt;/dependencies&amp;gt;
&amp;lt;/dependencyManagement&amp;gt;


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

&lt;/div&gt;
&lt;p&gt;As you already noticed, we are using a tool which belongs to the spring cloud project, as result, we need to set the Spring cloud version we're using.&lt;br&gt;
In side the properties tag, we'll add both, java and spring cloud versions:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;properties&amp;gt;
    &amp;lt;java.version&amp;gt;1.8&amp;lt;/java.version&amp;gt;
    &amp;lt;spring-cloud.version&amp;gt;2021.0.0&amp;lt;/spring-cloud.version&amp;gt;
&amp;lt;/properties&amp;gt;


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

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Please note that I'm using Spring boot version &lt;code&gt;2.6.1&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Also note that I'll be using the &lt;a href="https://github.com/xrio/spring-boot-movies-api" rel="noopener noreferrer"&gt;movies project&lt;/a&gt; from the previous articles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After having all the needed dependencies, we still have to declare our app is using OpenFeign in a certain package.&lt;br&gt;
We decorate our main class with the &lt;code&gt;@EnableFeignClients&lt;/code&gt; with the target package which will have the feign clients.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@SpringBootApplication
@EnableFeignClients("io.xrio.movies.controller.client")
public class MoviesApplication {
  ...
}


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  OpenFeign client implementation
&lt;/h2&gt;

&lt;p&gt;In the  the implementation, I will be sending a simple get request to the jsonplaceholder API (acting as the second micro-service) to get a list of posts using OpenFeign:&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-inter-comm-arch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-inter-comm-arch.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;In order to make use the Json/POJO auto-conversion which Spring Boot offers, we'll be using a DTO to manipulate the received/sent data (posts).&lt;br&gt;&lt;br&gt;
Inside the controller &amp;gt; dto package, we create the PostDTO.java file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@Data
public class PostDTO {

    private Long id;
    private Long userId;
    private String title;
    private String body;

}


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

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note that the structure of the DTO is defined by the response of the jsonplaceholder API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, we create our post client (feign client), which is going to be like the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@FeignClient(name = "jsonplaceholder", url = "https://jsonplaceholder.typicode.com/posts")
public interface PostClient {

    @GetMapping
    List&amp;lt;PostDTO&amp;gt; getPosts();

}


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

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;@FeignClient&lt;/code&gt; will declare this interface as a feign client in order to be implemented according to our needs.&lt;br&gt;&lt;br&gt;
The name attribute mainly useless in this case since we're not addressing the api with a name, but using its url instead. The name is used when a naming registry is integrated (a future article is on the way).   &lt;/p&gt;

&lt;p&gt;And just like magic, that's all for our client!&lt;/p&gt;

&lt;p&gt;Now we need to call our client and return the response to our user. We'll create a PostController which does just that:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@RestController
@RequestMapping("post")
@AllArgsConstructor
public class PostController {

    final PostClient postClient;

    @GetMapping
    public List&amp;lt;PostDTO&amp;gt; getPosts(){
        return postClient.getPosts();
    }


}


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

&lt;/div&gt;
&lt;p&gt;Finally, that's what you will get when invoking this PostController method:&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-inter-comm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-inter-comm.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;More articles &lt;a href="https://elattar.me/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>springcloud</category>
      <category>java</category>
      <category>openfeign</category>
      <category>spring</category>
    </item>
    <item>
      <title>Spring Boot optional request params</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Sun, 05 Dec 2021 16:05:18 +0000</pubDate>
      <link>https://dev.to/daasrattale/spring-boot-optional-request-params-51k3</link>
      <guid>https://dev.to/daasrattale/spring-boot-optional-request-params-51k3</guid>
      <description>&lt;p&gt;Sometimes the job description forces us into a scenario where the request param (or query params) are not always needed or required. The obvious way to get the job done is to check simply if the param is null or not. Let's try this and another smarter way using Optionals which come with Java since its version 8.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Using required attribute
&lt;/h2&gt;

&lt;p&gt;As simple as the following, we'll set the required attribute to false and check if there's a value in the associated variable: &lt;/p&gt;

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

@GetMapping("/params")
public String getWithParam(@RequestParam(required = false) String name){
    if(name == null){
        return "Hello Anonymous";
    }
    return "Hello "+name;
}


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Method 2: Using Java 8 Optionals
&lt;/h2&gt;

&lt;p&gt;This time we'll be doing the same using Optionals:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@GetMapping("/params")
public String getWithParam(@RequestParam Optional&amp;lt;String&amp;gt; name){
    if(name.isPresent()){
        return "Hello "+name.get();
    }
    return "Hello Anonymous";
}


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

&lt;/div&gt;

&lt;p&gt;Or even in an advanced way:&lt;/p&gt;

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

@GetMapping("/params")
public String getWithParam(@RequestParam Optional&amp;lt;String&amp;gt; name){
    return  "Hello "+ name.orElse("Anonymous");
}


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

&lt;/div&gt;

&lt;p&gt;More articles &lt;a href="https://elattar.me/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>boot</category>
      <category>optional</category>
      <category>java</category>
    </item>
    <item>
      <title>Spring Boot validation and bean manipulation</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Tue, 21 Sep 2021 12:33:16 +0000</pubDate>
      <link>https://dev.to/daasrattale/spring-boot-validation-and-bean-manipulation-1leo</link>
      <guid>https://dev.to/daasrattale/spring-boot-validation-and-bean-manipulation-1leo</guid>
      <description>&lt;p&gt;Secure applications follow several security measures during their dev and prod phases, the app entry points are one of the most important parts to secure due to the risk of data injection that may occur. Spring proposes its way of data validation which improves controlling these particular points.&lt;/p&gt;

&lt;p&gt;As you've already guessed, this article is about more than just data validation; it's also about bean or custom data structure manipulation, which are two important applicative security features that every developer should be aware of.&lt;/p&gt;

&lt;p&gt;Enough introductions, for now, let's start with a global blueprint of what we need to achieve, you need to know that both mechanisms resolve two security vulnerabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Injection attacks&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database schema exposure&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds bad right? Well, the solution is actually simpler than you think. First, let's understand both problems before jumping to the solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Injection attacks
&lt;/h2&gt;

&lt;p&gt;An injection attack is when malicious code is injected into the network and retrieves all of the data from the database and sends it to the attacker.&lt;br&gt;
As you concluded the attack uses the open door of your app to gain all the stored data, and it can disguise, the attack, in many types such as &lt;strong&gt;XSS, SQL, XPath, Template, code, CRLF, LDAP, OS command injections&lt;/strong&gt;, and more.&lt;br&gt;
If you're using &lt;strong&gt;ORM operations&lt;/strong&gt; you're not totally safe, but you're one step ahead. &lt;strong&gt;The more defenses you raise the better&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Database schema exposure
&lt;/h2&gt;

&lt;p&gt;Mainly when this occurs, it doesn't come with a great benefit for the attackers, but it still delivers a piece of valuable information, which is the way you constructed your &lt;strong&gt;schemas, data types, and relations&lt;/strong&gt;, in some scenarios it becomes critical.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data validation
&lt;/h2&gt;

&lt;p&gt;During this tutorial, we will be based on our last &lt;a href="https://github.com/xrio/simple-spring-boot-movies" rel="noopener noreferrer"&gt;Movies API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, let's add the Spring boot validation dependency to our pom.xml file.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;dependency&amp;gt; 
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt; 
    &amp;lt;artifactId&amp;gt;spring-boot-starter-validation&amp;lt;/artifactId&amp;gt; 
&amp;lt;/dependency&amp;gt;


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

&lt;/div&gt;
&lt;p&gt;Second, we'll enhance our movie model with some validation rules.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// other imports
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
@Entity
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @NotNull(message = "Id must not be null")
    private Long id;

    @NotBlank(message = "Name must not be blank")
    private String name;

    @NotBlank(message = "Type must not be blank")
    private String type;

    @Min(value = 1, message = "Movies are mainly more than a minute")
    @Max(value = 300, message = "Movies are less than 5 hours")
    private Long duration;

    @NotNull(message = "Release year must not be null")
    private Long releaseYear;

}



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

&lt;/div&gt;
&lt;p&gt;Third, we alter our controller end points' signatures so they can validate incoming request bodies and throw Exception instead of custom exceptions.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

...

import javax.validation.Valid;

@RestController
@RequestMapping("movie")
@Data
public class MovieController {

    ...

    @PostMapping("/")
    public ResponseEntity&amp;lt;?&amp;gt; save(@Valid @RequestBody Movie movie) throws Exception {
        if (movie == null)
            return ResponseEntity.badRequest().body("The provided movie is not valid");
        return ResponseEntity.status(HttpStatus.CREATED).body(movieService.save(movie));
    }

    @PutMapping("/")
    public ResponseEntity&amp;lt;?&amp;gt; update(@Valid @RequestBody Movie movie) throws Exception {
        if (movie == null)
            return ResponseEntity.badRequest().body("The provided movie is not valid");
        return ResponseEntity.ok().body(movieService.update(movie));
    }

    ...

}



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

&lt;/div&gt;
&lt;p&gt;The &lt;a class="mentioned-user" href="https://dev.to/valid"&gt;@valid&lt;/a&gt; makes sure that the incoming body is valid, otherwise a MethodArgumentNotValidException will be thrown&lt;/p&gt;

&lt;p&gt;Obviously, we removed the custom-made exception and replaced it with the Exception class so the controller won't suppress the exception in the controller layer and let the default exception handler interfere, which will cause a 500 server internal error. Instead, it will be handled by the exception handler we’re about to make.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

package io.xrio.movies.controller.advice;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity&amp;lt;?&amp;gt; handleValidationExceptions(MethodArgumentNotValidException exception) {
        Map&amp;lt;String, String&amp;gt; errors = new HashMap&amp;lt;&amp;gt;();
        exception.getBindingResult().getAllErrors().forEach((error) -&amp;gt; {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        return ResponseEntity.badRequest().body(errors);
    }
}



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

&lt;/div&gt;
&lt;p&gt;Just like our previous Movie exception handler, this ControllerAdvice based handler will target the MethodArgumentNotValidException type exceptions and resolve them by retrieving the validation violation, wrap it in a response entity and send it back to the user with 400 bad request response code.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-validation-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-validation-1.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: Returning the validation violations to the user is a huge blender, it's like telling a house robber why they failed to rob your own house.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To counter this, we'll print them on the logs, which are by the way are accessible only to the prod env admins. Our Exception will be like this:&lt;/p&gt;

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

import lombok.extern.slf4j.Slf4j;

...

@ControllerAdvice
@Slf4j
public class ValidationExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity&amp;lt;?&amp;gt; handleValidationExceptions(MethodArgumentNotValidException exception) {
        exception.getBindingResult().getAllErrors().forEach((error) -&amp;gt; {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            log.error(fieldName + ": " + errorMessage);
        });
        return ResponseEntity.badRequest().body("Sorry, that movie you sent sucks :)");
    }
}



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

&lt;/div&gt;

&lt;p&gt;Sending the same request will result this:&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-validation-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-validation-2.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;And only prod env admins can see this:&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-validation-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-validation-3.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The @Slf4j is a short way using &lt;a href="https://projectlombok.org/" rel="noopener noreferrer"&gt;Lombok&lt;/a&gt; to call the logger.&lt;/p&gt;

&lt;p&gt;Data validation not only is a layer to counter injection attacks, but it helps keep your data nice and clean.&lt;/p&gt;

&lt;p&gt;Since we still exposing our model in our end-points, it's time to change that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Data manipulation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introduction to the DTOs
&lt;/h3&gt;

&lt;p&gt;The data transfer objects, also known as Value Objects (VOs),  will be the ones carrying data between two processes, in our case, it will be their structure that will be exposed instead of the model's.&lt;/p&gt;

&lt;p&gt;Our MovieDTO will be like the following:&lt;/p&gt;

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

import lombok.Data;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class MovieDTO {

    @NotNull(message = "Id must not be null")
    private Long id;

    @NotBlank(message = "Name must not be blank")
    private String name;
    @NotBlank(message = "Type must not be blank")
    private String type;
    @Min(value = 1, message = "Movies are mainly more than a minute")
    @Max(value = 300, message = "Movies are less than 5 hours")
    private Long duration;
    @NotNull(message = "Release year must not be null")
    private Long releaseYear;

}



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

&lt;/div&gt;

&lt;p&gt;Since the DTOs are the ones to be exposed, we added some validation rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Okay, we have the DTOs exposed, but how are we going to persist data using DTOs?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The answer is that DTOs only exist in the controller layer, in other words, we can't use them on the service and repository layers.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also means our need for a &lt;strong&gt;conversion mechanism&lt;/strong&gt;, yes, we need a MovieConverter.&lt;/p&gt;

&lt;p&gt;Let's start with the integration of the &lt;a href="http://modelmapper.org/getting-started/" rel="noopener noreferrer"&gt;ModelMapper&lt;/a&gt; dependency which will help convert models and DTO in both ways:&lt;/p&gt;

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

&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.modelmapper&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;modelmapper&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.3.5&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;Then, we add its basic configuration so it will treated as Spring Bean:&lt;/p&gt;

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


import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ModelMapperConfig {

    @Bean
    public ModelMapper modelMapper() {
        return new ModelMapper();
    }
}



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

&lt;/div&gt;

&lt;p&gt;I don't like repeating myself (&lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;DRY priciple&lt;/a&gt;) that's why I always put redundant behavior into generic classes, the AbstractConverter will do that for us:&lt;/p&gt;

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


import java.util.ArrayList;
import java.util.List;

public abstract class AbstractConverter &amp;lt;DM, DTO&amp;gt; {

    public abstract DM convertToDM(DTO dto);

    public abstract DTO convertToDTO(DM dm);

    public List&amp;lt;DM&amp;gt; convertToDMs(List&amp;lt;DTO&amp;gt; dtos) {
        List&amp;lt;DM&amp;gt; dms = new ArrayList&amp;lt;&amp;gt;();
        for (DTO dto : dtos) dms.add(convertToDM(dto));
        return dms;
    }

    public List&amp;lt;DTO&amp;gt; convertToDTOs(List&amp;lt;DM&amp;gt; dms) {
        List&amp;lt;DTO&amp;gt; dtos = new ArrayList&amp;lt;&amp;gt;();
        for (DM dm : dms) dtos.add(convertToDTO(dm));
        return dtos;
    }

}



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

&lt;/div&gt;

&lt;p&gt;Our MovieConverter will inherit from the AbstractConverter with the movie model and DTO as class params.&lt;/p&gt;

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

import io.xrio.movies.dto.MovieDTO;
import io.xrio.movies.model.Movie;
import org.modelmapper.ModelMapper;
import org.modelmapper.config.Configuration;
import org.springframework.stereotype.Component;

@Component
public class MovieConverter extends AbstractConverter&amp;lt;Movie, MovieDTO&amp;gt; {

    private final ModelMapper modelMapper;

    public MovieConverter(ModelMapper modelMapper) {
        modelMapper.getConfiguration()
                .setFieldMatchingEnabled(true)
                .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);
        this.modelMapper = modelMapper;
    }

    @Override
    public Movie convertToDM(MovieDTO movieDTO) {
        return modelMapper.map(movieDTO, Movie.class);
    }

    @Override
    public MovieDTO convertToDTO(Movie movie) {
        return modelMapper.map(movie, MovieDTO.class);
    }
}


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

&lt;/div&gt;

&lt;p&gt;I decorated the MovieConverter with the @Component annotation so it can be injected into the MovieController later.&lt;/p&gt;

&lt;p&gt;The model mapper will be configured in the MovieConverter constructors with a simple configuration, and with the model and DTO having the same fields, the mapping will be possible for now.&lt;/p&gt;

&lt;p&gt;Before testing our converter, we need to inject it into the controller, then alter the endpoints so they can handle the DTOs now instead.&lt;/p&gt;

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

package io.xrio.movies.controller;

import io.xrio.movies.converter.MovieConverter;
import io.xrio.movies.dto.MovieDTO;
import io.xrio.movies.service.MovieService;
import lombok.Data;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

@RestController
@RequestMapping("movie")
@Data
public class MovieController {

    final MovieService movieService;
    final MovieConverter movieConverter;

    @PostMapping("/")
    public ResponseEntity&amp;lt;?&amp;gt; save(@Valid @RequestBody MovieDTO movieDTO) throws Exception {
        if (movieDTO == null)
            return ResponseEntity.badRequest().body("The provided movie is not valid");
        return ResponseEntity
                .status(HttpStatus.CREATED)
                .body(movieConverter.convertToDTO(movieService.save(movieConverter.convertToDM(movieDTO))));
    }

    @PutMapping("/")
    public ResponseEntity&amp;lt;?&amp;gt; update(@Valid @RequestBody MovieDTO movieDTO) throws Exception {
        if (movieDTO == null)
            return ResponseEntity.badRequest().body("The provided movie is not valid");
        return ResponseEntity
                .ok()
                .body(movieConverter.convertToDTO(movieService.update(movieConverter.convertToDM(movieDTO))));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity&amp;lt;?&amp;gt; delete(@PathVariable Long id) throws Exception {
        if (id == null)
            return ResponseEntity.badRequest().body("The provided movie's id is not valid");
        return ResponseEntity.ok().body("Movie [" + movieService.delete(id) + "] deleted successfully.");
    }

    @GetMapping("/")
    public ResponseEntity&amp;lt;List&amp;lt;MovieDTO&amp;gt;&amp;gt; findAll() {
        return ResponseEntity.ok().body(movieConverter.convertToDTOs(movieService.findAll()));
    }

}



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

&lt;/div&gt;

&lt;p&gt;Then we test it!&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-conversion-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-conversion-1.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Great! But it looks the same as before with more code!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;True, so let's play the same game with different rules, the movie model for us now will be different than the DTO in order to protect our API against the database schema exposure:&lt;/p&gt;

&lt;p&gt;Some of the movie model fields will be put in an info class that will be embedded in the movie, that way we will change the structure and keep things simple for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: I removed the model validation because it's no longer used or needed.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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


import lombok.Data;

import javax.persistence.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

@Data
@Entity
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @Embedded
    private Info info;

}



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

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

import javax.persistence.Embeddable;

@Embeddable
public class Info {

    private String name;
    private String type;
    private Long duration;
    private Long releaseYear;

}



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

&lt;/div&gt;

&lt;p&gt;We need also to alter our DTO's fields' names so we don't need to add an advanced configuration for the model mapper.&lt;/p&gt;

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


import lombok.Data;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class MovieDTO {

    @NotNull(message = "Id must not be null")
    private Long id;

    @NotBlank(message = "Name must not be blank")
    private String infoName;
    @NotBlank(message = "Type must not be blank")
    private String infoType;
    @Min(value = 1, message = "Movies are mainly more than a minute")
    @Max(value = 300, message = "Movies are less than 5 hours")
    private Long infoDuration;
    @NotNull(message = "Release year must not be null")
    private Long infoReleaseYear;

}



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

&lt;/div&gt;

&lt;p&gt;And finally testing it.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-conversion-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovie-conversion-2.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Finnally
&lt;/h2&gt;

&lt;p&gt;Data validation and data manipulation can be a greatly valued asset to your API dev and prod, not only enhancing security but also gives you the power to keep your data in shape and to adapt to the users’ requirements without changing your own. &lt;/p&gt;

&lt;p&gt;Find the source code &lt;a href="https://github.com/xrio/simple-spring-boot-movies" rel="noopener noreferrer"&gt;Here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;More articles &lt;a href="https://elattar.me/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>springframework</category>
      <category>java</category>
      <category>jee</category>
    </item>
    <item>
      <title>Getting started with Spring Boot: Creating a simple movies list API.</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Tue, 21 Sep 2021 12:15:47 +0000</pubDate>
      <link>https://dev.to/daasrattale/getting-started-with-spring-boot-creating-a-simple-movies-list-api-41l6</link>
      <guid>https://dev.to/daasrattale/getting-started-with-spring-boot-creating-a-simple-movies-list-api-41l6</guid>
      <description>&lt;p&gt;Spring boot is widely considered an entry to the Spring ecosystem, simple yet effective and powerful! Spring boot makes it possible to create Spring-based stand-alone, quality production apps with minimum needed configuration specifications. Let's keep it simple, just like the movies list API we're about to create!&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we start
&lt;/h2&gt;

&lt;p&gt;Your project structure matters, Spring boot gives you all the freedom to structure your project the way you see fit, you may want to use that wisely.&lt;/p&gt;

&lt;p&gt;There's not a particular structure you need to follow, I'll be introducing mine on this project but that doesn't mean you have to follow it the way it is, as I said you're free!&lt;/p&gt;

&lt;p&gt;Most tech companies, including mine, use guiding dev rules to keep the code clean and pretty, the rules are there to help you, don't go rogue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 0 : Introduction to the global architecture
&lt;/h2&gt;

&lt;p&gt;Before we get busy with the layers specifications, let's have a bird's-eye view :&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-init-movies-arch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fspring-init-movies-arch.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase I : Model definition
&lt;/h2&gt;

&lt;p&gt;Models are the data structure which you're project is dealing with (example: you're building a user management system, the user is your model among others).&lt;/p&gt;

&lt;p&gt;Usually, the software architect will be there to provide you with the needed resources to build your Spring boot models, those resources mainly are UML class diagrams. Here's ours :&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovies-model.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Felattar.me%2Fimages%2Fspring%2Fmovies-model.png" width="800" height="400"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: I decided for this model layer to be as simple as possible, to not give a wall to climb instead of a first step. In real-life projects, things get ugly and much more complicated.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase II : Service definition
&lt;/h2&gt;

&lt;p&gt;After the model layer, now it's time to blueprint our services' structure, in other words, we need to define what service our API is going to mainly provide.&lt;/p&gt;

&lt;p&gt;The services usually are fully invocated by the controller layer which means they usually have the same structure, but not all the time.&lt;/p&gt;

&lt;p&gt;This one also will be provided by the software architect, and it comes as a detailed list with descriptions, a set of UML sequence diagrams, or both.&lt;/p&gt;

&lt;p&gt;We need our API to be able to provide us with a list of saved movies, save, update and delete a movie.&lt;/p&gt;

&lt;p&gt;Our end-points will be the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Save EP&lt;/strong&gt;: This allows &lt;strong&gt;saving&lt;/strong&gt; a movie by sending a JSON object using an &lt;strong&gt;HTTP/POST&lt;/strong&gt; request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update EP&lt;/strong&gt;: This allows &lt;strong&gt;updating&lt;/strong&gt; a movie by sending a JSON object using an &lt;strong&gt;HTTP/PUT&lt;/strong&gt; request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete EP&lt;/strong&gt;: This allows &lt;strong&gt;deleting&lt;/strong&gt; a movie by sending its id using an &lt;strong&gt;HTTP/DELETE&lt;/strong&gt; request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find all EP&lt;/strong&gt;: This allows &lt;strong&gt;retrieving&lt;/strong&gt; all the existing movies by sending an &lt;strong&gt;HTTP/GET&lt;/strong&gt; request. (It's not recommended to open a find all end-point because it will slow down your application, instead set a limit, Example: 10 movies per request).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why are we using multiple HTTP verbs?
&lt;/h3&gt;

&lt;p&gt;If I were in your shoes right now, I'd be asking the same question. First, you can use it as you want with no restrictions, use an HTTP/POST request to retrieve movies, yes you can do that but, there's a reason why we don’t.&lt;/p&gt;

&lt;p&gt;Dev rules and conventions are there to help you and keep things in order, otherwise, all we'll be building is chaos!&lt;/p&gt;

&lt;p&gt;HTTP verbs are meant to describe the purpose of the request:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;HTTP Verb&lt;/th&gt;
        &lt;th&gt;CRUD Op&lt;/th&gt;
        &lt;th&gt;Purpose&lt;/th&gt;
        &lt;th&gt;On success&lt;/th&gt;
        &lt;th&gt;On failure&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;POST&lt;/td&gt;
        &lt;td&gt;Create&lt;/td&gt;
        &lt;td&gt;Creates a resource&lt;/td&gt;
        &lt;td&gt;201&lt;/td&gt;
        &lt;td&gt;404 | 409&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;GET&lt;/td&gt;
        &lt;td&gt;Read&lt;/td&gt;
        &lt;td&gt;Retrieves a resource&lt;/td&gt;
        &lt;td&gt;200&lt;/td&gt;
        &lt;td&gt;404&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;PUT&lt;/td&gt;
        &lt;td&gt;Update&lt;/td&gt;
        &lt;td&gt;Updates (replaces) a resource&lt;/td&gt;
        &lt;td&gt;200 | 204&lt;/td&gt;
        &lt;td&gt;404 | 405&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;PATCH&lt;/td&gt;
        &lt;td&gt;Update&lt;/td&gt;
        &lt;td&gt;Updates (modifies) a resource&lt;/td&gt;
        &lt;td&gt;200 | 204&lt;/td&gt;
        &lt;td&gt;404 | 405&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;DELETE&lt;/td&gt;
        &lt;td&gt;Delete&lt;/td&gt;
        &lt;td&gt;Deletes a resource&lt;/td&gt;
        &lt;td&gt;200&lt;/td&gt;
        &lt;td&gt;404 | 405&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each request requires a response, in both success and error scenarios, HTTP response codes are there to define what type  of response we are getting.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;HTTP response code&lt;/th&gt;
        &lt;th&gt;Meaning&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;100 - 199&lt;/td&gt;
        &lt;td&gt;Informational responses&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;200 - 299&lt;/td&gt;
        &lt;td&gt;Successful responses&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;300 - 399&lt;/td&gt;
        &lt;td&gt;Redirection responses&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;400 - 499&lt;/td&gt;
        &lt;td&gt;Client error responses&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;500 - 599&lt;/td&gt;
        &lt;td&gt;Server error responses&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Know more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" rel="noopener noreferrer"&gt;HTTP response codes here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase III: Technical benchmarking
&lt;/h2&gt;

&lt;p&gt;Now, we need to define the project technical requirements, what communication protocol we should use, what Database is suitable to store data, etc.&lt;/p&gt;

&lt;p&gt;We will be using REST as our main communication protocol, H2/file database to store our data.&lt;br&gt;
I chose those technologies for instructional purposes so that I could offer a simple yet working example, but in real-life projects, we select technologies only on the basis of their utility and ability to aid in the development of our API. That was the second factor that influenced my decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE: The more technology experience you have, the more accurate your decisions will be.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Phase IV: Development
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Github repository initialization
&lt;/h3&gt;

&lt;p&gt;To make this code accessible for all of you, and insure its version, we'll be using git and GitHub, find all the code here : &lt;a href="https://github.com/xrio/simple-spring-boot-movies.git" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Spring Initializr
&lt;/h3&gt;

&lt;p&gt;Spring provides us with an &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Initialization suite&lt;/a&gt; that helps us start our project quicker than usual.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="/images/spring/spring-init-movies.png" class="article-body-image-wrapper"&gt;&lt;img src="/images/spring/spring-init-movies.png"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;After the init and downloading the basic version of our project, there're three important files you need to know about :&lt;/p&gt;

&lt;h4&gt;
  
  
  1. The application main class (aka. the backbone)
&lt;/h4&gt;

&lt;p&gt;This class is the main class of the project and it represents its center.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;NOTE: All packages should be under the main package of your application so they can be bootstrapped.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package io.xrio.movies;

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

@SpringBootApplication
public class 
MoviesApplication {

    public static void main(String[] args) {
        SpringApplication.run(MoviesApplication.class, args);
    }

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. The application properties file
&lt;/h4&gt;

&lt;p&gt;This file is a way to put your configuration values which the app will use during the execution (example: URL to the database, server's port, etc.).&lt;br&gt;
&lt;strong&gt;&lt;em&gt;NOTE: You can add more properties files, I'll be covering that up in an upcoming article.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;NOTE1: By default the file is empty.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.datasource.url=jdbc:h2:file:./data/moviesDB
spring.jpa.defer-datasource-initialization=true
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. The pom file
&lt;/h4&gt;

&lt;p&gt;Since we are using Maven as our dependency manager (you can use Gradle instead) we have a pom.xml file containing all the data about our dependencies.&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;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
    &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.5.4&amp;lt;/version&amp;gt;
        &amp;lt;relativePath/&amp;gt; &amp;lt;!-- lookup parent from repository --&amp;gt;
    &amp;lt;/parent&amp;gt;
    &amp;lt;groupId&amp;gt;io.xrio&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;movies&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;name&amp;gt;movies&amp;lt;/name&amp;gt;
    &amp;lt;description&amp;gt;Just a simple movies api&amp;lt;/description&amp;gt;
    &amp;lt;properties&amp;gt;
        &amp;lt;java.version&amp;gt;1.8&amp;lt;/java.version&amp;gt;
    &amp;lt;/properties&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-data-jpa&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.h2database&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;h2&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
            &amp;lt;optional&amp;gt;true&amp;lt;/optional&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;excludes&amp;gt;
                        &amp;lt;exclude&amp;gt;
                            &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
                            &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
                        &amp;lt;/exclude&amp;gt;
                    &amp;lt;/excludes&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;

&amp;lt;/project&amp;gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Building the model layer
&lt;/h3&gt;

&lt;p&gt;The model layer is the direct implementation of our class diagrams as Java classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package io.xrio.movies.model;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Date;

@Data
@Entity
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private String name;
    private String type;
    private Long duration;
    private Long releaseYear;

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

&lt;/div&gt;



&lt;p&gt;The&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 provides us with embedded constructors and accessors so we can reduce the written code. see more about the [Lombok project](https://projectlombok.org/).

The

 ```@Entity```

 is there to tell Spring Data that particular class should be represented as a table in our relational database. we call that process an ORM (Object Relational Mapping).

So that our id won’t be duplicated, we will use a sequence, we put the

 ```@GeneratedValue(strategy = GenerationType.SEQUENCE)```

 there.

### Building the repository facade
Simply, an interface that will inherit Spring Data JPA powers and handle the CRUD ORM operations on our behalf.



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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.repository;&lt;/p&gt;

&lt;p&gt;import io.xrio.movies.model.Movie;&lt;br&gt;
import org.springframework.data.jpa.repository.JpaRepository;&lt;br&gt;
import org.springframework.stereotype.Repository;&lt;/p&gt;

&lt;p&gt;@Repository&lt;br&gt;
public interface MoviesRepository extends JpaRepository {&lt;br&gt;
}&lt;/p&gt;

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


@Repository ensures the dependency injection of the repository bean among other things, since the interface inherits from the generic JpaRepository, it will have all the already-set mechanisms of Spring Data JPA.

Spring Data is smart enough at the level it can handle a new operation only from the function signature. Example: You need to file a movie by its title? No problem, just add this function to your interface :



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

&lt;/div&gt;

&lt;p&gt;Movie findByName(String name);&lt;/p&gt;

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


### Building the custom exception

Before building our service layer, we need a couple of custom exceptions that will be thrown when things go south.

Basing on our service schema only two exceptions can be thrown when:
- Creating an already existing movie (MovieDuplicatedException class).



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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.exception;&lt;/p&gt;

&lt;p&gt;import lombok.Data;&lt;br&gt;
import lombok.EqualsAndHashCode;&lt;/p&gt;

&lt;p&gt;/**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@author : Elattar Saad&lt;/li&gt;
&lt;li&gt;
&lt;a class="mentioned-user" href="https://dev.to/version"&gt;@version&lt;/a&gt; 1.0&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/since"&gt;@since&lt;/a&gt; 10/9/2021&lt;br&gt;
*/&lt;br&gt;
@EqualsAndHashCode(callSuper = true)&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/data"&gt;@data&lt;/a&gt;&lt;br&gt;
@AllArgsConstructor&lt;br&gt;
public class MovieDuplicatedException extends Exception{&lt;/p&gt;

&lt;p&gt;/**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The duplicated movie's id
*/
private Long mid;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;}&lt;/p&gt;

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


- Updating a non-existing movie (MovieNotFoundException class).



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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.exception;&lt;/p&gt;

&lt;p&gt;import lombok.Data;&lt;br&gt;
import lombok.EqualsAndHashCode;&lt;/p&gt;

&lt;p&gt;@EqualsAndHashCode(callSuper = true)&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/data"&gt;@data&lt;/a&gt;&lt;br&gt;
@AllArgsConstructor&lt;br&gt;
public class MovieNotFoundException extends Exception{&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * The nonexistent movie's id
 */
private Long mid;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

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

***NOTE: There're mainly four ways to handle exception in Spring boot.***

***NOTE1: You can generalize custom exceptions so they can be used for more than one model.***

***NOTE2: You can handle your exceptions without custom-made exceptions and handlers.***


### Building the service layer
First, we will create a movie service interface that will bear the schema of our service, then implement it with the needed logic. This helps us to achieve the [purpose of the IoC](https://en.wikipedia.org/wiki/Inversion_of_control).



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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.service;&lt;/p&gt;

&lt;p&gt;import io.xrio.movies.exception.MovieDuplicatedException;&lt;br&gt;
import io.xrio.movies.exception.MovieNotFoundException;&lt;br&gt;
import io.xrio.movies.model.Movie;&lt;/p&gt;

&lt;p&gt;import java.util.List;&lt;/p&gt;

&lt;p&gt;public interface MovieService {&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Movie save(Movie movie) throws MovieDuplicatedException;
Movie update(Movie movie) throws MovieNotFoundException;
Long delete(Long id) throws MovieNotFoundException;
List&amp;lt;Movie&amp;gt; findAll();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

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




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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.service.impl;&lt;/p&gt;

&lt;p&gt;import io.xrio.movies.exception.MovieDuplicatedException;&lt;br&gt;
import io.xrio.movies.exception.MovieNotFoundException;&lt;br&gt;
import io.xrio.movies.model.Movie;&lt;br&gt;
import io.xrio.movies.repository.MoviesRepository;&lt;br&gt;
import io.xrio.movies.service.MoviesService;&lt;br&gt;
import lombok.Data;&lt;br&gt;
import org.springframework.stereotype.Service;&lt;/p&gt;

&lt;p&gt;import java.util.List;&lt;/p&gt;

&lt;p&gt;@Service&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/data"&gt;@data&lt;/a&gt;&lt;br&gt;
public class MovieServiceImpl implements MovieService {&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final MovieRepository movieRepository;

@Override
public Movie save(Movie movie) throws MovieDuplicatedException {
    Movie movieFromDB = movieRepository.findById(movie.getId()).orElse(null);
    if (movieFromDB != null)
        throw new MovieDuplicatedException(movie.getId());
    return movieRepository.save(movie);
}

@Override
public Movie update(Movie movie) throws MovieNotFoundException {
    Movie movieFromDB = movieRepository.findById(movie.getId()).orElse(null);
    if (movieFromDB == null)
        throw new MovieNotFoundException(movie.getId());
    movie.setId(movieFromDB.getId());
    return movieRepository.save(movie);
}

@Override
public Long delete(Long id) throws MovieNotFoundException {
    Movie movieFromDB = movieRepository.findById(id).orElse(null);
    if (movieFromDB == null)
        throw new MovieNotFoundException(id);
    movieRepository.delete(movieFromDB);
    return id;
}

@Override
public List&amp;lt;Movie&amp;gt; findAll() {
    return movieRepository.findAll();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

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


I combined the use of constructor dependency injection and Lombok’s

 ```@RequiredArgsConstructor```

 to reduce my code, without that it will look like this :



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

&lt;/div&gt;

&lt;p&gt;@Service&lt;br&gt;
public class MovieServiceImpl implements MovieService {&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final MovieRepository movieRepository;

public MovieServiceImpl(MovieRepository movieRepository) {
    this.movieRepository = movieRepository;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;...&lt;br&gt;
}&lt;/p&gt;

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


### Building the controller layer

After the service layer, time to build our controller to accept incoming requests.

As previously said, the controller layer directly calls the service layer, that's the reason behind the injection of a MovieService bean inside the movie controller.



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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.controller;&lt;/p&gt;

&lt;p&gt;import io.xrio.movies.exception.MovieDuplicatedException;&lt;br&gt;
import io.xrio.movies.exception.MovieNotFoundException;&lt;br&gt;
import io.xrio.movies.model.Movie;&lt;br&gt;
import io.xrio.movies.service.MovieService;&lt;br&gt;
import lombok.Data;&lt;br&gt;
import org.springframework.http.ResponseEntity;&lt;br&gt;
import org.springframework.web.bind.annotation.*;&lt;/p&gt;

&lt;p&gt;@RestController&lt;br&gt;
@RequestMapping("movie")&lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/data"&gt;@data&lt;/a&gt;&lt;br&gt;
public class MovieController {&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final MovieService movieService;

@PostMapping("/")
public ResponseEntity&amp;lt;?&amp;gt; save(@RequestBody Movie movie) throws MovieDuplicatedException {
    if (movie == null)
        return ResponseEntity.badRequest().body("The provided movie is not valid");
    return ResponseEntity.status(HttpStatus.CREATED).body(movieService.save(movie));
}

@PutMapping("/")
public ResponseEntity&amp;lt;?&amp;gt; update(@RequestBody Movie movie) throws MovieNotFoundException {
    if (movie == null)
        return ResponseEntity.badRequest().body("The provided movie is not valid");
    return ResponseEntity.ok().body(movieService.update(movie));
}

@DeleteMapping("/{id}")
public ResponseEntity&amp;lt;?&amp;gt; delete(@PathVariable Long id) throws MovieNotFoundException {
    if (id == null)
        return ResponseEntity.badRequest().body("The provided movie's id is not valid");
    return ResponseEntity.ok().body("Movie [" + movieService.delete(id) + "] deleted successfully.");
}

@GetMapping("/")
public ResponseEntity&amp;lt;?&amp;gt; findAll() {
    return ResponseEntity.ok().body(movieService.findAll());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

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


One more last step and we're good to go. To handle the exception thrown from the service layer, we need to catch it in the controller layer.

Fortunately, Spring boot provides us with an Exception Handler that can resolve exceptions under the hood and without any code to the controller.



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

&lt;/div&gt;

&lt;p&gt;package io.xrio.movies.controller.advice;&lt;/p&gt;

&lt;p&gt;import io.xrio.movies.exception.MovieDuplicatedException;&lt;br&gt;
import io.xrio.movies.exception.MovieNotFoundException;&lt;br&gt;
import org.springframework.http.HttpStatus;&lt;br&gt;
import org.springframework.http.ResponseEntity;&lt;br&gt;
import org.springframework.web.bind.annotation.ControllerAdvice;&lt;br&gt;
import org.springframework.web.bind.annotation.ExceptionHandler;&lt;br&gt;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;&lt;/p&gt;

&lt;p&gt;@ControllerAdvice&lt;br&gt;
public class MovieControllerExceptionHandler {&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ExceptionHandler(MovieNotFoundException.class)
private ResponseEntity&amp;lt;?&amp;gt; handleMovieNotFoundException(MovieNotFoundException exception){
    String responseMessage = "The provided movie ["+exception.getMid()+"] is nowhere to be found.";
    return ResponseEntity
            .status(HttpStatus.NOT_FOUND)
            .body(responseMessage);
}

@ExceptionHandler(MovieDuplicatedException.class)
private ResponseEntity&amp;lt;?&amp;gt; handleMovieDuplicatedException(MovieDuplicatedException exception){
    String responseMessage = "The provided movie ["+exception.getMid()+"] is already existing.";
    return ResponseEntity
            .status(HttpStatus.CONFLICT)
            .body(responseMessage);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

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


All we need to do next is to test what we build via a rest client, for this reason, I'm using [Insomnia](https://insomnia.rest/) :

##### The post end-point

&amp;lt;p align="center"&amp;gt;
  &amp;lt;img src="https://elattar.me/images/spring/movie-test-post.png"&amp;gt;
&amp;lt;/p&amp;gt;

##### The get end-point

&amp;lt;p align="center"&amp;gt;
  &amp;lt;img src="https://elattar.me/images/spring/movie-test-get.png"&amp;gt;
&amp;lt;/p&amp;gt;

##### The put end-point

&amp;lt;p align="center"&amp;gt;
  &amp;lt;img src="https://elattar.me/images/spring/movie-test-put.png"&amp;gt;
&amp;lt;/p&amp;gt;

##### The delete end-point

&amp;lt;p align="center"&amp;gt;
  &amp;lt;img src="https://elattar.me/images/spring/movie-test-delete.png"&amp;gt;
&amp;lt;/p&amp;gt;

And finally, testing the error scenario for some end-points.

Let's try and save a movie with an existing id :
&amp;lt;p align="center"&amp;gt;
  &amp;lt;img src="https://elattar.me/images/spring/movie-test-save-error.png"&amp;gt;
&amp;lt;/p&amp;gt;

Or delete a non-existing movie :
&amp;lt;p align="center"&amp;gt;
  &amp;lt;img src="https://elattar.me/images/spring/movie-test-delete-error.png"&amp;gt;
&amp;lt;/p&amp;gt;

## Summary 

Spring Boot is a powerful apps making tool, takes away all the times consuming tasks and leaves you with the logical ones to handle.
Don't get fouled, building APIs is not that easy, and from what I saw, that's just the tip of the Iceberg!

Find the source code [Here](https://github.com/xrio/simple-spring-boot-movies). 

More articles [Here](https://elattar.me/).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>Starting with Spring Framework? Here's what you need to know</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Tue, 21 Sep 2021 12:04:36 +0000</pubDate>
      <link>https://dev.to/daasrattale/starting-with-spring-framework-here-s-what-you-need-to-know-md6</link>
      <guid>https://dev.to/daasrattale/starting-with-spring-framework-here-s-what-you-need-to-know-md6</guid>
      <description>&lt;p&gt;Spring is a common term in the dev community, as a beginner, its wideness may overwhelm you on the first step you take towards it. I'm here to make it simpler.&lt;/p&gt;

&lt;p&gt;The Spring Framework is a Java platform application framework and inversion of the control (IoC) container. Any Java program may utilize the framework's fundamental capabilities, however, there are extensions for creating web apps on top of the Java EE platform. &lt;a href="https://en.wikipedia.org/wiki/Spring_Framework" rel="noopener noreferrer"&gt;Spring Framework - Wikipedia&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why using Spring?
&lt;/h2&gt;

&lt;p&gt;Over the years Spring Framework has proven itself to be :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Everywhere&lt;/strong&gt;: Developers all across the world rely on Spring's adaptable libraries. Every day, millions of end-users enjoy pleasant experiences from Spring, whether it's streaming TV, online shopping, or a variety of other creative solutions. All of the major tech companies, including Alibaba, Amazon, Google, Microsoft, and others, have contributed to Spring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible&lt;/strong&gt;: Spring's extensible and extensive collection of extensions and third-party libraries enable developers to create nearly any application they can imagine. The Inversion of Control (IoC) and Dependency Injection (DI) capabilities of Spring Framework offers the foundation for a diverse collection of features and functionality. Spring offers the tools to let you develop secure, reactive, cloud-based microservices for the web or complicated streaming data flows for the enterprise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Productive&lt;/strong&gt;: Spring Boot revolutionizes the way you approach Java programming jobs, greatly simplifying your workflow. Spring Boot makes microservice development a breeze by combining essentials like an application environment and an auto-configured, embedded web server. You can move even quicker by combining Spring Boot with Spring Cloud's extensive collection of supporting libraries, servers, patterns, and templates to quickly deploy complete microservices-based architectures to the cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast&lt;/strong&gt;: By default, Spring provides quick startup, fast shutdown, and efficient execution. For even more efficiency, Spring projects are increasingly using the reactive (nonblocking) programming style. Spring's superpower is developer productivity. Spring Boot makes it easier for developers to create apps with considerably less effort than alternative paradigms. Embedded web servers, auto-configuration, and "fat jars" make it easy to get started, and innovations like Spring DevTools' LiveReload allow developers to iterate quicker than ever before. With the Spring Initializr at start.spring.io, you can even start a new Spring project in seconds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secure&lt;/strong&gt;: Spring has a track record of promptly and properly dealing with security concerns. Spring committers collaborate with security experts to fix and test any identified flaws. Third-party dependencies are also constantly checked, and updates are released on a regular basis to make your data and apps as secure as possible. Spring Security also makes it easy to connect with industry-standard security schemes and offers trustworthy, secure-by-default solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supportive&lt;/strong&gt;: Spring's community is vast, international, and varied, encompassing people of all ages and skills, from total beginners to seasoned veterans. You can discover the assistance and resources you need to advance to the next level, no matter where you are on your journey: quickstarts, guides &amp;amp; tutorials, videos, meetings, support, or even formal training and certification.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What can you do using Spring?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Microservices &lt;a href="https://spring.io/microservices" rel="noopener noreferrer"&gt;Spring | Microservices&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Reactive systems &lt;a href="https://spring.io/reactive" rel="noopener noreferrer"&gt;Spring | Reactive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Cloud distributed structures &lt;a href="https://spring.io/cloud" rel="noopener noreferrer"&gt;Spring | Cloud&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Web applications &lt;a href="https://spring.io/web-applications" rel="noopener noreferrer"&gt;Spring | Web Apps&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Serverless Applications and Function as a Service (FaaS) &lt;a href="https://spring.io/serverless" rel="noopener noreferrer"&gt;Spring | Serverless&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Event-driven Systems &lt;a href="https://spring.io/event-driven" rel="noopener noreferrer"&gt;Spring | Event Driven&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Batches and automated tasks. &lt;a href="https://spring.io/batch" rel="noopener noreferrer"&gt;Spring | Batch&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What requirements I need to have before getting started with Spring.
&lt;/h3&gt;

&lt;p&gt;Generally speaking, you need to have a good knowledge of &lt;strong&gt;Java core&lt;/strong&gt;, a basic understanding of &lt;strong&gt;data structures&lt;/strong&gt;, &lt;strong&gt;OOP&lt;/strong&gt;, &lt;strong&gt;IoC&lt;/strong&gt;, and &lt;strong&gt;dependency injection&lt;/strong&gt;.&lt;br&gt;
But, you also need to know the basics of the framework you intend to use inside the Spring ecosystem, for example, if you are using &lt;strong&gt;Spring Data JPA&lt;/strong&gt; I believe you must know how &lt;strong&gt;JPA&lt;/strong&gt; works in the first place.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don't make the beginners' mistake, you don't have to know all about Spring before starting, it always comes piece by piece.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Where to start?
&lt;/h3&gt;

&lt;p&gt;As previously said, Spring is a whole ecosystem, it is highly recommended to enter it via the Spring Boot door, to do so I suggest this official article: ​​&lt;a href="https://spring.io/quickstart" rel="noopener noreferrer"&gt;Spring | Spring Quickstart Guide&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You can check my new article on Spring Boot &lt;a href="http://elattar.me/posts/getting-started-with-spring-boot-creating-a-simple-movies-list-api/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  More resources
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Learning sites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://spring.io/learn" rel="noopener noreferrer"&gt;&lt;strong&gt;Spring learn&lt;/strong&gt;&lt;/a&gt;: The official learning site and also my first direction when I need to look for something concerning Spring.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.baeldung.com/learn-spring-course" rel="noopener noreferrer"&gt;&lt;strong&gt;Baeldung&lt;/strong&gt;&lt;/a&gt;: A powerful site that provides devs with a set of informative guides with practical examples following the best practices.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dzone.com/articles/introducing-spring-boot" rel="noopener noreferrer"&gt;&lt;strong&gt;DZone&lt;/strong&gt;&lt;/a&gt;: DZone provides the information, resources, and tactics that IT professionals require. construct the future Are you a non-member? DZone.com is a prominent provider of information resources for software professionals and one of the world's largest online communities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Youtube Channels
&lt;/h4&gt;

&lt;p&gt;If you prefer videos, there's a lot of YouTube channels which I'm sure you'll find useful :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/JavaBrainsChannel" rel="noopener noreferrer"&gt;Java Brains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/c/amigoscode" rel="noopener noreferrer"&gt;Amigoscode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Training &amp;amp; certification
&lt;/h3&gt;

&lt;p&gt;In your advanced learning stages, you absolutely need to validate your knowledge, in other words, to certify your assets. Here's all you have to know : &lt;a href="https://spring.io/training" rel="noopener noreferrer"&gt;Spring | training&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spring</category>
      <category>springboot</category>
      <category>java</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Lost in binaries? Here’s what I do!</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Tue, 21 Sep 2021 12:02:54 +0000</pubDate>
      <link>https://dev.to/daasrattale/lost-in-binaries-here-s-what-i-do-1b1a</link>
      <guid>https://dev.to/daasrattale/lost-in-binaries-here-s-what-i-do-1b1a</guid>
      <description>&lt;p&gt;We all had and will surely have moments of uncertainty and completely suffering under the weight of the logical/technical problem we must handle.&lt;br&gt;
Okay, let’s start with this, YOU ARE NOT THE ONLY ONE WHO SUFFERS, WE ALL DO, the only difference is how often you get this, and how strong you become handling it over and over.&lt;/p&gt;

&lt;p&gt;I still remember my second internship as a software developer, I was a part of the team charged with building the mobile app version using react native, guess what? I don’t even master vanilla javascript nor how to build a mobile application! And let’s say I was completely screwed 'cause I had only 45 days to deliver the final version of something I had no idea about.&lt;/p&gt;

&lt;p&gt;What I’m saying here is not a new framework to master, but also a new design thinking to adapt, a new structure to set, and definitely a new solution to provide.&lt;/p&gt;

&lt;p&gt;That’s one of the situations I love and appreciate, yes! you read that right, that’s a golden opportunity to upgrade your set of skills and open up to new technical points of view.&lt;br&gt;
Now, Let’s start with what I did and let us just skip the self-doubt moments 😁.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Divide and conquer
&lt;/h2&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2APpUgUCH7FIvGqeOIkRl-Uw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2APpUgUCH7FIvGqeOIkRl-Uw.jpeg" width="800" height="450"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;What you need to know, is the problem you’re dealing with is a strong opponent to be handled at once and fully, and the best way to win the game is to turn it into a set of small problems that you will handle one by one.&lt;/p&gt;

&lt;p&gt;In my case here, is to turn my big problem, being overwhelmed with all this new stuff into these tiny fries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting into mobile development and think like a mobile developer.&lt;/li&gt;
&lt;li&gt;Mastering JavaScript as fast as possible and go after the web version of React (ReactJS) so I can understand its mobile version (React native).&lt;/li&gt;
&lt;li&gt;Checking out lot of open-sourced react projects so I’ll have an idea of how things are actually being done by professionals.&lt;/li&gt;
&lt;li&gt;Last and not least, getting to know the dev environment requirements and setup mine properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you feel like you need to, divide each one of these as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Go old school
&lt;/h2&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F960%2F1%2AXSpDrVMoMHvgyE5b60_0OA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F960%2F1%2AXSpDrVMoMHvgyE5b60_0OA.gif" width="480" height="195"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;It's a wonderful habit to go for a pen and paper when your brain can no longer visualize things properly.&lt;br&gt;
Instead of having that badly-crafted net of thoughts in your mind, why just make them real in a couple of notes and diagrams.&lt;/p&gt;

&lt;p&gt;Nevertheless, there're tools to help you get the job done:&lt;/p&gt;
&lt;h3&gt;
  
  
  For diagrams and drawings :
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://app.diagrams.net/" rel="noopener noreferrer"&gt;Draw.io&lt;/a&gt; : For designing your charts properly.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AXLsRRViEUA2mSLC2plnB5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AXLsRRViEUA2mSLC2plnB5w.png" width="800" height="454"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  For notes :
&lt;/h3&gt;

&lt;p&gt;I used to use &lt;a href="https://www.onenote.com/" rel="noopener noreferrer"&gt;One Note&lt;/a&gt; and it’s really amazing !&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AizKZcrDlgMp6aHyQTvyAaA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AizKZcrDlgMp6aHyQTvyAaA.jpeg" width="800" height="364"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Since I switched to MacOs and iOS, I'm using &lt;a href="https://www.icloud.com/notes" rel="noopener noreferrer"&gt;Apple Note&lt;/a&gt;, it's simple and classy !&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2ApQddpCd69VswKURa9jUBpg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2ApQddpCd69VswKURa9jUBpg.jpeg" width="800" height="616"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  And something really helpful :
&lt;/h3&gt;

&lt;p&gt;I got this idea while watching a med doctor performing an autopsy and recording a vocal report in the process.&lt;br&gt;
You can use any &lt;strong&gt;voice record&lt;/strong&gt; application to store your ideas, the best about this is that your feelings are stored too, so record them with &lt;strong&gt;passion&lt;/strong&gt; and &lt;strong&gt;excitement&lt;/strong&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Make use of your superpowers
&lt;/h2&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AHvlyDLkHH-6jWOyvvYwebQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AHvlyDLkHH-6jWOyvvYwebQ.png" width="800" height="430"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;You have those, but not all the time!&lt;/p&gt;

&lt;p&gt;While relaxed, we intend to think very clearly, and our brains work just magically.&lt;br&gt;
Yes, I’m talking about that shower time, bathroom time, or maybe that night walk time when your brain can make wonderful blueprints.&lt;/p&gt;

&lt;p&gt;While having a similar problem, I intend to have showers, sometimes 3 per day, night walks alone, or you’ll find me just laying down on my bed, thinking deeply of what needs to be done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t waste that on drama or some uselessness!&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. It is what it is
&lt;/h2&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F996%2F1%2AeV2eKRRYfL8w2N6kb8HWew.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F996%2F1%2AeV2eKRRYfL8w2N6kb8HWew.gif" width="498" height="380"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Sometimes, in order to handle a problem, you first need to clear your mind. In other words, you need to forget about it &lt;strong&gt;temporarily&lt;/strong&gt; and don't give a damn for the moment.&lt;/p&gt;

&lt;p&gt;But remember you only do that to give yourself a break from that emotional pressure, &lt;strong&gt;so be careful, without your control, it can turn into a lifetime break&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Get some help
&lt;/h2&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AkK-lsl-38LYGHi3__t3DSw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2AkK-lsl-38LYGHi3__t3DSw.jpeg" width="800" height="433"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;It may be a one-person job, still, you can have someone who’ll have your back.&lt;/p&gt;

&lt;p&gt;Sometimes the job is confidential and should not be shared, but I’m not talking technically, I have &lt;strong&gt;friends&lt;/strong&gt; who help me bear the pain, for that I’m grateful, &lt;strong&gt;emotional support&lt;/strong&gt; is way more important than technical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure you surround yourself with worthy people!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally,
&lt;/h2&gt;

&lt;p&gt;I’d like to say, having problems like these, doesn’t mean you’re dumb or stupid, doesn’t mean you made the wrong choice, it only means that you got yourself into a new situation, and you need to adapt to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn, adapt and overcome, remember?
&lt;/h3&gt;

</description>
      <category>devlive</category>
      <category>devlife</category>
      <category>dev</category>
      <category>engineer</category>
    </item>
    <item>
      <title>What about your first IT internship?</title>
      <dc:creator>Elattar Saad </dc:creator>
      <pubDate>Tue, 21 Sep 2021 12:00:17 +0000</pubDate>
      <link>https://dev.to/daasrattale/what-about-your-first-it-internship-2305</link>
      <guid>https://dev.to/daasrattale/what-about-your-first-it-internship-2305</guid>
      <description>&lt;p&gt;Like everyone I’ve been amazed by what the digital world is made of, and what it can offer us as an added value to our daily life. Don’t get me wrong I’m still amazed even as a senior computer engineering student.&lt;br&gt;
I’m a Moroccan youngster who always had a dream of becoming a computer scientist, my first most real step was joining the Higher School of Technology in Essaouira, yes, where the journey started.&lt;br&gt;
I mainly address my talk to the newbies, computer engineering students and whoever wants to follow this path :&lt;/p&gt;

&lt;p&gt;You spent some time as a fresh IT student, had some basics in mind, you even tried to experiment how it works in real projects, but what you still lacking here is the professional experience, trust me I know.&lt;/p&gt;

&lt;p&gt;I still remember my first days, looking for internships, I’m not going to lie, it was a taught process, but it could be so much easier with some external help. Here I am giving you what I wish I’ve been told:&lt;/p&gt;
&lt;h2&gt;
  
  
  1.Know what you want
&lt;/h2&gt;

&lt;p&gt;The step towards having a good internship is knowing what field you want, if you’re into web development, for example, you have to focus your energy on web development companies.&lt;br&gt;
Knowing your true desires will guide your search process.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A2gxkQsZIbhSy00LXj4aQCw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F1%2A2gxkQsZIbhSy00LXj4aQCw.gif" width="500" height="281"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  2.Know your target
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Collect their information
&lt;/h3&gt;

&lt;p&gt;After having an idea of what field to target, the next step will be looking for companies in the same field.&lt;br&gt;
You can use whatever search tool you want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Social media (I recommend LinkedIn)&lt;/li&gt;
&lt;li&gt;Social contacts (a friend of a friend, your school’s professional network, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But you still want to know what you must collect as valuable information, you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Obviously, an active contact (an e-mail address or a phone number)&lt;/li&gt;
&lt;li&gt;An idea about what this company do, its projects, its partners and for sure some names (its executive board, its HR manager, its director (or CEO/CTO), etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another thing, from personal experience, I advise you to apply for small companies’ internships, in these, you will be charged with more tasks so you can gain more experience.&lt;/p&gt;

&lt;p&gt;These specifications will help you to establish a connection and will give an idea of what you’ll be asked during the interview (if required).&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0%2AiZzti26dftKNQtoy" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0%2AiZzti26dftKNQtoy" width="800" height="533"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  The interview
&lt;/h3&gt;

&lt;p&gt;Sometimes the interview is not required, but you still have to be prepared for anything.&lt;/p&gt;

&lt;p&gt;During the interview, you can be asked about every detail in your Curriculum Vitae including your technical/hard skills such as programming languages, technologies and frameworks you’re familiar with, etc., your soft skills such as teamwork, team management, public speaking, etc., professional experience if you have some and hobbies.&lt;/p&gt;

&lt;p&gt;But here’s the good news, you have a trump card, which is the information you collected about this company, and which will show how interested and professional are you, especially if what they need is the same you can provide them within your CV.&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0%2AmsQePCEO2AkxPm1Z" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1400%2F0%2AmsQePCEO2AkxPm1Z" width="800" height="534"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  3.Know what you have
&lt;/h2&gt;

&lt;p&gt;For sure you need to know what you do best so you can use as an advantage:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Curriculum Vitae
&lt;/h3&gt;

&lt;p&gt;What you have here is literally who you are as a piece of paper, and while you apply your CV should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;True: Never lie, or put something you don’t have.&lt;/li&gt;
&lt;li&gt;Dynamic: you can’t use the same CV every time you apply (depends on the company needs and what position you’re applying for), and I said the moment your CV will get attention the company needs intersect with what skills you can offer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The motivation letter
&lt;/h3&gt;

&lt;p&gt;You got to know the importance of this document, and it has a huge effect on whatever decision the company will take.&lt;/p&gt;

&lt;p&gt;The motivation letter is literally what your intentions are, the reason behind that pushes you to have this internship and mostly what qualifies you to have it and not somebody else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure you make your intentions clear&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The portfolio
&lt;/h3&gt;

&lt;p&gt;Here’s the thing not required for your first internship, but it will give you a huge boost, it’s kind of here’s my work in real terms, and it better be deployed in a public environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;The internship is your gate to the professional you, it’s the opportunity to improve your skills, work with others and mostly contribute to real projects that will make our daily life even easier.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
