<?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: Paladuta Stefan</title>
    <description>The latest articles on Forem by Paladuta Stefan (@kanames).</description>
    <link>https://forem.com/kanames</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%2F872896%2Fae0aa8fc-a75d-45f3-9677-23e31857de10.jpg</url>
      <title>Forem: Paladuta Stefan</title>
      <link>https://forem.com/kanames</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kanames"/>
    <language>en</language>
    <item>
      <title>Why encourage to use JSTL in your legacy projects over JSP scriptlet?</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Sun, 06 Aug 2023 11:58:40 +0000</pubDate>
      <link>https://forem.com/kanames/why-to-encourage-to-use-jstl-in-your-legacy-projects-over-jsp-scriptlet-48f4</link>
      <guid>https://forem.com/kanames/why-to-encourage-to-use-jstl-in-your-legacy-projects-over-jsp-scriptlet-48f4</guid>
      <description>&lt;p&gt;This article will be a short and will represent maybe just a memo on why you as Team Leader should impose (or encourage) to your team the use of JSTL or/and even migrate piece by piece your current JSP’s written with scriptlet into JSTL syntax.&lt;/p&gt;

&lt;p&gt;The arguments:&lt;/p&gt;

&lt;h2&gt;
  
  
  The human nature
&lt;/h2&gt;

&lt;p&gt;If we write or maintain the .jsp pages in scriptlet code, believe me when I say that because of stressful situations (deadlines on projects or on features) or maybe because of commodity lot of things will be done in dumb ways. When I say dumb ways I mean that you will end up after a lot of time with a tone of things in FrontEnd written in .jsp as scriptlet that for sure should have been done in BackEnd. An example that I always saw in my time is that a lot of collections are sent in FrontEnd and the developer constructs a complete new collection from 0 and even does some calculations on it (that aren’t advanced but for sure they have no place in FrontEnd in this architecture).&lt;/p&gt;

&lt;p&gt;Using jstl syntax is very limited (that’s the beauty) will impose to the developers to stop putting everything in FE and start thinking what should the BE provide already. Meanwhile the FE with the jstl will do small things in his limitation like iteration, conditional check, formatting some data, etc. nothing crazy that the classic scriptlet would have done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visually pleasant
&lt;/h2&gt;

&lt;p&gt;I don’t know about you but I never saw in my company on the legacy application (that is over 15 years) code written in .jsp that doesn’t do crazy stuff ([…] the worst I seen his connection to DB, recovery of data , transforming that data, displaying that data […]) and looks ugly. Instead after 1 years of putting my team to try to use jstl when possible some pages for us developers are now more clearer (even found old bugs).&lt;/p&gt;

&lt;p&gt;BAD:&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;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Count to 10 in JSP scriptlet&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;%
    for(int i=1;i&amp;lt;=10;i++)
    {%&amp;gt;
     &amp;lt;%=i%&amp;gt;&amp;lt;br/&amp;gt;
     &amp;lt;%
     }
     %&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NICE:&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;%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %&amp;gt;
&amp;lt;html&amp;gt;
 &amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;Count to 10 Example (using JSTL)&amp;lt;/title&amp;gt;
 &amp;lt;/head&amp;gt;

 &amp;lt;body&amp;gt;
  &amp;lt;c:forEach var="i" begin="1" end="10" step="1"&amp;gt;
   &amp;lt;c:out value="${i}" /&amp;gt;
   &amp;lt;br /&amp;gt;
  &amp;lt;/c:forEach&amp;gt;
 &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is the cost ?
&lt;/h2&gt;

&lt;p&gt;For you as developers ? nothing because we should know to do this, writing clean code instead of bad code shouldn’t even be an argument.&lt;/p&gt;

&lt;p&gt;For the client ? if we don’t have experience in JSTL well some patience.&lt;/p&gt;

&lt;p&gt;REMEMBER: Let the service layer have the business logic and determine what data the JSP needs.&lt;/p&gt;




&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

&lt;p&gt;Based on the number of claps I will know if writing some tricks about this old concept is still wanted.&lt;/p&gt;

&lt;p&gt;My main article: &lt;a href="https://medium.com/@stefan.paladuta17/why-to-encourage-to-use-jstl-in-your-legacy-projects-over-jsp-scriptlet-4dd36e95ce00"&gt;https://medium.com/@stefan.paladuta17/why-to-encourage-to-use-jstl-in-your-legacy-projects-over-jsp-scriptlet-4dd36e95ce00&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jstl</category>
      <category>java</category>
      <category>jsp</category>
      <category>idioms</category>
    </item>
    <item>
      <title>Bash | Why should you put shell variables always between quotation marks ? (+ real world example)</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Wed, 26 Jul 2023 10:32:09 +0000</pubDate>
      <link>https://forem.com/kanames/bash-why-should-you-put-shell-variables-always-between-quotation-marks-real-world-example-4gj1</link>
      <guid>https://forem.com/kanames/bash-why-should-you-put-shell-variables-always-between-quotation-marks-real-world-example-4gj1</guid>
      <description>&lt;p&gt;This memo will help you understand how using quotation marks around shell variables can help ensure that they are interpreted correctly and can help avoid unexpected behavior.&lt;/p&gt;

&lt;p&gt;You should put shell variables inside quotation marks to ensure that they are interpreted correctly by the shell. When you use a variable in a shell command or script without quotation marks, the shell will expand the variable, which means it will replace the variable with its value. This can cause problems if the variable contains spaces, special characters, or other characters that the shell interprets in a special way.&lt;/p&gt;

&lt;p&gt;By enclosing the variable in quotation marks, you tell the shell to treat the entire string as a single argument, even if it contains spaces or other special characters. This can prevent errors and unexpected behavior in your shell commands and scripts.&lt;/p&gt;

&lt;p&gt;For example, consider the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MYVAR="Hello World"
echo $MYVAR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without quotation marks, Bash will split the value of MYVAR into two separate words, "Hello" and "World", and treat them as separate arguments to echo, resulting in the output:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;However, if you put the variable in double quotes, 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;MYVAR="Hello World"
echo "$MYVAR"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire value of MYVAR is treated as a single argument to echo, resulting in the output:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Similarly, if your variable contains special characters such as asterisks or question marks, Bash will interpret them as globbing patterns and try to expand them into filenames in the current directory. This can lead to unexpected behavior or errors. Using quotes can prevent this behavior and ensure that the variable is treated as a literal string.&lt;/p&gt;

&lt;p&gt;Therefore, it is generally a good practice to always put your shell variables inside double quotes unless you have a specific reason not to.&lt;/p&gt;

&lt;h1&gt;
  
  
  Real world example of bad management of quotation in shell scripting.
&lt;/h1&gt;

&lt;p&gt;Consider the following scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EX_VARIABLE="24/22/2021"
SQL_MSG=`sqlplus -s &amp;lt;user&amp;gt;/&amp;lt;pwd&amp;gt;@&amp;lt;db&amp;gt; &amp;lt;&amp;lt;-EOF
   whenever SQLERROR EXIT SQL.SQLCODE ROLLBACK;
   whenever OSERROR  EXIT SQL.SQLCODE ROLLBACK;

   select to_date('${EX_VARIABLE}','dd/mm/yyyy') from dual;

EOF`
if [ $? -eq 0 ]; then
   echo "OK";
else
   echo ${SQL_MSG}
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The objective of this shell script is to check if the conversion from the string representation of a date (stored in the EX_VARIABLE variable) is working properly by evaluating whether it is a valid date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ./sh_example.sh

select to_date('24/22/2021','dd/mm/yyyy') from dual bin boot dev 
docker-entrypoint-initdb.d etc home lib lib64 media mnt 
opt proc root run sbin sh_example sh_example.sh srv sys tmp u01 
usr var ERROR at line 1: ORA-01843: not a valid month
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2apGPSmb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkctq5717jsqh9jvkrtq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2apGPSmb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkctq5717jsqh9jvkrtq.jpg" alt="Image description" width="800" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, due to the lack of quotation marks around the SQL_MSG variable in the echo statement, the output includes extraneous information, such as the names of all the files in the current directory and if we check the content of the path where the shell is present:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IopqOgmE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmmi48x8xvbuk3oqh4jg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IopqOgmE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmmi48x8xvbuk3oqh4jg.jpg" alt="Image description" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we can see that the junk in fact represents all the files and logs from that specific folder !&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bin&lt;/li&gt;
&lt;li&gt;boot&lt;/li&gt;
&lt;li&gt;dev&lt;/li&gt;
&lt;li&gt;docker-entrypoint-initdb.d&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;li&gt;var&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reason of the behaviour
&lt;/h2&gt;

&lt;p&gt;If we revisit the shell code again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EX_VARIABLE="24/22/2021"
SQL_MSG=`sqlplus -s &amp;lt;user&amp;gt;/&amp;lt;pwd&amp;gt;@&amp;lt;db&amp;gt; &amp;lt;&amp;lt;-EOF
   whenever SQLERROR EXIT SQL.SQLCODE ROLLBACK;
   whenever OSERROR  EXIT SQL.SQLCODE ROLLBACK;

   select to_date('${EX_VARIABLE}','dd/mm/yyyy') from dual;

EOF`
if [ $? -eq 0 ]; then
   echo "OK";
else
   echo "${SQL_MSG}" #This was the only line of code changed
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but this time we are going to rewrite the line “echo ${SQL_MSG}”, more specific the variabile ${SQL_MSG} with quotation marks and run the shell again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root@9ea9fad92c38:/# ./sh_example.sh
select to_date('24/22/2021','dd/mm/yyyy') from dual
               *
ERROR at line 1:
ORA-01843: not a valid month
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SWM5u3ml--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r02we640k6s9ma59t2ga.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SWM5u3ml--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r02we640k6s9ma59t2ga.jpg" alt="Image description" width="800" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we can see that this time it worked but what happened ?&lt;/p&gt;

&lt;p&gt;Because the quotation marks were missing my theory is that the echo command tried to do echo of each of the lines that we see in the output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;echo select to_date(‘24/22/2021’,’dd/mm/yyyy’) from dual&lt;/li&gt;
&lt;li&gt;echo * &amp;lt;- and echo * actually is a command that returns you the list of all the files and folder from the current directoy so the junk that we saw in red is actually the result of this command&lt;/li&gt;
&lt;li&gt;echo ERROR at line 1:&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

&lt;p&gt;Original post: &lt;a href="https://medium.com/@stefan.paladuta17/bash-why-should-you-put-shell-variables-always-between-quotation-marks-real-world-example-ac794dd53a84"&gt;https://medium.com/@stefan.paladuta17/bash-why-should-you-put-shell-variables-always-between-quotation-marks-real-world-example-ac794dd53a84&lt;/a&gt;&lt;/p&gt;

</description>
      <category>shell</category>
      <category>bash</category>
      <category>code</category>
      <category>practice</category>
    </item>
    <item>
      <title>SWAGGER | Bye Bye swagger specifications and welcome OpenAPI specifications (springfox implementation v3 gone wrong)</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Sat, 15 Jul 2023 10:54:15 +0000</pubDate>
      <link>https://forem.com/kanames/swagger-bye-bye-swagger-specifications-and-welcome-openapi-specifications-springfox-implementation-v3-gone-wrong-19ol</link>
      <guid>https://forem.com/kanames/swagger-bye-bye-swagger-specifications-and-welcome-openapi-specifications-springfox-implementation-v3-gone-wrong-19ol</guid>
      <description>&lt;p&gt;The main article that bundles all together and redirects to different features that you can implement in swagger UI is present here: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article I am going to present what the implementation of springfox v3 (that is complain with OpenAPI specifications) brings to the table.&lt;/p&gt;

&lt;p&gt;The article will be divided in the following chapters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chapter 1 Introduce the feature in your project.&lt;/li&gt;
&lt;li&gt;Chapter 2 Is there a need for annotation to enable OAS 3.0 ?&lt;/li&gt;
&lt;li&gt;Chapter 3 Disable for production environment swagger.&lt;/li&gt;
&lt;li&gt;Chapter 4 Problems with the 3rd version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before starting here are some link(s) that you may be interested in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Repository of springfox: &lt;a href="https://github.com/springfox/springfox"&gt;https://github.com/springfox/springfox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Release notes for the version3: &lt;a href="https://newreleases.io/project/github/springfox/springfox/release/3.0.0"&gt;https://newreleases.io/project/github/springfox/springfox/release/3.0.0&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Chapter 1 Introduce the feature in your project
&lt;/h1&gt;

&lt;p&gt;Step 1 Introduce the dependency in your spring boot project (in pom.xml):&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;io.springfox&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;springfox-boot-starter&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.0.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2 Creating a Controller , a Dto and a config class to store the Docket Bean&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Tk_bBnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x17jxg94ejfn47slose.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Tk_bBnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x17jxg94ejfn47slose.png" alt="Image description" width="532" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.annotations.Api;
import ro.stefan.dto.Book;

@RestController
@Api(tags = "Book Controller")
public class BookController {

    @GetMapping("/books")
    public List&amp;lt;Book&amp;gt; getBooks(){
        return new ArrayList&amp;lt;Book&amp;gt;();
    }

    @GetMapping("/ping")
    public String ping() {
        return "pong";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the dto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Book {
    private String title;

    private String author;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

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

&lt;/div&gt;



&lt;p&gt;the configuration docket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.HashSet;
import java.util.Set;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RestController;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {

    @Bean
    public Docket getDocketInstanceEx1() {
        final Set&amp;lt;String&amp;gt; produces = new HashSet&amp;lt;String&amp;gt;();
        produces.add(MediaType.APPLICATION_JSON_VALUE);
        produces.add(MediaType.APPLICATION_XML_VALUE);

        return new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("Note API")
                        .description("A CRUD API to demonstrate Springfox 3 integration")
                        .version("0.0.1")
                        .license("MIT")
                        .licenseUrl("https://opensource.org/licenses/MIT")
                        .build())
                .produces(produces).consumes(produces)
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                .build();
    }

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Step 3 Access to the generated OpenAPI
&lt;/h1&gt;

&lt;p&gt;Location: &lt;a href="http://localhost:"&gt;http://localhost:&lt;/a&gt;/v3/api-docs and the result is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c3bkpVHu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nolxa1r91fr58g2s8pw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c3bkpVHu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nolxa1r91fr58g2s8pw5.png" alt="Image description" width="800" height="952"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This version of springfox implementation fills a lot of gaps that another project called &lt;u&gt;&lt;strong&gt;springdoc-openapi&lt;/strong&gt;&lt;/u&gt; had addressed for a long time.&lt;/p&gt;

&lt;p&gt;Before going further I will remind everybody that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;OpenAPI Specification (formerly Swagger Specification)&lt;/strong&gt; is an API description format for REST APIs. An OpenAPI file allows you to describe your entire API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swagger&lt;/strong&gt; is a set of open-source tools built around the OpenAPI Specification that can help you design, build, document and consume REST APIs.&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  Chapter 2 Is there a need for annotation to enable OAS 3.0 ?
&lt;/h1&gt;

&lt;p&gt;This question is actually thanks to &lt;a href="https://www.springcloud.io/post/2022-02/springboot-swagger3/#gsc.tab=0"&gt;https://www.springcloud.io/post/2022-02/springboot-swagger3/#gsc.tab=0&lt;/a&gt; that explains the fact why some tutorials guide you to add the annotation &lt;em&gt;&lt;strong&gt;@EnableOpenApi&lt;/strong&gt;&lt;/em&gt; to enable OpenAPI. Actually is wrong (or useless) and actually if you already have a workable project with this annotation, just remove it and tell me the contrary. But why ? because if you go into the jar &lt;strong&gt;springfox-boot-starter-3.0.0.jar&lt;/strong&gt; you can find a &lt;strong&gt;spring.factories.&lt;/strong&gt; Opening the file (.jar):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f-eLqf9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9s1wlsmd4rn4rolz3qg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f-eLqf9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9s1wlsmd4rn4rolz3qg.png" alt="Image description" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the following content is presented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
springfox.boot.starter.autoconfigure.OpenApiAutoConfiguration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: For people not familiar with Spring Boot this is a Spring Boot-specific SPI file that automatically discovers and registers the configuration of the Starter component.&lt;/p&gt;

&lt;p&gt;And if you use your eclipse (with JadClipse — decompiler) to look inside the jar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PMUtf8Bm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6uysdfr8jg9w9z1jfy2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PMUtf8Bm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6uysdfr8jg9w9z1jfy2.png" alt="Image description" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we can find in the class: &lt;strong&gt;OpenApiAutoConfiguration&lt;/strong&gt; with the piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ConditionalOnProperty(value = “springfox.documentation.enabled”, havingValue = “true”, matchIfMissing = true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that makes the annotation &lt;strong&gt;@EnableOpenApi&lt;/strong&gt; uselless, because the interface that represents the annotation is importing this class &lt;strong&gt;OpenApiDocumentationConfiguration.class&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Import(OpenApiDocumentationConfiguration.class)
public @interface EnableOpenApi {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that already activates swagger by default.&lt;/p&gt;




&lt;h1&gt;
  
  
  Chapter 3 Disable for production environment swagger
&lt;/h1&gt;

&lt;p&gt;NOTE: This is not a feature really of v3, but actually a trick using the previous chapter.&lt;/p&gt;

&lt;p&gt;Imagine that if you are like me a developer working in a company your software will go through multiple environments: DEVELOPING, TESTING, UAT (User Acceptance Tests), PRODUCTION (just as example) and we for sure don’t want in PRODUCTION to permit the Spring Boot project to generate a Swagger-UI (not always but in my case yes).&lt;/p&gt;

&lt;p&gt;For sure this is possible and quite simple if you read my previous Chapter 2 you have seen that we found a class called: &lt;strong&gt;OpenApiDocumentationConfiguration.class&lt;/strong&gt; that we know is responsible to enable or disabled swagger-ui (by default it’s ON), to turn it OFF we simply must go to our application properties or yaml (depends what we choose to have in our spring boot app) and write the following config if you are using .yaml format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;springfox:
  documentation:
    enabled: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or this format if you are using .properties format&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;springfox.documentation.enabled=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that’s all, now the url to swagger-ui will not work anymore.&lt;/p&gt;




&lt;h1&gt;
  
  
  Chapter 4 Problems with the 3rd version
&lt;/h1&gt;

&lt;p&gt;Even if I’m very dear to swagger I think it was some very big problems regarding code pollution that I hope I have time to write an article about. I wanted to show you guys a lot of new feature that SpringFox implementation brings with the OpenAPI specifications but sadly most of them are buggy or are done wrong, an example is the concept of multiple servers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y3pK5l4U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv67szg1tzhw6r0ekdvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y3pK5l4U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv67szg1tzhw6r0ekdvt.png" alt="Image description" width="391" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As many things this feature is buggy and not working properly: &lt;a href="https://github.com/springfox/springfox/issues/3483"&gt;https://github.com/springfox/springfox/issues/3483&lt;/a&gt; and we waited for too long for such a simple feature to be working again. With other words in the next weeks I will be more focus on displaying some alternatives to SpringFox. If I will discover new stuff I will keep this page updated.&lt;/p&gt;

&lt;p&gt;Second problem is the lack of transparency. A lot of milestone was set on this project but none of them presented for you as consumer a release date thus making you feel unsecure regarding what to do, to wait or not ? Sadly it’s clear that we as developers can’t wait and we must go forward with projects that are more active like spring-doc (that I will cover in future articles).&lt;/p&gt;

&lt;p&gt;Third problem that scared me is the number of things I did on old microservices projects (SpringBoot 2.6.0) because OAS 3.0 from springfox didn’t work, more details can be found here: &lt;a href="https://stackoverflow.com/questions/70178343/springfox-3-0-0-is-not-working-with-spring-boot-2-6-0"&gt;https://stackoverflow.com/questions/70178343/springfox-3-0-0-is-not-working-with-spring-boot-2-6-0&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;NOTE: This is my personal opinion and should be taken as being just a view on the project springfox. Again this project is dear to me and I really wanted to talk about it a lot but I want to deliver more value, not to wait for miracles.&lt;/p&gt;

&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

&lt;p&gt;Original post: &lt;a href="https://medium.com/@stefan.paladuta17/swagger-spring-boot-bye-bye-swagger-specifications-and-welcome-openapi-specifications-7eab7e68d6d7"&gt;https://medium.com/@stefan.paladuta17/swagger-spring-boot-bye-bye-swagger-specifications-and-welcome-openapi-specifications-7eab7e68d6d7&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swagger</category>
      <category>openapi</category>
      <category>springboot</category>
      <category>spring</category>
    </item>
    <item>
      <title>Spring Boot | Using SWAGGER at maximum — All annotations that we should know about in springfox implementation</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Sat, 15 Jul 2023 08:19:15 +0000</pubDate>
      <link>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-all-annotations-that-we-should-know-about-in-springfox-implementation-57a1</link>
      <guid>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-all-annotations-that-we-should-know-about-in-springfox-implementation-57a1</guid>
      <description>&lt;h2&gt;
  
  
  The main article that bundles all together and redirect to different features that you can implement in swagger UI is present here: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this article I am going to show the most important annotations I used from the springfox implementation starting on the swagger version2 specifications.&lt;/p&gt;

&lt;p&gt;The article will be divided in the following chapters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chapter: @Api annotation&lt;/li&gt;
&lt;li&gt;Chapter: @ApiOperation annotation&lt;/li&gt;
&lt;li&gt;Chapter: @ApiModel annotation&lt;/li&gt;
&lt;li&gt;Chapter: @ApiModelProperty annotation&lt;/li&gt;
&lt;li&gt;Chapter: @ApiIgnore&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Chapter: @Api annotation
&lt;/h1&gt;

&lt;p&gt;If you ever find a tutorial that tells you apply the following snippet of code and everything will work smooth as butter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
@RestController
@Api( description = "Book controller description | Api Annotation")
public class BookController {

   @GetMapping("/books")
   public List&amp;lt;Book&amp;gt; getBooks(){
     return new ArrayList&amp;lt;Book&amp;gt;();
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;well wrong. If you follow me and my articles you know that I am a big advocate of creating tutorial materials AND maintaining them up to date as much as possible, as we don’t need more junk on internet but we actually need to filter them and make them better.&lt;/p&gt;

&lt;p&gt;So going back to the problem. The lovely description attribute of the annotation @Api used for adding a description has been deprecated. By default, swagger api generates an empty description for the REST API class name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E8A-sCRm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1nhteo2vi28s7todj25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E8A-sCRm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1nhteo2vi28s7todj25.png" alt="Image description" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now in present this attribute “description”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8-uMis6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vrmpke6h64i72t9ubtfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8-uMis6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vrmpke6h64i72t9ubtfw.png" alt="Image description" width="580" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what is the solution ? Simple, the attribute tags. Example of using the tags attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;....
@RestController
@Api( tags = "Book controller description | Api Annotation")
public class BookController {

   @GetMapping("/books")
   public List&amp;lt;Book&amp;gt; getBooks(){
     return new ArrayList&amp;lt;Book&amp;gt;();
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FeE5zVKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzz1qsazvkp9i30qqh70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FeE5zVKK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzz1qsazvkp9i30qqh70.png" alt="Image description" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are there limits and/or tips&amp;amp;tricks you can use ? Well, based on my tests:&lt;/p&gt;

&lt;p&gt;Tip&amp;amp;Trick: We can add emojis (:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.....
@RestController
@Api( tags = "Secret 📚 endpoints")
public class BookController {
   @GetMapping("/books")
   public List&amp;lt;Book&amp;gt; getBooks(){
      return new ArrayList&amp;lt;Book&amp;gt;();
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Limit: We can’t abuse the number of characters that we write in the tags value, so take care please.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OTpHQrNT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3l6jy42tdhaszm00216.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OTpHQrNT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3l6jy42tdhaszm00216.png" alt="Image description" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tip&amp;amp;Trick: The attribute can actually accept an array of tags (strings) and put the same endpoint in multiple points&lt;/p&gt;

&lt;p&gt;Example of the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package ro.stefan.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import ro.stefan.dto.Book;
@RestController
@Api( tags = {"books","store","something else"})
public class BookController {

 @GetMapping("/books")
public List&amp;lt;Book&amp;gt; getBooks(){
  return new ArrayList&amp;lt;Book&amp;gt;();
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FE43TAhh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qj1jmelxv62woqp7erku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FE43TAhh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qj1jmelxv62woqp7erku.png" alt="Image description" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Chapter: @ApiOperation annotation
&lt;/h1&gt;

&lt;p&gt;You could further customize the description at an operation level by using @ApiOperation annotation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@RestController
@Api( tags = "Book Store | API annotation")
public class BookController {

 @ApiOperation(value = "Recover the collection of all books from the store | API Operation annotation")
 @GetMapping("/books")
 public List&amp;lt;Book&amp;gt; getBooks(){
  return new ArrayList&amp;lt;Book&amp;gt;();
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NeUVTA17--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/loq9bxus66fha8cr3yjh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NeUVTA17--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/loq9bxus66fha8cr3yjh.png" alt="Image description" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Chapter: @ApiModel
&lt;/h1&gt;

&lt;p&gt;@ApiModel is an annotation used to enhance the resource model description. We can use @ApiModel for the entire model class.&lt;/p&gt;

&lt;p&gt;snippet of some code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import io.swagger.annotations.ApiModel;

@ApiModel(description = "Model retrieved from library system")
public class Book {
  private String title;
  private String author;

  public String getTitle() {
    return title;
  }
  public void setTitle(String title) {
    this.title = title;
  }

  public String getAuthor() {
    return author;
   }
  public void setAuthor(String author) {
    this.author = author;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LSJI0hVq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wqfkxtaz9wxct3d06vo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LSJI0hVq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wqfkxtaz9wxct3d06vo.png" alt="Image description" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6C5PFThC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r91adu1jr6lmzp45kmka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6C5PFThC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r91adu1jr6lmzp45kmka.png" alt="Image description" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Chapter: @ApiModelProperty
&lt;/h1&gt;

&lt;p&gt;@ApiModelProperty like @ApiModel is used enhance the resource model description but in this case for the individual attributes of the model class.&lt;/p&gt;

&lt;p&gt;Snippet of some code (also with the @ApiModel annotation from previous chapter):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(description = "Model retrieved from library system")
public class Book {

  @ApiModelProperty(notes = "Title of the book", example = "Inside of this hell")
  private String title;

  @ApiModelProperty(notes = "Author of the book", example = "Stefan P.")
  private String author;

  public String getTitle() {
    return title;
  }
  public void setTitle(String title) {
    this.title = title;
  }
  public String getAuthor() {
    return author;
  }
  public void setAuthor(String author) {
    this.author = author;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0v2BwCNQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ouqpxbq18er78x4rv0s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0v2BwCNQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ouqpxbq18er78x4rv0s4.png" alt="Image description" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After (also with the @ApiModel annotation from previous chapter):&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7gz44G1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9zklnbpvjdj83g6hmav7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7gz44G1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9zklnbpvjdj83g6hmav7.png" alt="Image description" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Chapter: @ApiIgnore
&lt;/h1&gt;

&lt;p&gt;Let’s say that you have a project and like every new project when you build it you construct an endpoint that must act as test, to see if the base code is working if the C.I./C.D. is fine etc. Over the years I found a lot of endpoints made with this reason that remained until deploy in production. Honestly (in present with my current experience) I think they are very good to have.&lt;br&gt;
An example of what I currently use is an endpoint called /ping that displays the up time of the microservices, the libraries used inside and their versions.&lt;/p&gt;

&lt;p&gt;For this example I use the following controller:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YTnfiy----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idprtfhy8wk0f65makjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YTnfiy----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idprtfhy8wk0f65makjm.png" alt="Image description" width="800" height="325"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ro.stefan.dto.Book;
import springfox.documentation.annotations.ApiIgnore;

@RestController
@Api( tags = "Book Store | API annotation")
public class BookController {

  @ApiOperation(value = "Recover the collection of all books from the store | API Operation annotation.")
  @GetMapping("/books")
  public List&amp;lt;Book&amp;gt; getBooks(){
    return new ArrayList&amp;lt;Book&amp;gt;();
  }

  @ApiIgnore 
  @GetMapping("/ping")
  public String ping() {
    return "pong";
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with a simple method /ping that just returns a pong string. So after applying (uncomment) the code we can see that the interface swagger-ui displays nothing regarding /ping&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e2P8WYav--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2g4rtyfj4mp35893pgx0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e2P8WYav--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2g4rtyfj4mp35893pgx0.png" alt="Image description" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;but if we call the endpoint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oJtZ1-kt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vkuspe4dnxd88n93s7qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oJtZ1-kt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vkuspe4dnxd88n93s7qk.png" alt="Image description" width="289" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it exists so this is a success we as developers know a secret endpoint ;). And nobody that is consuming our contract (reading the swagger-ui) will know (normally speaking).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: There are many other annotations offered by Spring but in reality this are the ones that I want to focus on because they are the most common ones you will ever see in projects if not more than you will ever see for version 2 of the swagger specifications. The next step is not to learn more annotations on this example/series but to move to the next version (v3 focused on OpenAPI object).&lt;/p&gt;

&lt;p&gt;If you want my code you can find it here: &lt;a href="https://github.com/Kanames/SpringBoot-SwaggerExamples"&gt;https://github.com/Kanames/SpringBoot-SwaggerExamples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

&lt;p&gt;My original article: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-all-annotations-that-we-should-know-about-in-springfox-e419e575b078"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-all-annotations-that-we-should-know-about-in-springfox-e419e575b078&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>spring</category>
      <category>swagger</category>
      <category>openapi</category>
    </item>
    <item>
      <title>Spring Boot | Using SWAGGER at maximum — Docket advanced details</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Sat, 08 Jul 2023 19:21:46 +0000</pubDate>
      <link>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-docket-advanced-details-1a1o</link>
      <guid>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-docket-advanced-details-1a1o</guid>
      <description>&lt;p&gt;The main article that bundles all together and redirect to different features that you can implement in swagger UI is present here: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article I am going to show how to populate in more detail the Docket object used to generate the SWAGGER-UI that we all appreciate and use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chapter: Producing and Consuming&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Chapter: Adding extra models&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Chapter: Global request parameters default&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Chapter: Global response default&lt;/strong&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Chapter 1 Producing and Consuming
&lt;/h1&gt;

&lt;p&gt;Producing and consuming actions are two details that I personally appreciate when I see them in projects. It’s very nice and helpful when you see a documentation regarding an API that tells you as consumer what form of response it can give you: &lt;strong&gt;json&lt;/strong&gt;, &lt;strong&gt;xml&lt;/strong&gt;, &lt;strong&gt;custom response&lt;/strong&gt;, etc. and what form of information you need to send, thus making the experience more valuable.&lt;/p&gt;

&lt;p&gt;To set what is the API producing and consuming we can see the methods &lt;em&gt;.produces()&lt;/em&gt; and &lt;em&gt;.consumes()&lt;/em&gt; on the Docket object. These two methods expect from you, a collection of type Set of what forms will the application accept/offer. In case you are wondering why Set collection, you just need to simply remember: “A Set is a Collection that cannot contain duplicate elements.” which with other words means the UI should render only unique forms thus a Set is perfect for this case.&lt;/p&gt;

&lt;p&gt;A basic example of the entire class with the Docket object populated for consuming:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
public class SpringFoxConfig {

 @Bean
 public Docket getDocketInstance() {
  final Set&amp;lt;String&amp;gt; produces = new HashSet&amp;lt;String&amp;gt;();
  produces.add(MediaType.APPLICATION_JSON_VALUE);
  produces.add(MediaType.APPLICATION_XML_VALUE);
  produces.add("Stefan's custom mapping value");

  return new Docket(DocumentationType.SWAGGER_2)
    .produces(produces)
    .select()
    .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
    .paths(PathSelectors.any())
    .build();
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: produces.add(“Stefan’s custom mapping value”); it’s here just to prove the concept that it’s just a string applied on that collection + you shouldn’t normally go outside of the standard defined MIME formats.&lt;/p&gt;

&lt;p&gt;Before applying the changes:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rejsDKYt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcuki39jlxxl0fzfv8em.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rejsDKYt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcuki39jlxxl0fzfv8em.png" alt="Docket configured without any consumer or producer type" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After applying the changes:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tHX4oG82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrj28s1ff1sm1lr1qafj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tHX4oG82--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jrj28s1ff1sm1lr1qafj.png" alt="Docket configured without any consumer only" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do this ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because as mentioned already an API can accept and return data in different formats (json, xml, etc.) so we can useconsumes and produces to specify the MIME types understood by your API. To set the consumes and produces type is easy and just represents an array of MIME type.&lt;br&gt;
This modification as presented in the examples are done globally so that means that all controllers from that spring boot project will render this but you can override this value at API level (method from the controller) if you have exceptions.&lt;/p&gt;

&lt;p&gt;Important note: “Note that consumes only affects operations with a request body, such as POST, PUT and PATCH.” — swagger.io&lt;/p&gt;

&lt;p&gt;What MIME type we can use ?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;application/json&lt;/li&gt;
&lt;li&gt;application/xml&lt;/li&gt;
&lt;li&gt;application/x-www-form-urlencoded&lt;/li&gt;
&lt;li&gt;multipart/form-data&lt;/li&gt;
&lt;li&gt;text/plain; charset=utf-8&lt;/li&gt;
&lt;li&gt;text/html&lt;/li&gt;
&lt;li&gt;application/pdf&lt;/li&gt;
&lt;li&gt;image/png
etc...&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  Chapter 2 — Adding extra models
&lt;/h1&gt;

&lt;p&gt;“A key feature offered by Springfox that was very appealing for reverse-engineering/retrofitting an existing Spring Boot microservice to generate an OAS was the ability to ad-hoc pick up POJOs and have a schema generated for it.” — &lt;a href="https://github.com/springdoc/springdoc-openapi/issues/415"&gt;https://github.com/springdoc/springdoc-openapi/issues/415&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I put the following quote because it expresses very simple the current chapter. Adding extra models in the SWAGGER-UI is actually a thing that I saw being used very often by other teams.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Autowired
private TypeResolver typeResolver;

@Bean
public Docket getDocketInstanceEx1() {
    final Set&amp;lt;String&amp;gt; produces = new HashSet&amp;lt;String&amp;gt;();
    produces.add(MediaType.APPLICATION_JSON_VALUE);
    produces.add(MediaType.APPLICATION_XML_VALUE);

    return new Docket(DocumentationType.SWAGGER_2)
            .produces(produces)
            .consumes(produces)
            .additionalModels(typeResolver.resolve(Author.class))
            .select()
            .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
            .paths(PathSelectors.any())
            .build();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NOTE: Personally I never had a reason to do this but only because I didn’t have a reason or opportunity it doesn’t mean it’s useless I just never had the chance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vRWrOSB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/urjra6b42276fhn2tnot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vRWrOSB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/urjra6b42276fhn2tnot.png" alt="The swagger-ui presented with an extra Model called Author that isn’t part of any controller" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why would you this ?&lt;/p&gt;

&lt;p&gt;Based on my reason I just found the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;This issue: &lt;a href="https://github.com/springdoc/springdoc-openapi/issues/415"&gt;https://github.com/springdoc/springdoc-openapi/issues/415&lt;/a&gt; that explain that the desire to add extra models is to generate a bigger open API json. I wanted to simply generate the Open API spec yaml/json as a baseline with the existing Spring Boot controllers, but then manually write up summaries, descriptions, response types, and return types in the yaml itself. My primary use case here is for large existing microservices that weren’t built-out with an Open API or API driven development mindset. (Also, the return types of our controllers are almost always Strings because we serialize manually with GSON as opposed to Jackson w/ Spring, but I think swagger-core provides annotations that resolve this anyway)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other teams/projects do this because they have old systems where the controller returns a generic String that represents an object in json format.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Chapter 3 — Global request parameters default
&lt;/h1&gt;

&lt;p&gt;The method: .globalRequestParameters() is one of the most useful features we have in Docket. It allows you to add for all requests (all endpoints of the spring boot project) written in all controllers a parameter that can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query parameter&lt;/li&gt;
&lt;li&gt;Header attribute&lt;/li&gt;
&lt;li&gt;Cookie&lt;/li&gt;
&lt;li&gt;Path&lt;/li&gt;
&lt;li&gt;Form&lt;/li&gt;
&lt;li&gt;Body&lt;/li&gt;
&lt;li&gt;Form Data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Values extracted from the springfox.documentation.service.ParameterType enum.&lt;/p&gt;

&lt;p&gt;Example with header attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package ro.stefan.config;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

import com.fasterxml.classmate.TypeResolver;

import ro.stefan.dto.Author;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.RequestParameterBuilder;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.ParameterType;
import springfox.documentation.service.RequestParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {  
  @Autowired
    private TypeResolver typeResolver;

    @Bean
    public Docket getDocketInstanceEx1() {
        final Set&amp;lt;String&amp;gt; produces = new HashSet&amp;lt;String&amp;gt;();
        produces.add(MediaType.APPLICATION_JSON_VALUE);
        produces.add(MediaType.APPLICATION_XML_VALUE);

        List&amp;lt;RequestParameter&amp;gt; listRequestParamters = new ArrayList&amp;lt;RequestParameter&amp;gt;();
        RequestParameter requestParamterToken = new RequestParameterBuilder()
                .name("ACCESS_TOKEN")
                .required(true)
                .query(q -&amp;gt; q.model(modelSpecificationBuilder -&amp;gt; modelSpecificationBuilder.scalarModel(ScalarType.STRING)))
                .in(ParameterType.HEADER)
                .build();

        listRequestParamters.add(requestParamterToken );
        return new Docket(DocumentationType.SWAGGER_2)
                .produces(produces)
                .consumes(produces)
                .globalRequestParameters(listRequestParamters)
                .additionalModels(typeResolver.resolve(Author.class))
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
                .paths(PathSelectors.any())
                .build();
    }
}

//----------------------------------------------------------------------------------------------------------------------


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

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import ro.stefan.dto.Book;

@RestController
public class BookController {

    @GetMapping("/books")
    public List&amp;lt;Book&amp;gt; getBooks(){
        return new ArrayList&amp;lt;Book&amp;gt;();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dt6pKdPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8t0wv1mcs8y74cxiamyf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dt6pKdPj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8t0wv1mcs8y74cxiamyf.png" alt="Image description" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;so we can see now in the SWAGGER-UI the header attribute ACCESS_TOKEN is mandatory for the endpoint to be called. Thus avoiding to write code in Controller that is just used on an interceptor or filter.&lt;/p&gt;

&lt;p&gt;Example with query parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

import com.fasterxml.classmate.TypeResolver;

import ro.stefan.dto.Author;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.RequestParameterBuilder;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.ParameterType;
import springfox.documentation.service.RequestParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {

    @Autowired
    private TypeResolver typeResolver;

    @Bean
    public Docket getDocketInstanceEx1() {
        final Set&amp;lt;String&amp;gt; produces = new HashSet&amp;lt;String&amp;gt;();
        produces.add(MediaType.APPLICATION_JSON_VALUE);
        produces.add(MediaType.APPLICATION_XML_VALUE);

        List&amp;lt;RequestParameter&amp;gt; listRequestParamters = new ArrayList&amp;lt;RequestParameter&amp;gt;();
        RequestParameter limitParameter = new RequestParameterBuilder()
                .name("limit")
                .required(false)
                .query(q -&amp;gt; q.model(modelSpecificationBuilder -&amp;gt; modelSpecificationBuilder.scalarModel(ScalarType.STRING)))
                .in(ParameterType.QUERY)
                .build();
        RequestParameter pagesParameter = new RequestParameterBuilder()
                .name("pages")
                .required(false)
                .query(q -&amp;gt; q.model(modelSpecificationBuilder -&amp;gt; modelSpecificationBuilder.scalarModel(ScalarType.STRING)))
                .in(ParameterType.QUERY)
                .build();
        listRequestParamters.add(limitParameter);
        listRequestParamters.add(pagesParameter);

        return new Docket(DocumentationType.SWAGGER_2)
                .produces(produces)
                .consumes(produces)
                .globalRequestParameters(listRequestParamters)
                .additionalModels(typeResolver.resolve(Author.class))
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
                .paths(PathSelectors.any())
                .build();
    }   
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So… we can see that the line of code that dictates the types is .in(ParameterType.QUERY)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t3OMLQMt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxcdlm1p7285oxkl3gsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t3OMLQMt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pxcdlm1p7285oxkl3gsn.png" alt="Swagger UI displaying the query parameters wrote in Docket and applied to all controllers of the project" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example with cookie parameter:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vytGqPzz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sm9nh2r4ecdqloe44lj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vytGqPzz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sm9nh2r4ecdqloe44lj8.png" alt="Swagger UI displaying the cookie parameters wrote in Docket and applied to all controllers of the project" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to see the entire code and example just visit my repository on GitHub and written at the bottom of this article.&lt;/p&gt;

&lt;p&gt;Now as you can imagine the possibilities are big.&lt;/p&gt;

&lt;p&gt;Why would you need this ?&lt;/p&gt;

&lt;p&gt;Project’s where you have interceptors or filters and per each request sent by the client and you want to extract an information like a access token (jwt, etc.). It’s clear that you don’t write the token variable into the controller because the controller will never use the variable so instead of having a required variable written in Controller that will never be used there, you can avoid writing it and put it directly into the Docket property if the variable is mandatory for all request of your microservices.&lt;/p&gt;

&lt;h1&gt;
  
  
  Chapter 4 — Global response default
&lt;/h1&gt;

&lt;p&gt;Swagger API’s allow you as developer to override the default response messages of different HTTP requests by telling it (swagger) the to stop using default responses .useDefaultResponseMessages(false) and starting to construct your own cases with the method: .globalResponses()&lt;/p&gt;

&lt;p&gt;NOTE: Remember all of this methods are applied at Docket level.&lt;/p&gt;

&lt;p&gt;So before overring it in swagger UI we will see that in case of 500 and 403 error messages we would get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bBizsnwm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mw8z4ot5kjq2wpcttw2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bBizsnwm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mw8z4ot5kjq2wpcttw2l.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After applying the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseBuilder;
import springfox.documentation.service.Response;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {

    @Bean
    public Docket getDocketInstanceEx1() throws JsonProcessingException {
        List&amp;lt;Response&amp;gt; listResponses = new ArrayList&amp;lt;Response&amp;gt;();

        class ServerError{
            private String serverIp;
            private String serverName;
            private String errorMsg;
            private String errorStack;

            public String getServerIp() {
                return serverIp;
            }
            public void setServerIp(String serverIp) {
                this.serverIp = serverIp;
            }
            public String getServerName() {
                return serverName;
            }
            public void setServerName(String serverName) {
                this.serverName = serverName;
            }
            public String getErrorMsg() {
                return errorMsg;
            }
            public void setErrorMsg(String errorMsg) {
                this.errorMsg = errorMsg;
            }
            public String getErrorStack() {
                return errorStack;
            }
            public void setErrorStack(String errorStack) {
                this.errorStack = errorStack;
            }

        }

        ObjectMapper objMapper = new ObjectMapper();
        listResponses.add(new ResponseBuilder().code("500").description(objMapper.writeValueAsString(new ServerError())).build());
        listResponses.add(new ResponseBuilder().code("403").description("Forbidden!!!!!").build());


        return new Docket(DocumentationType.SWAGGER_2)      
                .useDefaultResponseMessages(false)
                .globalResponses(HttpMethod.GET,listResponses)
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
                .paths(PathSelectors.any())
                .build();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AqobwXcQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utwa1fk99el7l7jrvvff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AqobwXcQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utwa1fk99el7l7jrvvff.png" alt="Image description" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So as you can imagine again this feature brings a ton of value to you as a user that offers API’s and value to a consumer that will bother you less because you documentation just got more precious.&lt;/p&gt;

&lt;p&gt;Why would you need this ?&lt;/p&gt;

&lt;p&gt;Because in an enterprise environment as much as I hate saying we must understand that we aren’t a team of 10 or 20 or 30 people we are a team over 300+ developers on different projects that are part of the same ecosystem so naturally if you let everyone define it’s own style the system wouldn’t be so optimal. So based on what I said this feature is used when the company architect say “All web services should have this standard response in case of failure (server) or non-auth.” thus reducing the complexity of the system and putting down a LAW (yes, I hate this but makes sense if you think about it at cold).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: There are a lot of features that Docket object from swagger offers but please always take in consideration if the feature is old or deprecated and try to find something that is more up to date. Even this article presents things using the SWAGGER_2 version when now the hype is version 3.&lt;/p&gt;

&lt;p&gt;If you want my code you can find it here: &lt;a href="https://github.com/Kanames/SpringBoot-SwaggerExamples"&gt;https://github.com/Kanames/SpringBoot-SwaggerExamples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

&lt;p&gt;Original post: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-docket-advanced-details-6b72b334be21"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-docket-advanced-details-6b72b334be21&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swagger</category>
      <category>springboot</category>
      <category>spring</category>
      <category>openapi</category>
    </item>
    <item>
      <title>Spring Boot | Using SWAGGER at maximum — ApiInfo</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Mon, 03 Jul 2023 17:32:37 +0000</pubDate>
      <link>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-apiinfo-4d33</link>
      <guid>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-apiinfo-4d33</guid>
      <description>&lt;p&gt;The main article that bundles all together and redirect to different features that you can implement in swagger UI is present here: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article I am going to show how to add ApiInfo object in your Docket so that you will have a more professional look on your Swagger UI.&lt;/p&gt;




&lt;p&gt;ApiInfo is the object that allows you as a developer to add Contact information, descriptions of the API, terms of use, and other information that are less important from an implementation point of view but important from an organization point of view.&lt;/p&gt;

&lt;p&gt;The majority of the time teams don’t focus at all on this small details because they bring no value to the API but as mentioned they bring value from the fact that it’s a small detail that can be part of a set of small details that together makes your application more enjoyable and most of all makes you proud of your work. We can consider it in IT “Nice to have…”&lt;/p&gt;

&lt;p&gt;Adding ApiInfo couldn’t have been easier, so I present it by a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {


    @Bean
    public Docket getDocketInstance() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfoExample01())
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfoExample01() {
        return new ApiInfoBuilder()
                .title("API Info - Title section")
                .description("API Info - Description section")
                .version("0.0.1")
                .contact(new Contact("Stefan", "https://medium.com/@stefan.paladuta17", "test@test.com"))
                .build();
    }

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

&lt;/div&gt;



&lt;p&gt;First we will see how the swagger-ui looks without ApiInfo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D7oUTGFW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ug2i0eqwx5a2h0jxwqbz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D7oUTGFW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ug2i0eqwx5a2h0jxwqbz.png" alt="Image description" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we will see how the swagger-ui looks with ApiInfo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vnj200X2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9trdiv0k7ejxs8xj7vhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vnj200X2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9trdiv0k7ejxs8xj7vhj.png" alt="Image description" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we can see that with the ApiInfo based on our example added a lot of new things:&lt;/p&gt;

&lt;p&gt;Point 1: The title is now more personalized for your application, and this believe me it’s important when you manage a dozen of microservices each with their own swagger interface and you want to test them individually.&lt;/p&gt;

&lt;p&gt;Point 2: We have a description section where we can add information that describes the point of this swagger interface or the business logic that this API’s expose.&lt;/p&gt;

&lt;p&gt;Point 3: We expose an URL that can redirect the user to a main page of the developing team that manages this bundle of endpoints.&lt;/p&gt;

&lt;p&gt;Point 4: We expose a way for someone to contact us. And this for me it’s the most important thing in an API world, you should make the effort to make the proper documentation for consumers and if that documentation is not enough then you should leave at least a way for them to contact you for a feedback.&lt;/p&gt;

&lt;p&gt;Let’s get deeper in the details: the method .description() can be very powerful because we can add HTML code. Well actually it’s a bit fake the statement but in reality it’s called: CommonMark syntax (learn it and you can do amazing stuff).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {


  @Bean
  public Docket getDocketInstance() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfoExample02())
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.controller"))
                .paths(PathSelectors.any())
                .build();
  }

  private ApiInfo apiInfoExample02() {
        return new ApiInfoBuilder()
                .title("API Info - Title section")
                .description("API Info - &amp;lt;strong&amp;gt;Description&amp;lt;/strong&amp;gt; section &amp;lt;br&amp;gt; testing something new &amp;lt;br&amp;gt; &amp;lt;table&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;2&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;3&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;/table&amp;gt;")
                .version("0.0.1")
                .contact(new Contact("Stefan", "https://medium.com/@stefan.paladuta17", "test@test.com"))
                .build();
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: the &lt;em&gt;title&lt;/em&gt; and &lt;em&gt;version&lt;/em&gt; properties are required, others are optional. The result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JyqAxUOO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atz89wyshrs7t03kbfz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JyqAxUOO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atz89wyshrs7t03kbfz5.png" alt="Image description" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why should you dedicate precious minutes/hours on this small details&lt;/strong&gt; ? if you don’t see the value, then just take as good practice as the smartbear company implies “[…] it is considered to be a good practice to include general information about your API into the specification: version number, license notes, contact data, links to documentation, and more.”&lt;/p&gt;




&lt;p&gt;Conclusion: ApiInfo is an object that permits you as developer to populate your Swagger-UI with the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The title&lt;/li&gt;
&lt;li&gt;The description&lt;/li&gt;
&lt;li&gt;The version ( + the url)&lt;/li&gt;
&lt;li&gt;The Contact to join the API owner&lt;/li&gt;
&lt;li&gt;The licence ( + the url)&lt;/li&gt;
&lt;li&gt;The API vendor’s extension&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;thus making your API documentation look much professional and easy to read by any consumer and also enforce you or your team to keep an eye on small details (good practice).&lt;/p&gt;

&lt;p&gt;If you want my code you can find it here: &lt;a href="https://github.com/Kanames/SpringBoot-SwaggerExamples"&gt;https://github.com/Kanames/SpringBoot-SwaggerExamples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

</description>
      <category>swagger</category>
      <category>openapi</category>
      <category>springboot</category>
      <category>spring</category>
    </item>
    <item>
      <title>Spring Boot | Using SWAGGER at maximum — Grouping/Definition/Tag</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Sat, 01 Jul 2023 13:33:05 +0000</pubDate>
      <link>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-groupingdefinitiontag-1i69</link>
      <guid>https://forem.com/kanames/spring-boot-using-swagger-at-maximum-groupingdefinitiontag-1i69</guid>
      <description>&lt;p&gt;The main article that bundles all together and redirect to different features that you can implement in swagger UI is present here: &lt;a href="https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0"&gt;https://medium.com/@stefan.paladuta17/spring-boot-using-swagger-at-maximum-9828ae9fb9d0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article I am going to show how grouping/definitions/tags can be achieved in swagger UI.&lt;/p&gt;




&lt;p&gt;Why should you bother to implement grouping in your application ?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Maybe you have an application that exposes a ton of endpoints and that means you may have developers that want to group them logically.&lt;/li&gt;
&lt;li&gt;Maybe you have an application that has a ton of controllers that together, bundles the everything too tight (from an SWAGGER UI point of view) and separation should be applied.&lt;/li&gt;
&lt;li&gt;Maybe you have an application that is presented as a monolith and exposes a ton of web services for different groups/teams. In this case you may want to divide them based for who they are exposed so that the UI generate via swagger won’t be huge and confusing but instead be directly focused on specific group of consumers.&lt;/li&gt;
&lt;li&gt;Categorizing apis.&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  How to do grouping ?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1 — Using GROUPS
&lt;/h2&gt;

&lt;p&gt;We create first the Docket’s. In my case I create 2 docket bean’s that will be for 2 groups (&lt;strong&gt;address&lt;/strong&gt; and &lt;strong&gt;accounting&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package ro.stefan.config;

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

import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {

    @Bean
    public Docket api1() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("address")
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.external.apis.address"))
                .paths(PathSelectors.any())
                .build();
    }


    @Bean
    public Docket api2() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("accounting")
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.external.apis.accounting"))
                .paths(PathSelectors.any())
                .build();
    }


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

&lt;/div&gt;



&lt;p&gt;the layout of the project is the following (also can be seen directly via my github repo. attached at the end of the article):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zKFPUrj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgt2v72pt1xei3dtevjh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zKFPUrj4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgt2v72pt1xei3dtevjh.png" alt="Image description" width="340" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in this layout we have 2 basic controllers ( &lt;em&gt;AccountingController&lt;/em&gt; and &lt;em&gt;AddressController&lt;/em&gt; ) with just methods that return null that are put there just for the POC (Proof Of Concept). And the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ifZMi7tM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwjxzxxen4akx7igcyp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ifZMi7tM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwjxzxxen4akx7igcyp8.png" alt="Image description" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z_jpOhHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz3lbp7rggtnab1iqflh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z_jpOhHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz3lbp7rggtnab1iqflh.png" alt="Image description" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we can see that the generate UI swagger has in the Select definition comboBox our 2 groups.&lt;/p&gt;

&lt;h2&gt;
  
  
  2 — Using TAGS
&lt;/h2&gt;

&lt;p&gt;Using Tags it’s more interesting, here we don’t have anymore definitions (the combo box) but we define a proper grouping of endpoint. First I start with sharing the Docket code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package ro.stefan.config;

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

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Tag;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SpringFoxConfig {


    @Bean
    public Docket api3() {
        // here tags is optional, it just adds a description in the UI
        // by default description is class name, so if you use same tag using 
        // `@Api` on different classes it will pick one of the class name as 
        // description, so better define your own description for them
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .tags(new Tag("security", "security related"), 
                          new Tag("loan", "loan related"))
                .select()
                .apis(RequestHandlerSelectors.basePackage("ro.stefan.external.apis"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Openapi OAS3 with springfox ")
                .description("Code first approach")
                .version("1.0.0")
                .contact(new Contact("Stefan", "https://test.com", "test@test.com"))
                .build();
    }

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

&lt;/div&gt;



&lt;p&gt;the layout of the project is the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CV1uiNXu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xkbamux2av9lje9d83m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CV1uiNXu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xkbamux2av9lje9d83m.png" alt="Image description" width="343" height="515"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
public class AccountingController {

    @GetMapping("/accounts")
    public List&amp;lt;String&amp;gt; getAccounts(){
        return null;
    }
}
/* ----------------------- */
@RestController
public class AddressController {

    @GetMapping("/addresses")
    public List&amp;lt;String&amp;gt; getAddresses(){
        return null;
    }
}
/* ----------------------- */
@RestController
@Api(tags = "loan")
public class LoanController {

    @GetMapping("/loan")
    public String getLoanDetails() {
        return null;
    }
}
/* ----------------------- */
@RestController
@Api(tags = "security")
public class SecurityController {
    @GetMapping("/user")
    public String getUser() {
        return null;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in this layout we have 4 basic controllers with just a method that return null but put there just for the POC (Proof Of Concept) and the result&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vwfHhW5V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yp3d93eydgd16a6h5nxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vwfHhW5V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yp3d93eydgd16a6h5nxj.png" alt="Image description" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interesting, so by putting on 2 controllers the necessary annotation @Tag we just unlocked the power to change also the name of the group and the description.&lt;/p&gt;

&lt;p&gt;We can see that 2 controllers that aren’t annotated with the @Tag are auto-generated their names (accounting-controller and address-controller) and the 2 controllers that we annotated with @Tag are named and descripted as we written in the Docket code.&lt;/p&gt;

&lt;p&gt;You can have operations under multiple tags, but not tags under tags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: The concept of grouping API’s is not something specific to java here I encourage you to follow if you want to see the same principle applied for .NET Core, C#: &lt;a href="http://www.mattruma.com/adventures-in-apis-grouping-controllers-in-swagger/"&gt;http://www.mattruma.com/adventures-in-apis-grouping-controllers-in-swagger/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want my code you can find it here: &lt;a href="https://github.com/Kanames/SpringBoot-SwaggerExamples"&gt;https://github.com/Kanames/SpringBoot-SwaggerExamples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee &lt;a href="https://www.buymeacoffee.com/stefansplace"&gt;https://www.buymeacoffee.com/stefansplace&lt;/a&gt; (;&lt;/p&gt;

&lt;p&gt;References:&lt;br&gt;
&lt;a href="https://medium.com/p/2b25eb39a0cb"&gt;https://medium.com/p/2b25eb39a0cb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>swagger</category>
      <category>openapi</category>
      <category>spring</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Microservices | Why should you think twice before migrating from a giant legacy application to microservices</title>
      <dc:creator>Paladuta Stefan</dc:creator>
      <pubDate>Sat, 24 Jun 2023 13:49:52 +0000</pubDate>
      <link>https://forem.com/kanames/microservices-why-should-you-think-twice-before-migrating-from-a-giant-legacy-application-to-microservices-c3l</link>
      <guid>https://forem.com/kanames/microservices-why-should-you-think-twice-before-migrating-from-a-giant-legacy-application-to-microservices-c3l</guid>
      <description>&lt;p&gt;There are millions of articles that say how great microservices are and how awesome it is to use them from several points of view, but this article is not meant to measure the greatest of the microservices infrastructure but tell you the real cost, that nobody is telling/displaying you about implementing this kind of infrastructure. To do this kind of migration from a legacy monolith to a microservices solution is not easy and actually I dare to use the words “horrible” and “stressful” when done complete wrong.&lt;/p&gt;

&lt;p&gt;There aren’t many success strategies to implement it from a management point of view, but before starting please take in mind the following(s):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This is NOT a tutorial&lt;/li&gt;
&lt;li&gt;This is NOT a measuring article or manifest regarding if microservices are bad or not.&lt;/li&gt;
&lt;li&gt;This is NOT a story told from a Project Manager’s point of view. but it’s a story told from a developers point of view.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This article in exchange will attack the following points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Are you a core system ?&lt;/li&gt;
&lt;li&gt;Is your management aware of the costs ?&lt;/li&gt;
&lt;li&gt;Is your team aware of the costs ?&lt;/li&gt;
&lt;li&gt;Do you have someone in team that handled microservices in the past ?&lt;/li&gt;
&lt;li&gt;Is your infrastructure stable ?&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Background of my work&lt;/p&gt;

&lt;p&gt;In my area of specialization my application is in reality an ecosystem of applications that lives inside a large monolith composed of multiple different type of applications that are also part of their own ecosystem.&lt;/p&gt;

&lt;p&gt;You can think about this infrastructure like a StateMachine infrastructure where you have the core StateMachine that represents the starting point of everything, maybe like the login page (as an example) that redirects you to the internal system that has multiple search inputs , links, etc. And those links open themselves small/large application that are StateMachines.&lt;/p&gt;

&lt;p&gt;To bring a little background my main focus is on Banking applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Point 1: Are you a core system ?
&lt;/h2&gt;

&lt;p&gt;In every large company the system that in most cases is monolithic even today in 2022 (but can also be applied on the rest of types) you have at a high level, two types of modules/system/projects/components how ever you wish to call them&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type: core&lt;/li&gt;
&lt;li&gt;Type: consumer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: “&lt;em&gt;This is just my personal terminology, if I find a more used term I will update the article&lt;/em&gt;”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Core&lt;/em&gt;&lt;/strong&gt; means that your application is focused not around interfaces (UI) for an end user but your business is focused on core concepts that must offer support to other systems to consume (&lt;strong&gt;&lt;em&gt;consumers&lt;/em&gt;&lt;/strong&gt;) your logic.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core system: &lt;em&gt;Payment System&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Consumer: &lt;em&gt;Loan System&lt;/em&gt; paying for installments
If you are a core system in that case your life is much easier because the number of sub-calls you need to do to other sub-system is less to none, thus making your communication in infrastructure less messy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But as a core system you have a lot of pressure to satisfy the following points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: your endpoints need to be as fast as possible you can’t have a reason to be slow, you as a core system that offers to other business need to think about how fast your endpoint is by using whatever strategy can be applied on your project (like caching or event based solutions). The reason if it’s not already clear is that, if consumers are coming to digest (call) your endpoint but that consumer represents a large business unit they can’t stay on your endpoint 1, 2 or 3 seconds, in my case if I see more than 800miliseconds we must have a discussions on what are you doing their.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&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%2Forxuad4rx9t7nonyxhj8.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%2Forxuad4rx9t7nonyxhj8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above simple example we can see that an UI is responsible for creating online a loan for a client. It can have 2 sub call’s to systems that checks the credit line of an client and also creates an account for him if all is fine. But this simple communication with just 2 sub-system can take: 2s + 1.5s a total of 3.5 seconds and that’s without any business logic written on our UI part. So it’s clearly not fine and this should be the first call/sign to everybody, that you can’t migrate a product from a sync. communication environment to microservices and still want to have sync. communication and more speed, THAT’s impossible and breaks the basic rules of what microservices should be.&lt;/p&gt;

&lt;p&gt;NOTE: Normally you shouldn’t have sync communication but normality is too costly and migrations should be as cheap as possible for the management so let’s move on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logic&lt;/strong&gt;: your endpoints should be done in a logical manner like REST Infrastructure where it dictates in simple terms “SMART ENDPOINTS”.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Point 2: Is your management aware of the costs ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwveev1w68y3oahna9ns.jpg" 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%2Fmwveev1w68y3oahna9ns.jpg" alt="Photo by Alexander Krivitskiy on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you think you know the cost of microservices then multiple it by 2 or 3. It may sound crazy but the cost of migrating an application that is already leaving and written in a monolith style is giant. Or even if you start creating new microservices with a new business but you lack the basic infrastructure to do so then I wish you good luck and may you finish the project with your mind still not lost.&lt;/p&gt;

&lt;p&gt;First sub-point is management should understand the basics of microservices, not at technical level but at the level where a common ground can be found to explain the smallest and simplest elements of this infrastructure. Some elements that are a must for a management to know for this infrastructure, are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API&lt;/li&gt;
&lt;li&gt;REST&lt;/li&gt;
&lt;li&gt;ENDPOINT&lt;/li&gt;
&lt;li&gt;MONOLITH&lt;/li&gt;
&lt;li&gt;SERVICES&lt;/li&gt;
&lt;li&gt;CONTAINER&lt;/li&gt;
&lt;li&gt;AUTHORIZATION&lt;/li&gt;
&lt;li&gt;AUTHENTICATION&lt;/li&gt;
&lt;li&gt;TRANSACTIONALITY&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Second sub-point is management should know that to go to a microservice approach you should need a team structure that represent(s) correctly what you are trying to accomplish. For anyone that is new to infrastructure there is a law called “Conway’s Law” and states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So that means that if your team is designed similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fext1tm8fijwth27fucqs.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%2Fext1tm8fijwth27fucqs.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;then that means that you are the type of organization that in general when you want to interact with DB people you raise tickets (Jira if you have Atlassian products) or mails to a group dedicated to DBA management thus making your software to look like in the above, a giant cake of layers.&lt;/p&gt;

&lt;p&gt;In microservices this kind of structure is not going to get you far if you insist with this. But in ex-change it offers you the following clean solution:&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%2Fat2jqchvxq0iwc8yk64z.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%2Fat2jqchvxq0iwc8yk64z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example in this image we see 3 team’s with a set of products or a product and this teams contains people focused on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QA&lt;/li&gt;
&lt;li&gt;UI&lt;/li&gt;
&lt;li&gt;DBA&lt;/li&gt;
&lt;li&gt;OPS&lt;/li&gt;
&lt;li&gt;DEV&lt;/li&gt;
&lt;li&gt;and more if the case needs to have..&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This kind of organization actually boosts the people moral moreover, by giving the sense that they can climb some kind of hierarchy or job thus giving them something to be interested in giving a goal giving them something to focus them inside your company. At the end of the day isn’t it good for you as company to keep the people ?&lt;/p&gt;

&lt;p&gt;Third sub-point is management should encourage the creation as many POC’s (Proof of concept) as possible so that nothing is lost in communication and everything that is proposed, is represented as small demo/POC to display what the goal must be in the end or at least a part of it.&lt;/p&gt;

&lt;p&gt;Not doing POC’s will not give you a gasp on what really will result after the developing is finished, also a POC should show you if the system that we will have in the end is exactly like you thought about:&lt;/p&gt;

&lt;p&gt;A POC or the DEMO should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show the FrontEnd that must be achieved&lt;/li&gt;
&lt;li&gt;Should demonstrate via a large number if diagrams of all kind how the BackEnd is divided with reasoning + how the communication is done.&lt;/li&gt;
&lt;li&gt;Present the con’s and pro’s&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short words Companies/Entities should invest money to get money, this in IT is called simply ARCHITECT DOCUMENT and will present everything that Management, QA team, Dev team, etc. will read understand and agree if it’s suitable for all.&lt;/p&gt;

&lt;p&gt;Most people refuse to understand that if you start a project you must NOT fail it, but don’t gasp that as humans we make mistakes and making decisions without doing research will just make you lose money, time, and make your workers day a living hell. if after 3 month’s of generating the documents, schemes, diagrams , a POC you release that this can’t be maintain on this budget for this client, then it’s natural in my opinion to stop it and you learned something from this (YOU ALWAYS LEARN SOMETHING FROM FAILING).&lt;/p&gt;




&lt;h2&gt;
  
  
  Point 3: Is your team aware of the costs ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dd5f4po5ywadw82lqtd.jpg" 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%2F9dd5f4po5ywadw82lqtd.jpg" alt="Photo by Jason Goodman on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;sually (in my case) but also talking with other friends in other companies a migration is not done by the team that does the daily maintenance of the project but done by another team that was the role of coming doing the product in version 2.0 and then leave (what I like to call ninja’s).&lt;/p&gt;

&lt;p&gt;At end when they leave the new product is given to the team that is doing the daily maintenance and continues to work on it like nothing happened.&lt;/p&gt;

&lt;p&gt;Personal note: this kind of thing is brining value to the final actors and product, the actual team should be aware of what’s happening on the infrastructure and how to product will look because they know it better, to hire people with the purpose of rewriting but to know understand the business of the application is just stupid and the problem is on both side:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;management&lt;/strong&gt;: Not understanding that the start of this kind of project is not something that can be done overnight and key things should be first done, before accepting the migration and starting it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Manual that describes the product&lt;/li&gt;
&lt;li&gt;Sequence diagrams of simple teste cases and edge test cases.&lt;/li&gt;
&lt;li&gt;Understanding the number of interactions of the current system with other systems&lt;/li&gt;
&lt;li&gt;Understanding the business from a high level&lt;/li&gt;
&lt;li&gt;Understanding the platform from were you are leaving and the consequences of not being their&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;external team&lt;/strong&gt;: Not all persons that have this position of going from project to project have the passion to understand the business and generate a beautiful product with a wonderful codebase and excellent guidelines as much as we wish (not most, because in my cases I had an excellent collaboration with me external team) but in general people are focused on bringing as much business as possible and don’t care about the quality of the software as result.&lt;/p&gt;

&lt;p&gt;Going back to the cost for the team that is doing the management, let’s see what the team should know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the desired result of the migration ?&lt;/li&gt;
&lt;li&gt;Does the new version of the product handles all scenarios ?&lt;/li&gt;
&lt;li&gt;What is the new tech. stack that the team must know ?&lt;/li&gt;
&lt;li&gt;What is the new infrastructure that the team must understand ?&lt;/li&gt;
&lt;li&gt;What are the protocols for: production error, handling manual interventions, time to market.&lt;/li&gt;
&lt;li&gt;How difficult is the debugging of the application ?&lt;/li&gt;
&lt;li&gt;How difficult is to introduce new features ?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Point 4: Do you have someone in team that handled microservices in the past ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddaplmh4rmjmj594b3gd.jpg" 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%2Fddaplmh4rmjmj594b3gd.jpg" alt="Photo by Mr. Bochelly on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my opinion it’s critical for someone in the team to have handled in their past microservices infrastructure, especially when you aren’t starting a system from zero but your migrating from one big important monolith to microservices infrastructure.&lt;/p&gt;

&lt;p&gt;Having someone in the team that handled in past this relative “new” infrastructure will save you :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time in experiments&lt;/li&gt;
&lt;li&gt;Bringing more cons or pros in decision making&lt;/li&gt;
&lt;li&gt;Show what streets work on long/short run&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Point 5: Is your infrastructure stable ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn8vkwya11vieyeiadc5.jpg" 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%2Fzn8vkwya11vieyeiadc5.jpg" alt="Photo by Mick Haupt on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are the kind of project that goes on an infrastructure that was already tested by another product then please ignore/skip this section.&lt;/p&gt;

&lt;p&gt;But if you are the kind of project that is the first project that goes in this microservices world in your organization that means that you will also be the first one to test the infrastructure and before starting you should understand the following things as developer and then as a product manager:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You will be the tester of the infrastructure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As developer and product manager of course it’s going to be hard to understand this but this kind of infrastructure is very shaky when it’s so young in the company, things will shake and they shake hard until everybody learn’s to manage it.&lt;/p&gt;

&lt;p&gt;In my personal view until the team responsible for servers were able to learn all, I had some rough times deploying, different stuff was failing ingress was failing, pods weren’t created, deployment weren’t updated and so on.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You must understand the infrastructure needs to be monitored&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tools that never existed in your organization may be without question inserted to help in debugging problems and monitoring distributed systems.&lt;/p&gt;




&lt;p&gt;Thank you all for the time I can imagine this article may not be what you needed but I hope that it presented to you some points that you should take in consideration when trying to move from monolith’s to microservice’s just for the fun of having this buzzword in your company.&lt;/p&gt;

&lt;p&gt;Please leave a comment and like if you appreciate it, if not please offer constructive criticisms in comments.&lt;/p&gt;

&lt;p&gt;Originally posted on: &lt;a href="https://medium.com/@stefan.paladuta17/microservices-why-should-you-think-twice-before-migrating-from-a-giant-legacy-application-to-d020075dd8b" rel="noopener noreferrer"&gt;https://medium.com/@stefan.paladuta17/microservices-why-should-you-think-twice-before-migrating-from-a-giant-legacy-application-to-d020075dd8b&lt;/a&gt;&lt;/p&gt;

</description>
      <category>monolith</category>
      <category>microservices</category>
      <category>legacy</category>
      <category>services</category>
    </item>
  </channel>
</rss>
