<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: André Moriya</title>
    <description>The latest articles on Forem by André Moriya (@andremoriya).</description>
    <link>https://forem.com/andremoriya</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%2F365741%2F06795f92-dccc-4582-911c-0fd9587b59bf.jpg</url>
      <title>Forem: André Moriya</title>
      <link>https://forem.com/andremoriya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andremoriya"/>
    <language>en</language>
    <item>
      <title>SOLID Principles</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Thu, 07 Aug 2025 16:43:03 +0000</pubDate>
      <link>https://forem.com/andremoriya/solid-principles-56jd</link>
      <guid>https://forem.com/andremoriya/solid-principles-56jd</guid>
      <description>&lt;h2&gt;
  
  
  Everyone knows, but it's worth remembering 😂
&lt;/h2&gt;

&lt;p&gt;Hi fellow developers!&lt;/p&gt;

&lt;p&gt;My topic today is about &lt;strong&gt;SOLID&lt;/strong&gt;. I decided to write about it to learn more and share this content with you. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SOLID&lt;/strong&gt; is a set of 5 essential principles that help developers write clean, maintainable, and scalable object-oriented code. In this article, we’ll dive deep into each principle with clear explanations and real Java examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 What is SOLID?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;S.O.L.I.D&lt;/strong&gt; is an acronym introduced by Robert C. Martin (Uncle Bob) that stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt;: Single Responsibility Principle
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O&lt;/strong&gt;: Open/Closed Principle
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L&lt;/strong&gt;: Liskov Substitution Principle
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I&lt;/strong&gt;: Interface Segregation Principle
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D&lt;/strong&gt;: Dependency Inversion Principle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These principles guide developers in designing software that’s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to maintain&lt;/li&gt;
&lt;li&gt;More reusable&lt;/li&gt;
&lt;li&gt;More readable&lt;/li&gt;
&lt;li&gt;Less prone to bugs&lt;/li&gt;
&lt;li&gt;Easier to test and scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a closer look at each letter.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 1. Single Responsibility Principle (SRP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 “A class should have only one reason to change.” Each class should do one thing and do it well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ Why?&lt;br&gt;
If a class has multiple responsibilities, changes to one responsibility might break the others.&lt;/p&gt;

&lt;p&gt;✅ Example:&lt;br&gt;
Use interfaces or abstract classes and inheritance to extend behavior.&lt;/p&gt;

&lt;p&gt;🛑 Bad Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;calculateTotal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveToDatabase&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;printInvoice&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&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;In my opinion this class isn't a good example to try to explain this principle. I don't have any idea in my mind, but I hope it helps you understand.🤣&lt;br&gt;
This class mixes business logic, persistence, and presentation - all in one. 😁 This situation is not something you would encounter in real life, in a real project or on your project. At least that's what I hope 🙏😅&lt;br&gt;
This class is hard to test, maintain and opened to create a bug&lt;/p&gt;

&lt;p&gt;✅ Good Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;voic&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="n"&gt;input&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceCalculator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;InvoiceRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceDAO&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;InvoiceRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="n"&gt;input&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoicePrinter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="cm"&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;Each class now has a single responsibility.&lt;/p&gt;

&lt;p&gt;Maybe, we could use a functional interface like &lt;a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/function/Function.html" rel="noopener noreferrer"&gt;Function&lt;/a&gt; or &lt;a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/function/Consumer.html" rel="noopener noreferrer"&gt;Consumer&lt;/a&gt; and take advantage of java language features.&lt;br&gt;
What's do you think about it?&lt;/p&gt;


&lt;h2&gt;
  
  
  🔹 2. Open/Closed Principle (OCP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 “Software entities should be open for extension but closed for modification.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ Why?&lt;br&gt;
Modifying existing code introduces risk. Extending it (e.g., via inheritance or composition) avoids breaking tested code.&lt;/p&gt;

&lt;p&gt;🛑 Bad Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&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;method&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CreditCard"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PayPal"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&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;✅ Good Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreditCardPayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Paying with credit card"&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Paying with PayPal"&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentMethod&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Easily extend by adding new PaymentMethod types&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;No need to modify PaymentProcessor to add new methods — just extend PaymentMethod.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 3. Liskov Substitution Principle (LSP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 “Subtypes must be substitutable for their base types.”&lt;br&gt;
A subclass should be able to replace its parent class without breaking the program.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ Why?&lt;/p&gt;

&lt;p&gt;Violating this leads to code that crashes or behaves incorrectly when using polymorphism.&lt;/p&gt;

&lt;p&gt;🛑 Bad Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Flying"&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;class&lt;/span&gt; &lt;span class="nc"&gt;Ostrich&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&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;UnsupportedOperationException&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;Calling fly() on Bird works for most birds, but fails for Ostrich — violating LSP.&lt;/p&gt;

&lt;p&gt;✅ Good Example (Refactored Design):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flyable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sparrow&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Flyable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fly&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sparrow flying"&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;class&lt;/span&gt; &lt;span class="nc"&gt;Ostrich&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bird&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Doesn't implement Flyable&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, only birds that can fly implement Flyable, respecting LSP.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 4. Interface Segregation Principle (ISP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 “Clients should not be forced to depend on methods they do not use.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Split large, bloated interfaces into smaller, more specific ones.&lt;/p&gt;

&lt;p&gt;✅ Why?&lt;br&gt;
A class should only implement the methods it needs. Large interfaces cause unnecessary complexity.&lt;/p&gt;

&lt;p&gt;🛑 Bad Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Machine&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fax&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimplePrinter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Machine&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Printing..."&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Not needed */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;fax&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Not needed */&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forces SimplePrinter to implement unused methods.&lt;/p&gt;

&lt;p&gt;✅ Good Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Scanner&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scan&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimplePrinter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Printer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Printing..."&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;Each class now depends only on what it actually uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 5. Dependency Inversion Principle (DIP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 “High-level modules should not depend on low-level modules. Both should depend on abstractions.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depend on interfaces, not concrete implementations.&lt;/p&gt;

&lt;p&gt;✅ Why?&lt;br&gt;
This promotes flexibility, testability, and decoupling.&lt;/p&gt;

&lt;p&gt;🛑 Bad Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&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;PaypalProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&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;PaypalProcessor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// tightly coupled&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pay&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;✅ Good Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaypalProcessor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Paid with PayPal"&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&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;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&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;processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processor&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can easily swap PaypalProcessor for another processor or mock it in tests.&lt;/p&gt;

&lt;p&gt;📗 Summary Table&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;S&lt;/td&gt;
&lt;td&gt;Single Responsibility&lt;/td&gt;
&lt;td&gt;One reason to change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;Open/Closed&lt;/td&gt;
&lt;td&gt;Extend without modifying&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;Liskov Substitution&lt;/td&gt;
&lt;td&gt;Replace parent without breaking behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I&lt;/td&gt;
&lt;td&gt;Interface Segregation&lt;/td&gt;
&lt;td&gt;Don’t force classes to depend on unused methods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;Dependency Inversion&lt;/td&gt;
&lt;td&gt;Depend on abstractions, not concrete classes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Done!&lt;br&gt;
I hope this post is useful for me 😅 and you now and in the future, and that you will find it helpful. 🙏&lt;br&gt;
If you have any opinions, criticisms or ideas, don't hesitate to get in touch.&lt;/p&gt;

&lt;p&gt;Thank you very much&lt;br&gt;
See ya!&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>cleancoding</category>
      <category>learning</category>
    </item>
    <item>
      <title>Handling Exceptions in Spring with OncePerRequestFilter and @ControllerAdvice</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Thu, 21 Mar 2024 15:17:08 +0000</pubDate>
      <link>https://forem.com/andremoriya/onceperrequestfilter-catching-an-exception-in-controlleradvice-1fhk</link>
      <guid>https://forem.com/andremoriya/onceperrequestfilter-catching-an-exception-in-controlleradvice-1fhk</guid>
      <description>&lt;p&gt;Hello, fellow developers!&lt;/p&gt;

&lt;p&gt;Recently, I encountered a challenging scenario while working with Spring's &lt;code&gt;OncePerRequestFilter&lt;/code&gt; and &lt;code&gt;@ControllerAdvice&lt;/code&gt; for exception handling. I'm excited to share both the problem I faced and the solution I discovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In my project, where I extensively use &lt;code&gt;@ControllerAdvice&lt;/code&gt; to handle exceptions, I integrated a OncePerRequestFilter for request filtering. Initially, I assumed the exceptions thrown in the filter would be neatly caught by my controller advice. However, that wasn't the case.&lt;/p&gt;

&lt;p&gt;Here's how my CustomFilter looked initially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Slf4j
public class CustomFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String trackingId = (String) request.getAttribute(Constants.TRACKING_ID);
        ContentRequestWrapper requestWrapper = new ContentRequestWrapper(request);

        try {
            filterChain.doFilter(requestWrapper, response);
        } catch (RuntimeException e) {
            log.error("Error on method [doFilterInternal]: {} {} Tracking-ID: {}",
                      e.getClass(), e.getMessage(), trackingId, e);
            throw new RuntimeException("Message");
        } catch (Exception e) {
            log.error("Error on method [doFilterInternal] Exception: {} - Tracking ID {}",
                      e.getMessage(), trackingId, e);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And my &lt;code&gt;ControllerExceptionHandler&lt;/code&gt; looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Slf4j
@ControllerAdvice
public class ControllerExceptionHandler {
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity&amp;lt;StandardError&amp;gt; requestError(RuntimeException e, HttpServletRequest request) {
        String trackingId = request.getAttribute(Constants.TRACKING_ID).toString();
        logger.error("Service Error - TrackingId: {}", trackingId, e);

        var error = StandardError.builder()
                .trackingId(trackingId)
                .timestamp(LocalDateTime.now())
                .path(request.getRequestURI())
                .error("Service Error")
                .status(SERVICE_UNAVAILABLE.value())
                .message(e.getMessage())
                .build();

        return ResponseEntity.status(SERVICE_UNAVAILABLE).body(error);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, exceptions thrown in CustomFilter were not being handled by &lt;code&gt;ControllerExceptionHandler&lt;/code&gt; as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the Solution
&lt;/h2&gt;

&lt;p&gt;After some research and experimentation, I found a valuable post on Stack Overflow that addressed a similar issue. It suggested integrating the HandlerExceptionResolver.&lt;/p&gt;

&lt;p&gt;Here’s how I modified my CustomFilter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Slf4j
@Component("customRequestFilter")
public class CustomFilter extends OncePerRequestFilter {
    private final HandlerExceptionResolver resolver;

    public CustomFilter(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver resolver) {
        this.resolver = resolver;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String trackingId = (String) request.getAttribute(Constants.TRACKING_ID);
        log.info("Method [doFilterInternal] checking authorization: tracking-id {}", trackingId);

        ContentRequestWrapper requestWrapper = new ContentRequestWrapper(request);
        try {
            filterChain.doFilter(requestWrapper, response);
        } catch (RuntimeException e) {
            log.error("Error on method [doFilterInternal]: {} {} Tracking-ID: {}",
                      e.getClass(), e.getMessage(), trackingId, e);
            resolver.resolveException(request, response, null, e);
        } catch (Exception e) {
            log.error("Error on method [doFilterInternal] Exception: {} - Tracking ID {}",
                      e.getMessage(), trackingId, e);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, I needed to register CustomFilter with Spring's context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Bean(name = "customFilter")
public FilterRegistrationBean&amp;lt;CustomFilter&amp;gt; basicAuthFilterFilter() {
    final FilterRegistrationBean&amp;lt;CustomFilter&amp;gt; filterRegistrationBean = new FilterRegistrationBean&amp;lt;&amp;gt;();
    filterRegistrationBean.setFilter(customFilter);
    filterRegistrationBean.addUrlPatterns("/subscription/*");
    filterRegistrationBean.setName("CustomFilter");
    return filterRegistrationBean;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;By integrating &lt;code&gt;HandlerExceptionResolver&lt;/code&gt; into CustomFilter and utilizing resolver.resolveException() within the catch blocks, I was able to ensure that exceptions thrown in the filter were handled by ControllerAdvice. This approach may not be suitable for every situation, but it worked effectively for my specific needs.&lt;/p&gt;

&lt;p&gt;I hope this breakdown helps you understand how to better manage exceptions in your Spring applications. If you face a similar problem, perhaps this solution will be helpful!&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy coding!&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>community</category>
    </item>
    <item>
      <title>How to use the keycloak latest tag instead of the legancy tag, in your docker-compose.</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Tue, 02 Aug 2022 15:07:00 +0000</pubDate>
      <link>https://forem.com/andremoriya/how-to-use-the-keycloak-latest-tag-instead-of-the-legancy-tag-in-you-docker-compose-3an2</link>
      <guid>https://forem.com/andremoriya/how-to-use-the-keycloak-latest-tag-instead-of-the-legancy-tag-in-you-docker-compose-3an2</guid>
      <description>&lt;p&gt;Hi everyone.&lt;/p&gt;

&lt;p&gt;Some time ago, and after a long time, I was trying to use again a new keycloak version.&lt;br&gt;
But I've had some problem to start my container with this compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'
volumes:
  postgres_data:
    driver: local
  keycloak_data:
    driver: local
networks:
  local:
    name: localhost
    external: true
services:
  postgres:
    image: 'postgres:latest'
    networks:
      - local
    volumes:
      - 'postgres_data:/var/lib/postgresql/data'
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: password
  keycloak:
    image: 'quay.io/keycloak/keycloak:latest'
    networks:
      - local
    environment:
      DB_VENDOR: POSTGRES
      DB_ADDR: postgres
      DB_DATABASE: keycloak
      DB_USER: keycloak
      DB_SCHEMA: public
      DB_PASSWORD: password
      KEYCLOAK_USER: kc_user
      KEYCLOAK_PASSWORD: kc_pass
    ports:
      - '8000:8080'
    depends_on:
      - postgres
  pgadmin4:
    image: 'dpage/pgadmin4:latest'
    environment:
      PGADMIN_DEFAULT_EMAIL: andremoriya@gmail.com
      PGADMIN_DEFAULT_PASSWORD: admin123
    networks:
      - local
    depends_on:
      - postgres
    ports:
      - '6543:80'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I just wanted to see if this compose worked, but when I ran docker-compose, I received the following error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attaching to keycloak-latest_keycloak_1
keycloak_1  | Keycloak - Open Source Identity and Access Management
keycloak_1  | 
keycloak_1  | Find more information at: https://www.keycloak.org/docs/latest
keycloak_1  | 
keycloak_1  | Usage:
keycloak_1  | 
keycloak_1  | kc.sh [OPTIONS] [COMMAND]
keycloak_1  | 
keycloak_1  | Use this command-line tool to manage your Keycloak cluster.
keycloak_1  | Make sure the command is available on your "PATH" or prefix it with "./" (e.g.:
keycloak_1  | "./kc.sh") to execute from the current folder.
keycloak_1  | 
keycloak_1  | Options:
keycloak_1  | 
keycloak_1  | -cf, --config-file 
keycloak_1  |                      Set the path to a configuration file. By default, configuration properties are
keycloak_1  |                        read from the "keycloak.conf" file in the "conf" directory.
keycloak_1  | -h, --help           This help message.
keycloak_1  | -v, --verbose        Print out error details when running this command.
keycloak_1  | -V, --version        Show version information
keycloak_1  | 
keycloak_1  | Commands:
keycloak_1  | 
keycloak_1  |   build                   Creates a new and optimized server image.
keycloak_1  |   start                   Start the server.
keycloak_1  |   start-dev               Start the server in development mode.
keycloak_1  |   export                  Export data from realms to a file or directory.
keycloak_1  |   import                  Import data from a directory or a file.
keycloak_1  |   show-config             Print out the current configuration.
keycloak_1  |   tools                   Utilities for use and interaction with the server.
keycloak_1  |     completion            Generate bash/zsh completion script for kc.sh.
keycloak_1  | 
keycloak_1  | Examples:
keycloak_1  | 
keycloak_1  |   Start the server in development mode for local development or testing:
keycloak_1  | 
keycloak_1  |       $ kc.sh start-dev
keycloak_1  | 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Changing
&lt;/h2&gt;

&lt;p&gt;So, in our compose, we must change and add a few simple configurations.&lt;/p&gt;

&lt;p&gt;The admin environment variable in Keycloak has been changed from &lt;code&gt;KEYCLOAK_USER&lt;/code&gt; and &lt;code&gt;KEYCLOAK_PASSWORD&lt;/code&gt; to &lt;code&gt;KEYCLOAK_ADMIN&lt;/code&gt; and &lt;code&gt;KEYCLOAK_ADMIN_PASSWORD&lt;/code&gt; respectively.&lt;br&gt;
And we must include the 'command: start-dev' in our compose.&lt;/p&gt;

&lt;p&gt;After changing, our compose should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;....
  keycloak:
    image: 'quay.io/keycloak/keycloak:latest'
    networks:
      - local
    environment:
      // new environment variables
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgresqldb:5432/keycloak
      KC_DB_USERNAME: user
      KC_DB_PASSWORD: pass
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin123
    ports:
      - '8000:8080'
    command: start-dev // Added
    depends_on:
      - postgres
....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we can run again, and the console output should look like this.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attaching to keycloak-latest_keycloak_1keycloak_1  | Updating the configuration and installing your custom providers, if any. Please wait.Attaching to keycloak-latest_keycloak_1
keycloak_1  | 2022-08-02 15:02:59,158 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 6757ms
keycloak_1  | 2022-08-02 15:03:02,504 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: FrontEnd: , Strict HTTPS: false, Path: , Strict BackChannel: false, Admin: , Port: -1, Proxied: false
keycloak_1  | 2022-08-02 15:03:03,351 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
keycloak_1  | 2022-08-02 15:03:03,469 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
keycloak_1  | 2022-08-02 15:03:03,514 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
keycloak_1  | 2022-08-02 15:03:03,752 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000128: Infinispan version: Infinispan 'Triskaidekaphobia' 13.0.9.Final
keycloak_1  | 2022-08-02 15:03:04,200 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_357415, Site name: null
keycloak_1  | 2022-08-02 15:03:05,672 INFO  [org.keycloak.quarkus.runtime.storage.database.liquibase.QuarkusJpaUpdaterProvider] (main) Initializing database schema. Using changelog META-INF/jpa-changelog-master.xml
keycloak_1  | 2022-08-02 15:03:08,125 INFO  [org.keycloak.services] (main) KC-SERVICES0050: Initializing master realm
keycloak_1  | 2022-08-02 15:03:10,137 INFO  [org.keycloak.services] (main) KC-SERVICES0009: Added user 'admin' to realm 'master'
keycloak_1  | 2022-08-02 15:03:10,279 INFO  [io.quarkus] (main) Keycloak 18.0.2 on JVM (powered by Quarkus 2.7.5.Final) started in 10.932s. Listening on: http://0.0.0.0:8080
keycloak_1  | 2022-08-02 15:03:10,280 INFO  [io.quarkus] (main) Profile dev activated. 
keycloak_1  | 2022-08-02 15:03:10,280 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-metrics, vault, vertx]
keycloak_1  | 2022-08-02 15:03:10,287 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And using the web browser, we can see this page:&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%2F0bx6o606gqyw7mttqqzf.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%2F0bx6o606gqyw7mttqqzf.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

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

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;That's something I've recently discovered.&lt;/p&gt;

&lt;p&gt;If you have any suggestions for how I can improve this post, please let me know. Please leave a comment if you have any suggestions or criticism.&lt;/p&gt;

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

</description>
      <category>docker</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>Apache camel: Xml file to JSON file.</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Fri, 29 Jul 2022 18:40:28 +0000</pubDate>
      <link>https://forem.com/andremoriya/apache-camel-xml-file-to-json-file-2m36</link>
      <guid>https://forem.com/andremoriya/apache-camel-xml-file-to-json-file-2m36</guid>
      <description>&lt;p&gt;Hi there,&lt;/p&gt;

&lt;p&gt;I started learning Apache Camel a few days ago and was having difficulty with this simple case: Creating a JSON file from an XML file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1: Old version
&lt;/h2&gt;

&lt;p&gt;I picked up a project from a course I was taking. And the version used in this course was out of date. The course was using the dependency 'camel-xmljson,' which has since been removed in the new version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrading project
&lt;/h2&gt;

&lt;p&gt;So I've decided to upgrade project to use &lt;code&gt;Java 17&lt;/code&gt; and apache camel version &lt;code&gt;3.18.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To do this, I've needed to import new dependencies on project:&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;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.camel&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;camel-jaxb&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${camel-version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.camel&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;camel-jackson&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${camel-version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.camel&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;camel-jacksonxml&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${camel-version}&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Refactoring the code
&lt;/h2&gt;

&lt;p&gt;After import the new dependencies, I needed to refactor my code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before refactoring
&lt;/h3&gt;

&lt;p&gt;The code was as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static void main(String[] args) throws Exception {

        CamelContext context = new DefaultCamelContext();
        context.addRoutes(new RouteBuilder() {

            @Override
            public void configure() throws Exception {

                from("file:pedidos?delay=5s&amp;amp;noop=true").
                    split().
                        xpath("/pedido/itens/item").
                    filter().
                        xpath("/item/formato[text()='EBOOK']").
                    marshal().xmljson().
                    log("${id} - ${body}").
                    setHeader(Exchange.FILE_NAME, simple("${file:name.noext}-${header.CamelSplitIndex}.json")).
                to("file:saida");
            }

        });

        context.start();
        Thread.sleep(20000);
        context.stop();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After refactoring
&lt;/h3&gt;

&lt;p&gt;And now I needed to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static void main(String[] args) throws Exception {

        try (CamelContext context = new DefaultCamelContext()) {
            JacksonDataFormat jacksonDataFormat = new JacksonDataFormat();
            jacksonDataFormat.setPrettyPrint(true);
            jacksonDataFormat.enableFeature(SerializationFeature.WRAP_ROOT_VALUE);

            context.addRoutes(new RouteBuilder() {

                @Override
                public void configure() throws Exception {

                    from("file:input?delay=5s&amp;amp;noop=true")
                        .filter()
                            .xpath("/pedido/itens/item/formato[text()='EBOOK']")
                        .unmarshal().jacksonXml(Pedido.class)
                        .marshal(jacksonDataFormat)
                        .setHeader(Exchange.FILE_NAME, simple("${file:name.noext}.json"))
                        .to("file:output");
                }

            });

            context.start();
            Thread.sleep(20000);
            context.stop();
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I needed to use some jackson annotations in "Pedido.java":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "pedido")
public class Pedido {

    @JacksonXmlProperty(localName = "id")
    private String id;
    @JacksonXmlProperty(localName = "dataCompra")
    private String dataCompra;
    @JacksonXmlProperty(localName = "itens")
    private Itens itens;
    @JacksonXmlProperty(localName = "pagamento")
    private Pagamento pagamento;

....
// getters and setters

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

&lt;/div&gt;



&lt;p&gt;Note that 'Before refactoring,' I only needed to use'marshal().xmljson(),' and 'After refactoring,' I needed to do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JacksonDataFormat jacksonDataFormat = new JacksonDataFormat();
jacksonDataFormat.setPrettyPrint(true);
jacksonDataFormat.enableFeature(SerializationFeature.WRAP_ROOT_VALUE);

.unmarshal().jacksonXml(Pedido.class)
.marshal(jacksonDataFormat)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Well, this was the solution I discovered.&lt;/p&gt;

&lt;p&gt;I know, there must be a better method, and if you know, left your comment and help me improve. :D&lt;/p&gt;

&lt;p&gt;Thank you very much and see you!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[pt-br] Acessando keycloak via Spring Netflix Zuul</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Fri, 24 Sep 2021 19:12:23 +0000</pubDate>
      <link>https://forem.com/andremoriya/pt-br-acessando-keycloak-via-spring-netflix-zuul-182n</link>
      <guid>https://forem.com/andremoriya/pt-br-acessando-keycloak-via-spring-netflix-zuul-182n</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Olá pessoal!&lt;/p&gt;

&lt;p&gt;Hoje eu vou escrever sobre um problema que estava tendo entre o &lt;a href="https://spring.io/projects/spring-cloud-netflix#overview" rel="noopener noreferrer"&gt;Spring Netflix Zuul&lt;/a&gt; e o &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;keycloak&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema entre o Zuul e o keycloak
&lt;/h2&gt;

&lt;p&gt;O que estava ocorrendo era o seguinte.&lt;/p&gt;

&lt;p&gt;Devido a um cliente, precisamos fazer com que o keycloak fosse acessado externamente via o nosso gateway.&lt;/p&gt;

&lt;p&gt;Porém ao fazer os testes, acessando essa tela de login do keycloak&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%2F0wwyvr14nrb93dovr5f9.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%2F0wwyvr14nrb93dovr5f9.png" alt="image"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Via o zuul e após informar o &lt;em&gt;username&lt;/em&gt; e &lt;em&gt;password&lt;/em&gt; estava recebendo o seguinte erro&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%2Fop8xzw23m61th6muzt1a.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%2Fop8xzw23m61th6muzt1a.png" alt="spring-zuul-keycloak-problem"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Porém não ocorria erro no container do zuul e nem do keycloak. O único erro que ocorria, aparecia no console do navegador, mas era apenas um erro 400 e mais nada.  &lt;/p&gt;

&lt;h2&gt;
  
  
  O que fiz para solucionar
&lt;/h2&gt;

&lt;p&gt;Pois bem, como pesquisando na internet não havia achado nada, fui para documentação do spring na parte &lt;a href="https://docs.spring.io/spring-cloud-netflix/docs/2.2.9.RELEASE/reference/html/#cookies-and-sensitive-headers" rel="noopener noreferrer"&gt;9.4. Cookies and Sensitive Headers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nessa parte mostra que, por padrão, a &lt;em&gt;sensitveHeaders&lt;/em&gt; há três valores: &lt;em&gt;Cookie,Set-Cookie,Authorization&lt;/em&gt;, como mostra o exemplo da própria documentação:&lt;/p&gt;

&lt;p&gt;application.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; zuul:
  routes:
    users:
      path: /myusers/**
      sensitiveHeaders: Cookie,Set-Cookie,Authorization
      url: https://downstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E na explicação abaixo, mostra o que fazer caso alguma rota precise dessas informações.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The sensitiveHeaders are a blacklist, and the default is not empty. Consequently, to make Zuul send all headers (except the ignored ones), you must explicitly set it to the empty list. Doing so is necessary if you want to pass cookie or authorization headers to your back end. The following example shows how to use sensitiveHeaders:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E foi isso que precisei fazer no meu application.properties, deixei conforme a documentação&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zuul.routes.auth.sensitive-headers=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Atualização
&lt;/h2&gt;

&lt;p&gt;Quando você for tentar efetuar o login, e no console do navegador estiver apresentando esse erro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Refused to display 'http(s)://host:port/' in a frame because it set 'X-Frame-Options' to 'deny'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vá nas configurações do seu Spring security e no método&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected void configure(HttpSecurity http) throws Exception
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicione a linha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http.headers().frameOptions().sameOrigin()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Após passar um bom tempo pesquisando e lendo a documentação, consegui fazer o acesso&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%2Fdfviq11rv0pcdb912rbz.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%2Fdfviq11rv0pcdb912rbz.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Qualquer dúvida que tenha, ou sugestões e críticas mande uma mensagem no &lt;a href="https://twitter.com/andremoriya" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; ou deixa aqui sua mensagem&lt;/p&gt;

&lt;p&gt;Muito obrigado e até a próxima. &lt;/p&gt;

</description>
      <category>springzuul</category>
      <category>java</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>JEP 378: Text Blocks. New way to use String in Java</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Fri, 24 Sep 2021 16:32:39 +0000</pubDate>
      <link>https://forem.com/andremoriya/jep-378-text-blocks-new-way-to-use-string-in-java-3f7g</link>
      <guid>https://forem.com/andremoriya/jep-378-text-blocks-new-way-to-use-string-in-java-3f7g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article, I'm going to show the Java Text Block feature!&lt;/p&gt;

&lt;p&gt;This feature is available since Java 15 and brings to us , a simple way to write Strings.&lt;/p&gt;

&lt;p&gt;Now some examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing simple HTML
&lt;/h2&gt;

&lt;p&gt;In this first example, when you need to write Html code. Before this feature, we need to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var html = "&amp;lt;html&amp;gt;\n" +
              "    &amp;lt;body&amp;gt;\n" +
              "        &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;\n" +
              "    &amp;lt;/body&amp;gt;\n" +
              "&amp;lt;/html&amp;gt;\n";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we had to concatenate each line to write this simple code.&lt;br&gt;
But see now with this new feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var html = """
    &amp;lt;html&amp;gt;
        &amp;lt;body&amp;gt;
            &amp;lt;p&amp;gt;Hello, world&amp;lt;/p&amp;gt;
        &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
""";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In these two cases, the output is:&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%2F4p6j4fx8chr203m23k3q.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%2F4p6j4fx8chr203m23k3q.png" alt="html"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing SQL queries
&lt;/h2&gt;

&lt;p&gt;In this second case, when you need to create a query for your application.&lt;/p&gt;

&lt;p&gt;Your code will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var query = "SELECT \"ID\", \"FIRST_NAME\", \"LAST_NAME\" FROM \"PERSON\"\n" + 
                   "WHERE \"CITY\" = 'CURITIBA'\n" + 
                   "ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";

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

&lt;/div&gt;



&lt;p&gt;With Text Blocks, this code above will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var query = """
          SELECT "EMP_ID",  "FIRST_NAME", "LAST_NAME" FROM "PERSON_TB"
          WHERE "CITY" = 'CURITIBA'
          ORDER BY "EMP_ID", "LAST_NAME";
          """;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And these two cases, the output is:&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%2F5t0mewinzot86t9x65nh.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%2F5t0mewinzot86t9x65nh.png" alt="query"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We saw the difference between writing Strings in Java with and without Text Blocks. Before it is more difficult and easier to make mistakes.&lt;/p&gt;

&lt;p&gt;This feature brings an easy way to write a test, for example, when you need to test a Rest API passing a JSON. Or when you need to write a complex query.&lt;/p&gt;

&lt;p&gt;If you want to know more about it, access this &lt;a href="https://openjdk.java.net/jeps/378" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And If you have any questions, leave a comment or ask me on my &lt;a href="https://twitter.com/andremoriya" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;A special thanks to &lt;a href="https://dev.to/ymoto"&gt;Yugo Sakamoto&lt;/a&gt; for helping me in this post!&lt;/p&gt;

&lt;p&gt;Thanks very much!&lt;/p&gt;

</description>
      <category>java</category>
      <category>string</category>
      <category>jep378</category>
      <category>textblocks</category>
    </item>
    <item>
      <title>[pt-br] keycloak: Resolvendo problema de 'WFLYCTL0348: Timeout after [300] seconds waiting for service container stability.'</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Thu, 19 Aug 2021 01:46:42 +0000</pubDate>
      <link>https://forem.com/andremoriya/keycloak-resolvendo-problema-de-wflyctl0348-timeout-after-300-seconds-waiting-for-service-container-stability-41bo</link>
      <guid>https://forem.com/andremoriya/keycloak-resolvendo-problema-de-wflyctl0348-timeout-after-300-seconds-waiting-for-service-container-stability-41bo</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Olá pessoal!&lt;/p&gt;

&lt;p&gt;Hoje meu post será sobre um problema que passei, no meu trabalho, subindo um container do keycloak e se conectando a base de dados do SQL Server na GCP Cloud SQL.&lt;/p&gt;

&lt;p&gt;Abaixo irei apresentar a solução que encontrei para o erro:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WFLYCTL0348: Timeout after [300] seconds waiting for service container stability.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O aconteceu?
&lt;/h2&gt;

&lt;p&gt;No trabalho estava testando o keycloak com o MS SQL Server.&lt;/p&gt;

&lt;p&gt;Rodando os containers localmente, do keycloak e do banco foi tudo tranquilo.&lt;/p&gt;

&lt;p&gt;Porém ao fazer o teste apontando o keycloak para o banco na GCP Cloud SQL, me deparei com o erro e o container parou de funcionar.&lt;/p&gt;

&lt;p&gt;Olhando para a base de dados, algumas tabelas foram criadas mas não todas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas por que disso?
&lt;/h2&gt;

&lt;p&gt;Isso acontece pois o keycloak, por padrão, vem configurado um timeout de 300 segundos e o liquibase nesse tempo não terminou ainda a migração.&lt;/p&gt;

&lt;p&gt;Para essa configuração há 3 variáveis na jogada: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;jboss.as.management.blocking.timeout&lt;/em&gt;&lt;br&gt;
&lt;em&gt;deployment-timeout&lt;/em&gt;&lt;br&gt;
&lt;em&gt;default-timeout&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  O que foi feito?
&lt;/h2&gt;

&lt;p&gt;Para resolver o problema foi necessário criar um arquivo para alterar esses timeout's, um Dockerfile para criar uma imagem customizada e o docker-compose para criar o container&lt;/p&gt;

&lt;h3&gt;
  
  
  Arquivo para alterar os timeout's
&lt;/h3&gt;

&lt;p&gt;O nome do meu arquivo foi &lt;em&gt;changeTimeout.batch&lt;/em&gt;, mas você pode escolher um nome melhor (rsrs).&lt;/p&gt;

&lt;p&gt;O conteúdo do arquivo ficou parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;embed-server --std-out=echo --server-config=standalone-ha.xml
batch
/system-property=jboss.as.management.blocking.timeout:add(value=900)
/subsystem=deployment-scanner/scanner=default:write-attribute(name=deployment-timeout,value=900)
/subsystem=transactions:write-attribute(name=default-timeout,value=900)
run-batch
stop-embedded-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse arquivo faz com que as 3 variáveis citados acima, seja alteradas para 900 segundos ou 15 minutos, mas você pode colocar o tempo que quiser, desde que seja em segundos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;

&lt;p&gt;O Dockerfile ficou assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM quay.io/keycloak/keycloak:10.0.2

COPY --chown=jboss ./changeTimeout.batch /tmp/changeTimeout.batch

RUN cd $JBOSS_HOME \
  &amp;amp;&amp;amp; ./bin/jboss-cli.sh --file=/tmp/changeTimeout.batch \
  &amp;amp;&amp;amp; rm -rf $JBOSS_HOME/standalone/configuration/standalone_xml_history \
  &amp;amp;&amp;amp; rm -rf $JBOSS_HOME/standalone/data \
  &amp;amp;&amp;amp; rm -rf $JBOSS_HOME/standalone/tmp \
  &amp;amp;&amp;amp; rm -rf /tmp/changeTimeout.batch

# Optional parameters

ENV KEYCLOAK_USER admin
ENV KEYCLOAK_PASSWORD admin123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criado o seu Dockerfile execute o comando para criar a imagem&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t keycloak . # O nome 'keycloak' será usado depois no docker-compose no parâmetro 'image'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;E o meu docker-compose ficou dessa forma:&lt;br&gt;
&lt;/p&gt;

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

services:
  keycloak-sqlserver:
    container_name: keycloak-sqlserver
    image: keycloak # Lembra o comentário acima, sobre o nome?
    environment:
      PROXY_ADDRESS_FORWARDING: "true"
      DB_VENDOR: mssql
      DB_ADDR: [IP]
      DB_DATABASE: [NOME_DB]
      DB_SCHEMA: dbo
      DB_USER: [USUARIO]
      DB_PASSWORD: [SENHA]
    ports:
      - 6090:8080
      - 6091:9990

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

&lt;/div&gt;



&lt;p&gt;Após feita essas configurações, execute o comando para testar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se tudo ocorrer bem (rsrsrs), após o liquibase finalizar a migração, o keycloak continuará com o processo de inicialização e você verá a seguinda saída nos logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01:33:57,370 INFO  [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0212: Resuming server
01:33:57,375 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://0.0.0.0:9990/management
01:33:57,376 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://0.0.0.0:9990
01:33:57,376 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 10.0.2 (WildFly Core 11.1.1.Final) started in 54943ms - Started 690 of 995 services (708 services are lazy, passive or on-demand)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Esse foi a solução que encontrei usando essa referência.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://serviceorientedarchitect.com/wflyctl0348-timeoutexception-while-running-keycloak-in-a-docker-container-with-an-external-database-mariadb/"&gt;WFLYCTL0348: TimeoutException while running Keycloak in a Docker container with an external database (MariaDB)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No meu caso estava usando o SQL Server e usei o docker-compose também.&lt;/p&gt;

&lt;p&gt;Espero que isso possa ajudá-lo, caso venha a ter o mesmo problema.&lt;/p&gt;

&lt;p&gt;Críticas, dúvidas ou sugestões entre em contato e vamos conversar.&lt;/p&gt;

&lt;p&gt;Muito obrigado&lt;/p&gt;

</description>
      <category>keycloak</category>
      <category>docker</category>
      <category>wflyctl0348</category>
      <category>timeout</category>
    </item>
    <item>
      <title>ObjectMapper: Conversion to generic types.</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Wed, 18 Aug 2021 13:20:20 +0000</pubDate>
      <link>https://forem.com/andremoriya/objectmapper-conversion-to-generic-types-1bpa</link>
      <guid>https://forem.com/andremoriya/objectmapper-conversion-to-generic-types-1bpa</guid>
      <description>&lt;p&gt;Hey folks!&lt;/p&gt;

&lt;p&gt;I decided to write this post because I needed to do a conversion using generic classes.&lt;/p&gt;

&lt;p&gt;It's quite simple, but I believe that it can be helpful in the future, both for myself and for other devs.&lt;/p&gt;

&lt;p&gt;What I was needed to get a JSON callback coming from a rest service, developed in the company.&lt;/p&gt;

&lt;p&gt;The code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CloseableHttpClient client = HttpClients.createDefault();

// Code omitted...
response = client.execute(request);
// Code omitted...

BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
ResponseApiDTO&amp;lt;ProductDTO&amp;gt; response = mapper.readValue(br.readLine(), new TypeReference&amp;lt;ResponseApiDTO&amp;lt;ProductDTO&amp;gt;&amp;gt;() {});

ProductDTO dto = response.getDto();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was basically it.&lt;br&gt;
As the project doesn't use spring, this was the way implemented.&lt;/p&gt;

&lt;p&gt;Well, that's it, I hope this post could have helped.&lt;/p&gt;

&lt;p&gt;Thanks&lt;/p&gt;

</description>
      <category>java</category>
      <category>generic</category>
      <category>json</category>
    </item>
    <item>
      <title>[pt-br] ObjectMapper: Convertendo para tipos genericos.</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Sun, 13 Jun 2021 16:08:20 +0000</pubDate>
      <link>https://forem.com/andremoriya/pt-br-objectmapper-convertendo-para-tipos-genericos-2c8k</link>
      <guid>https://forem.com/andremoriya/pt-br-objectmapper-convertendo-para-tipos-genericos-2c8k</guid>
      <description>&lt;p&gt;Olá pessoal!&lt;/p&gt;

&lt;p&gt;Decidi fazer esse post, pois precisei fazer uma conversão usando classes genéricas.&lt;/p&gt;

&lt;p&gt;É um tanto simples, mas que acredito que posso servir de ajuda futuramente, tanto pra mim quanto para outros devs.&lt;/p&gt;

&lt;p&gt;O que eu precisava, era pegar um retorno JSON vindo de um serviço rest.&lt;/p&gt;

&lt;p&gt;O código fico parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CloseableHttpClient client = HttpClients.createDefault();

// Codigos omitidos...
response = client.execute(request);
//Codigos omitidos...

BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));
ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
MensagemApiDTO&amp;lt;ProdutoDTO&amp;gt; resposta = mapper.readValue(br.readLine(), new TypeReference&amp;lt;MensagemApiDTO&amp;lt;ProdutoDTO&amp;gt;&amp;gt;() {});

ProdutoDTO dto = resposta.getDto();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O responsável por fazer a conversão é esse cara:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mapper.readValue(br.readLine(), new TypeReference&amp;lt;MensagemApiDTO&amp;lt;ProdutoDTO&amp;gt;&amp;gt;() {});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;em&gt;TypeReference&lt;/em&gt; faz a conversão para o seu objeto genérico. &lt;/p&gt;

&lt;p&gt;Basicamente foi isso.&lt;br&gt;
Como o projeto não usa spring, essa foi a maneira implementada.&lt;/p&gt;

&lt;p&gt;Bom é isso, espero que esse post possa ter ajudado.&lt;br&gt;
Criticas e sugestões são bem-vindas.&lt;/p&gt;

&lt;p&gt;Obrigado&lt;/p&gt;

</description>
      <category>java</category>
      <category>objectmapper</category>
      <category>generics</category>
    </item>
    <item>
      <title>keycloak + Azure Active Directory</title>
      <dc:creator>André Moriya</dc:creator>
      <pubDate>Sun, 13 Jun 2021 15:41:43 +0000</pubDate>
      <link>https://forem.com/andremoriya/keycloak-azure-active-directory-4cg4</link>
      <guid>https://forem.com/andremoriya/keycloak-azure-active-directory-4cg4</guid>
      <description>&lt;p&gt;Hi folks!&lt;/p&gt;

&lt;p&gt;In this post, I'm going to write about keycloak and Microsoft Azure Active Directory (AD).&lt;/p&gt;

&lt;p&gt;I have decided to write this post for two reasons: first, in my current job (02/2021), we need to integrate between keycloak and active directory because a customer uses azure AD, and second because I had a lot of difficulties searching for other posts on the subject to configure the keycloak and AD. So go ahead.&lt;/p&gt;

&lt;h1&gt;Register an app in Azure Active Directory&lt;/h1&gt;

&lt;p&gt;Acess the &lt;a rel="noreferrer noopener" href="https://portal.azure.com/#home"&gt;Microsoft azure&lt;/a&gt; portal and click in Azure Active Directory&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_dashboard.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_dashboard.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;Access from dashboard&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_menu_ad.png%3Fw%3D212" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_menu_ad.png%3Fw%3D212" alt=""&gt;&lt;/a&gt;Acess from menu&lt;/p&gt;

&lt;p&gt;When you click on the menu, you'll be to redirect to the tenant overview. If you don't have any tenants, please see the &lt;a rel="noreferrer noopener" href="https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-access-create-new-tenant"&gt;quickstart&lt;/a&gt; to create a new tenant.&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_overview.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_overview.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;The tenant overview&lt;/p&gt;

&lt;h2&gt;Registering a new app&lt;/h2&gt;

&lt;p&gt;On this page search for the &lt;em&gt;App registrations&lt;/em&gt; menu, click it to show the App registrations page.&lt;br&gt;After this we'll register a new app. So, click on &lt;em&gt;New registration&lt;/em&gt; to go to the app registration page. &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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_app_registration_new.png%3Fw%3D624" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_app_registration_new.png%3Fw%3D624" alt=""&gt;&lt;/a&gt;Menu &lt;em&gt;App registrations&lt;/em&gt; and &lt;em&gt;New registration&lt;/em&gt; menu.&lt;/p&gt;

&lt;p&gt;On the &lt;em&gt;Register an application&lt;/em&gt;, write a &lt;em&gt;Name&lt;/em&gt;, select the &lt;em&gt;Accounts in this organizational directory only&lt;/em&gt; and click on &lt;em&gt;Register&lt;/em&gt;.&lt;br&gt;After you click on &lt;em&gt;Register&lt;/em&gt;, you'll be redirected to the new app overview page.&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_register_app.png%3Fw%3D678" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_register_app.png%3Fw%3D678" alt=""&gt;&lt;/a&gt;Registering the new application&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_new_app_registration_overview.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_new_app_registration_overview.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;The new application - overview&lt;/p&gt;

&lt;h2&gt;Client secrets&lt;/h2&gt;

&lt;p&gt;Now on this page, we'll go to the &lt;em&gt;Certificates &amp;amp; secrets&lt;/em&gt; menu. Clicking on the menu, a screen will appear and we'll see &lt;em&gt;Certificates&lt;/em&gt; and &lt;em&gt;Client secrets&lt;/em&gt; below. On &lt;em&gt;Client secrets&lt;/em&gt;, click on &lt;em&gt;New client secret&lt;/em&gt; to open a window to register a new client secret.&lt;br&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_client_secrets_new.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_client_secrets_new.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Write a &lt;em&gt;Description&lt;/em&gt; (optional), choose an &lt;em&gt;Expires&lt;/em&gt;, and click on &lt;em&gt;Add&lt;/em&gt;. After this new client secrets will appear on the table below. &lt;br&gt;Copy the &lt;em&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/em&gt; and save it, because after you won't be able to see the value again.&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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_client_secrets_created_copy_value.png%3Fw%3D984" 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%2Fandremoriya.files.wordpress.com%2F2021%2F02%2Fazure_ad_client_secrets_created_copy_value.png%3Fw%3D984" alt=""&gt;&lt;/a&gt;Save the &lt;em&gt;Value&lt;/em&gt; and &lt;em&gt;ID&lt;/em&gt;, we need this information later. Now that you have done it,  we need to configure the keycloak.&lt;/p&gt;

&lt;h1&gt;Configuring keycloak&lt;/h1&gt;

&lt;p&gt;Now we need to configure the keycloak. &lt;br&gt;First, we'll create a realm, but if you already have a realm, go to the &lt;em&gt;Configuring an Identity Providers&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Creating a realm&lt;/h2&gt;

&lt;p&gt;If you don't have yet a realm, It is easy to create a realm in keycloak. &lt;br&gt;In the left menu, above &lt;strong&gt;Configure&lt;/strong&gt;, pass the mouse over the &lt;em&gt;realm name&lt;/em&gt; and click in &lt;strong&gt;Add realm&lt;/strong&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fcreate_realm1-edited.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fcreate_realm1-edited.png"&gt;&lt;/a&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fadd_realm-2.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fadd_realm-2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just type a name and click on &lt;strong&gt;Create.&lt;/strong&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-1.png%3Fw%3D991" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-1.png%3Fw%3D991" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Configuring a &lt;em&gt;Identity Providers&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;On the left menu, go to the &lt;strong&gt;Identity Providers&lt;em&gt; &lt;/em&gt;&lt;/strong&gt;menu.&lt;br&gt;On &lt;em&gt;Add provider&lt;/em&gt;, select the &lt;em&gt;OpenID connect V1.0&lt;/em&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_add.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_add.png"&gt;&lt;/a&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_add_oidc-1.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_add_oidc-1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After this, the window &lt;em&gt;Add identity provider&lt;/em&gt; will open.&lt;br&gt;&lt;br&gt;Type an &lt;em&gt;Alias&lt;/em&gt;, and a &lt;em&gt;Display Name&lt;/em&gt; if you want. After, Go to the &lt;strong&gt;Import External IDP Config&lt;/strong&gt;, and see the &lt;em&gt;Import from URL&lt;/em&gt; field.&lt;br&gt;Now we need to back to the Azure AD, access the application on &lt;em&gt;App registration&lt;/em&gt;, and see the &lt;em&gt;&lt;strong&gt;Endpoints.&lt;/strong&gt;&lt;/em&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fazure_ad_new_app_registration_overview.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fazure_ad_new_app_registration_overview.png"&gt;&lt;/a&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fendpoints.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fendpoints.png"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Copy the &lt;em&gt;OpenID Connect metadata document&lt;/em&gt; information and back to the keycloak.&lt;br&gt;&lt;br&gt;In &lt;em&gt;Import for URL&lt;/em&gt; paste the metadata copied above, and click on the &lt;em&gt;Import&lt;/em&gt; button.&lt;br&gt;&lt;br&gt;That done, some settings must appear in &lt;em&gt;OpenID Connect Config&lt;/em&gt; as shown in the image below&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_oidc_conect_config.png%3Fw%3D722" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_oidc_conect_config.png%3Fw%3D722" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now see these last three fields in the image above. We need to fill the &lt;em&gt;Client ID&lt;/em&gt; and &lt;em&gt;Client Secret&lt;/em&gt; fields with the &lt;em&gt;Certificates &amp;amp; secrets&lt;/em&gt;, registered in the Azure.&lt;br&gt;The &lt;strong&gt;Client Authentication&lt;/strong&gt; field, choose the &lt;em&gt;Client secret sent as post&lt;/em&gt;. &lt;br&gt;The &lt;strong&gt;Client ID&lt;/strong&gt; field, go to the Azure, &lt;em&gt;App registration&lt;/em&gt;, select the application. In the application &lt;em&gt;Overview&lt;/em&gt;, look at the &lt;strong&gt;Application (Client) ID&lt;/strong&gt; and copy this value. Back to the keycloak, and paste the information in the field.&lt;br&gt;The &lt;strong&gt;Client secret&lt;/strong&gt; field, do you remember that we need to save some information in the &lt;em&gt;Client secret&lt;/em&gt; section in this post? So we need the client secret &lt;em&gt;Value&lt;/em&gt;, get this value and paste into the field.&lt;br&gt;&lt;br&gt;Once this is done, the settings should look like the image below:&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_oidc_config_save.png%3Fw%3D714" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_oidc_config_save.png%3Fw%3D714" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;Now save it and go to the top page, and copy the &lt;strong&gt;Redirect URI.&lt;/strong&gt; This information we need to use in the azure.&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_redirect_uri.png%3Fw%3D740" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_identity_provider_redirect_uri.png%3Fw%3D740" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After those configurations, back to azure again to the last configurations.&lt;/p&gt;

&lt;h2&gt;Configure the &lt;em&gt;Authentication&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Now back to the Azure, and go to &lt;strong&gt;Azure Active Directory&lt;/strong&gt; &amp;gt; &lt;strong&gt;App registration&lt;/strong&gt; &amp;gt; application &amp;gt; &lt;strong&gt;Authentication&lt;/strong&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fmenu_authentication-1.png%3Fw%3D239" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fmenu_authentication-1.png%3Fw%3D239" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Platform configurations&lt;/em&gt; will appear, click on the &lt;strong&gt;Add a platform&lt;/strong&gt; button as the image below&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fazure_ad_app_authentication.png%3Fw%3D966" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fazure_ad_app_authentication.png%3Fw%3D966" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we click, a window will appear on the right side. Select the &lt;strong&gt;Web&lt;/strong&gt; option.&lt;br&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fazure_ad_app_add_platform_web.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fazure_ad_app_add_platform_web.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now paste the &lt;strong&gt;Redirect URI&lt;/strong&gt;, copied in the last section, in the &lt;strong&gt;Redirect URIs&lt;/strong&gt; and click on &lt;strong&gt;Configure&lt;/strong&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-2.png%3Fw%3D550" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-2.png%3Fw%3D550" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this is done, the configuration should appear as in the image below.&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fredirect_uri_configured.png%3Fw%3D964" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fredirect_uri_configured.png%3Fw%3D964" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can test our application. &lt;br&gt;&lt;br&gt;So back to the keycloak, select the realm and go to menu &lt;strong&gt;Clients&lt;/strong&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_clients_test_auth.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fkeycloak_clients_test_auth.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click in the account's &lt;strong&gt;Base URL&lt;/strong&gt;. We will be redirected to the sign-in page as the imagem below.&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-3.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-3.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;In this example, I'm using version 12.0.4.RELEASE. Perhaps your page will be different.&lt;/p&gt;

&lt;p&gt;Click in &lt;strong&gt;Sign In&lt;/strong&gt; button, and We will be redirected to the sign-in form. See the &lt;em&gt;Or sign in with&lt;/em&gt; button. This button is our previously configured &lt;em&gt;Identity provider&lt;/em&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Flogin_azure.png%3Fw%3D485" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Flogin_azure.png%3Fw%3D485" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on this button, and we will be redirected to the Microsoft Sign-in form. Put your azure user (e-mail/username) and after your password.&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-4.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-4.png"&gt;&lt;/a&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fstay_signed_in.png" class="article-body-image-wrapper"&gt;&lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fstay_signed_in.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything went well, this page should appear.&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-5.png%3Fw%3D654" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-5.png%3Fw%3D654" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update some information and click on &lt;em&gt;Submit&lt;/em&gt;, you will be redirected to this page:&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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-6.png%3Fw%3D1024" 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%2Fandremoriya.files.wordpress.com%2F2021%2F04%2Fimage-6.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well that's it. I hope this post can help you.&lt;br&gt;&lt;br&gt;Send your feedback/suggestion and/or if you need some help, please contact me.&lt;br&gt;&lt;br&gt;Thank you very much and see you soon.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>keycloak</category>
      <category>idp</category>
      <category>security</category>
    </item>
  </channel>
</rss>
