About sealed classes and interfaces

Starting Java 17 we can now allow additional class modifiers like sealed, non-sealed etc. A sealed class or interface can be extended or implemented only by those classes and interfaces permitted to do so. Following are the keywords related to sealed classes.
New Keywords
    Earlier we had only two options, allow subclasses to inherit the parent class or interface or not at all. In the later case using Final class modifier. Using sealed we can take a more controlled middle path where the Parent Class or Interface can dictate the Sub classes which can inherit from the Class.

    Defining sealed class (Two Styles)

    Style One: Using permit keyword

    using the class modifiers sealed and permits we can create sealed classes. In the example bellow we are Defining abstract sealed class Tesla which permits three known subclasses Model3, ModelS and TeslaSUV.
    Tesla
    package java17.sealed;
    
    public abstract sealed class Tesla permits Model3, ModelS, TeslaSUV{
    	public abstract Integer maxRange();
    	public String basePrice() {
    		return "25000 USD";
    	}
    }
    
    //Subclass 1
    public final class Model3 extends Tesla {
    	@Override
    	public Integer maxRange() {
    		return 200;
    	}
    }
    
    //Subclass 2
    public final class ModelS extends Tesla {
    	@Override
    	public Integer maxRange() {
    		return 400;
    	}
    }
    
    //Subclass3 (non-sealed)
    public non-sealed class TeslaSUV extends Tesla {
    	@Override
    	public Integer maxRange() {
    		// TODO Auto-generated method stub
    		return null;
    	}
    }
    
    

    Style Two: Using member classes

    In the following example we are creating a sealed class BMWCars and three member classes.
    BMWCars
    package java17.sealed;
    
    public sealed class BMWCars {
    
    	public final class BMW3 extends BMWCars implements ElectricVehicle{
    
    	}
    	
    	public final class BMWI extends BMWCars implements Vehicle {
    
    	}
    	
    	public non-sealed class BMWJV extends BMWCars implements Vehicle {
    
    	}
    
    }
    

    Rules for Defining Sealed Classes or Interfaces

    Both Class and Interface can be marked with sealed. Inherited child classes can be marked with either final, sealed and non-sealed. Every permitted subclass must directly extend the sealed class. A permitted subclass may be non-sealed so that it is open for extension by unknown subclasses.

    Summary

    With introduction of sealed classes we can define the known subclasses of an abstract class. In other words now we can enforce extension of classes that is known in compile time. It allows us to have greater control of class proliferation and improve security.

    This article shows how to install Maven (3.6.3) on macOS Monterey(version 12.2.1) with M1 processor.

    Download Maven

    First we need to download the Maven, for that please visit the following official maven download https://maven.apache.org/download.cgi


    Install Maven

    Go to the download location
    Normally /Users/${username}/Downloads and execute the following command

    Terminal
    tar -xvzf apache-maven-4.0.0-alpha-3-bin.tar.gz
    x apache-maven-4.0.0-alpha-3/bin/mvn.cmd
    x apache-maven-4.0.0-alpha-3/bin/mvn
    x apache-maven-4.0.0-alpha-3/README.txt
    x apache-maven-4.0.0-alpha-3/LICENSE
    x apache-maven-4.0.0-alpha-3/NOTICE
    x apache-maven-4.0.0-alpha-3/lib/
    x apache-maven-4.0.0-alpha-3/lib/aopalliance.license
    x apache-maven-4.0.0-alpha-3/lib/commons-cli.license
    x apache-maven-4.0.0-alpha-3/lib/commons-codec.license
    x apache-maven-4.0.0-alpha-3/lib/commons-lang3.license
    x apache-maven-4.0.0-alpha-3/lib/failureaccess.license
    x apache-maven-4.0.0-alpha-3/lib/guava.license
    x apache-maven-4.0.0-alpha-3/lib/guice.license
    x apache-maven-4.0.0-alpha-3/lib/httpclient.license
    x apache-maven-4.0.0-alpha-3/lib/httpcore.license
    
    It will create a folder apache-maven-4.0.0-alpha-3 which will contain unzipped contains from the downloaded file. Now Move the folder apache-maven-4.0.0-alpha-3 to final destination. In my case i moved to a folder DevRuntime which contains other runtimes for my development.
    ~/.zshenv
    export MAVEN_HOME=~/DevRuntime/apache-maven-4.0.0-alpha-3 export PATH=$PATH:$MAVEN_HOME/bin
    Now source the zshenv file
    Terminal
    source ~/.zshenv

    Install Maven

    Now Check that Maven is working
      
    Terminal
    mvn --verison
    Apache Maven 4.0.0-alpha-3 (2ccf57baa5191468f9911fe85fd99672ac3bacb9)
    Maven home: /Users/SiddB/DevRuntime/apache-maven-4.0.0-alpha-3
    Java version: 18.0.1.1, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-18.0.1.1.jdk/Contents/Home
    Default locale: en_US, platform encoding: UTF-8
    OS name: "mac os x", version: "12.2.1", arch: "aarch64", family: "mac"
    

    How to get Bash version number in Mac OS

    Following command can be used to know the bash version in Mac OS.
    Execute the following command to know the bash version.
    bash --version
    When I execute the above command I get the followings.
    
    GNU bash, version 3.2.57(1)-release (arm64-apple-darwin21)
    Copyright (C) 2007 Free Software Foundation, Inc.
          

    Image showing the command and it's output.



    JUnit 5 Example : Custom Display Name

    In JUnit 5, we can use @DisplayName to declare custom display names for test classes and test methods.
    The custom display name will be visible while debugging or while generating any reports from test execution.

    First Let's see an example of Test Class without using Display Name.

    Example 1 without Display name

    package com.bootng.display;
    
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    
    public class DisplayCustomNameTest {
    
    	@Test
    	public void test_if_it_will_rain() {
    	}
    
    	@Test
    	public void test_if_it_will_be_cloudy() {
    	}
    
    	@Test
    	public void test_if_it_will_be_sunny() {
    	}
    
    }
    
    

    Output




    You can see in the above example, once the Test is executed it shows the exact test method name. Now using DisplayName annotation we will be able to override the display name without changing the test method name.

    Display CustomName Example

    package com.bootng.display;
    @DisplayName("Vacation Weather Test")
    public class DisplayCustNameTest {
    	@DisplayName("🌧")
    	@Test
    	public void test_if_it_will_rain() {
    	}
    
    	@DisplayName("🌨")
    	@Test
    	public void test_if_it_will_be_cloudy() {
    	}
    
    	@DisplayName("🌞")
    	@Test
    	public void test_if_it_will_be_sunny() {
    	}
    }
    
    Output


    We can also use a Custom Name generator to generate the test names. 

    As of Version 5.4 it comes with the following generators out of the box.

    Custom Name Generator Example


    DisplayNameGenerator.IndicativeSentences
    DisplayNameGenerator.ReplaceUnderscores
    DisplayNameGenerator.Simple
    DisplayNameGenerator.Standard

    Each of the above generators have different implementations of how to generate test name.  In this article we will see how to use the ReplaceUnderscores. 

    In the Following example we are using ReplaceUnderscores.  As a result the test names will be generated by replacing the "_" from respective names.
    package com.bootng.display;
    
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    
    @DisplayName("Weather Test DisplayExample ")
    @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
    public class DisplayGeneratorExampleTest {
    
    	@Test
    	public void test_if_it_will_rain() {
    	}
    
    	@Test
    	public void test_if_it_will_be_cloudy() {
    	}
    
    	@Test
    	public void test_if_it_will_be_sunny() {
    	}
    }
    

    Output


    Sublime find special characters

    Often we need to highlight uni code in Sublime editor which is a very popular Editor among developers.

    Using Regular Expression

    A regular expression for finding non-ASCII (code point > 128). The best thing about regular expression is that it will work in any editors that support searching with regular expression.
    [^\x00-\x7F]
    

    Using Plugins

    A Sublime Text 3 plugin to help identify invisible and ambiguous Unicode whitespace characters (zero width spaces, no-break spaces, and similar.)
    Please comment if you know any other alternative options for the same purpose.

    Generating Fibonacci number in java

    This article goes through different implementations of Fibonacci numbers in java.
    Brute Force: Recursive
    The following code is recursive implementation with time complexity O(2**N). That is time complexity is equal to 2 power N.
    public int fib(int n) {
    		if (n == 0)
    			return 0;
    		else if (n == 1)
    			return 1;
    		else
    			return fib(n - 1) + fib(n - 2);
    	}
    Topdown Implementation
    Top-down implementation with time complexity of O(N). Here we cache the value at a specific stage and then see if the stage is already calculated, then return from the cache.
    public static int fib_topdown(int n, int td[]) {
    		if (td[n] != 0 && n != 0)
    			return td[n];
    		else if (n == 0)
    			td[n] = 0;
    		else if (n == 1)
    			td[n] = 1;
    		else
    			td[n] = fib_topdown(n - 1, td) + fib_topdown(n - 2, td);
    		return td[n];
    	}
    	
    Bottom-Up approach
    The code is self-explanatory we use the fundamentals of Fibonacci.
    public static int fib_bottomup(int n) {
    		if (n < 2)
    			return n;
    		int f0 = 0;
    		int f1 = 1;
    		int f2 = 0;
    		for (int i = 2; i <= n; i++) {
    			f2 = f0 + f1;
    			f0 = f1;
    			f1 = f2;
    		}
    
    		return f2;
    }

    References

    How to skip test in Maven

    Maven provides a way to only build the application code and skip executing test cases
    Enter the following command to build the application code but don't execute test cases.
    Skip executing tests
    mvn install -DskipTests
    

    References


    Following article is a very good one explaining the Gaussian Mixture model along with python code.

    https://towardsdatascience.com/gaussian-mixture-models-explained-6986aaf5a95 


     

    Best practices for building containers

    This page lists online resources covering key concepts about how to build containers which are more efficient and secured

    Online Resources for Docker best practices

    Pagination and Sorting using Spring Data JPA

    Documenting API is very important so that users of the API can get a sense of how to call the API and know about different parameters, data types supported, etc. This article deeps dive into exposing REST API that supports Open API Documentation.

    Introduction

    API users need to understand how to interact with the API. OpenAPI Specification (OAS) defines a standard interface to RESTful APIs which allows both humans and computers to discover and understand the capabilities of the API. Swagger implements this interface and in this article, we will walk through changes required to be done to a Spring Boot REST application.

    Spring Boot Rest Application

    We will use an existing spring boot rest application and will add support for the swagger documentation. This application has few Resources already exposed as RESTFul API,  like
    BlogControllerV0,
    BlogControllerV1,
    BlogControllerV2 etc.

    pom.xml changes
    Just include the springdoc-openapi-ui dependency and do mvn install
    pom.xml changes
    <!--  swagger ui -->
    <dependency>
    	<groupId>org.springdoc</groupId>
    	<artifactId>springdoc-openapi-ui</artifactId>
    	<version>1.5.10</version>
    </dependency>

    Accessing the Swagger documentations

    Swagger documentation can be accessed by following URL
    http://localhost:8080/swagger-ui/index.html
    It will show a page like bellow





    If we want to access the JSON data containing the swagger documentation by visiting following URL
    http://localhost:8080/v3/api-docs
    {
       "openapi":"3.0.1",
       "info":{
          "title":"OpenAPI definition",
          "version":"v0"
       },
       "servers":[
          {
             "url":"http://localhost:8080",
             "description":"Generated server url"
          }
       ],
       "paths":{
          "/blogapi/v2/blogs":{
             "get":{
                "tags":[
                   "blog-controller-v-2"
                ],
                "operationId":"getBlogStories",
                "responses":{
                   "200":{
                      "description":"OK",
                      "content":{
                         "application/json":{
                            "schema":{
                               "type":"array",
                               "items":{
                                  "$ref":"#/components/schemas/BlogStory"
                               }
                            }
                         }
                      }
                   }
                }
             },
             "post":{
                "tags":[
                   "blog-controller-v-2"
                ],
                "operationId":"addBlogStory",
                "requestBody":{
                   "content":{
                      "application/json":{
                         "schema":{
                            "$ref":"#/components/schemas/BlogStory"
                         }
                      }
                   },
                   "required":true
                },
                "responses":{
                   "200":{
                      "description":"OK",
                      "content":{
                         "application/json":{
                            "schema":{
                               "$ref":"#/components/schemas/BlogStory"
                            }
                         }
                      }
                   }
                }
             }
          },
          "/blogapi/v1/categories":{
             "get":{
                "tags":[
                   "category-controller"
                ],
                "operationId":"getBlogCats",
                "responses":{
                   "200":{
                      "description":"OK",
                      "content":{
                         "application/json":{
                            "schema":{
                               "type":"array",
                               "items":{
                                  "$ref":"#/components/schemas/BlogCategory"
                               }
                            }
                         }
                      }
                   }
                }
             },
             "post":{
                "tags":[
                   "category-controller"
                ],
                "operationId":"addCats",
                "requestBody":{
                   "content":{
                      "application/json":{
                         "schema":{
                            "$ref":"#/components/schemas/BlogCategory"
                         }
                      }
                   },
                   "required":true
                },
                "responses":{
                   "200":{
                      "description":"OK",
                      "content":{
                         "application/json":{
                            "schema":{
                               "$ref":"#/components/schemas/BlogCategory"
                            }
                         }
                      }
                   }
                }
             }
          },
          "/blogapi/v2/blogs/{id}":{
             "get":{
                "tags":[
                   "blog-controller-v-2"
                ],
                "operationId":"getBlogStory",
                "parameters":[
                   {
                      "name":"id",
                      "in":"path",
                      "required":true,
                      "schema":{
                         "type":"string"
                      }
                   }
                ],
                "responses":{
                   "200":{
                      "description":"OK",
                      "content":{
                         "application/json":{
                            "schema":{
                               "$ref":"#/components/schemas/BlogStory"
                            }
                         }
                      }
                   }
                }
             }
          }
       },
       "components":{
          "schemas":{
             "BlogStory":{
                "type":"object",
                "properties":{
                   "id":{
                      "type":"string"
                   },
                   "name":{
                      "type":"string"
                   },
                   "summary":{
                      "type":"string"
                   },
                   "description":{
                      "type":"string"
                   },
                   "category":{
                      "type":"string"
                   }
                }
             },
             "BlogCategory":{
                "type":"object",
                "properties":{
                   "id":{
                      "type":"string"
                   },
                   "name":{
                      "type":"string"
                   }
                }
             }
          }
       }
    }

    Summary

    In this article, we saw how to quickly add support for Swagger documentation in the Spring boot APP. With very few changes we can get working and interactive swagger API documentation. The Swagger implementation can also be used to customize the report.

    References