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

Pagination and Sorting using Spring Data JPA

This article deeps dive into exposing REST API that supports pagination using Spring DATA JPA.

Introduction

Pagination is a way to get a subset(page) of data on a fixed page and be able to retrieve the pages randomly or sequentially. Most important parameters are,

Total number of records
Number of records on a page (page size)
Current Page number (page order number) Based on the above informations we can build the algorithm to fetch the respective data. In the SQL world given the current page and page size, we can retrieve the information using limit and offset like follows, Select * from [TABLE NAME] limit pageSize, offset pageNumber*pageSize Spring Data encapsulates all these algorithms/queries and handles all edge cases to return us paginated data.
In the next section we will walk through a sample REST API Controller which uses Spring Data JPA to return paginated response.

Implementations

Dish.java
Model class representing Dish object which holds information of about dishes.
@Entity
@Table (name = "dish_table")
public class Dish {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name = "id")
	private Long id;
	
	@NotNull
	@Size(min=2, message="Name should have atleast 5 characters")
	@Column(name = "name")
	private String name;
	
	@Column(name = "description")
	private String description;
	
	@Column(name = "lowprice")
	private Double lowPrice;
	
	@Column(name = "highprice")
	private Double highPrice;
	
	public Dish () {}
	//Getter and Setters
}
DishRepository
Dish Repository extends JpaRepository which extends interface PagingAndSortingRepository that provides methods like Page findAll(Pageable pageable);. On top of that, we have specified our own method which returns a paginated response and takes a name as the first parameter and Pageable as the second parameter.
@Repository
public interface DishRepository extends JpaRepository {
	public Page findByName(String name, Pageable pageable);
}
DishControllerPaginatedV2
Our Rest controller uses repository method findAll(pageRequest). We need to build the pageRequest object and pass it to the repository method. We are getting the pageNo as request parameter.
@RestController
@RequestMapping("api/v2")
public class DishControllerPaginatedV2 {

	private static final int  pageSize = 2;

	@Autowired
	DishRepository repo;
	
	@GetMapping(value="/dishes",produces = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity> getDish3(@RequestParam (defaultValue = "0") int pageNo) throws Exception {
		Sort sort = Sort.by("name");
		Pageable pageReq =  PageRequest.of(pageNo, pageSize, sort);
		Page result =  repo.findAll(pageReq);
		return ResponseEntity.ok(result);
	}
}
Invoke REST API
invoking the API with the following curl will provide us paginated response as shown in the next block.
curl --request GET \
  --url 'http://localhost:8080/api/v1/dishes3?pageNo=0' \
  --header 'cache-control: no-cache'
REST API RESPONSE
{
    "content": [
        {
            "id": 12,
            "name": "Anchovies",
            "description": "Anchovies",
            "lowPrice": 1987,
            "highPrice": 0
        },
        {
            "id": 14,
            "name": "Celery",
            "description": "Celery",
            "lowPrice": 2928,
            "highPrice": 0
        }
    ],
    "pageable": {
        "sort": {
            "sorted": true,
            "unsorted": false,
            "empty": false
        },
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 2,
        "paged": true,
        "unpaged": false
    },
    "last": false,
    "totalPages": 7,
    "totalElements": 14,
    "size": 2,
    "number": 0,
    "sort": {
        "sorted": true,
        "unsorted": false,
        "empty": false
    },
    "numberOfElements": 2,
    "first": true,
    "empty": false
}

Summary

In this article, we saw how to quickly build paginated REST API using Spring Data JPA. We need to create the PageRequest object and call the repository method findALL(pageRequest). Spring Data will take care of the offset calculation and will return one page of data along with some important information. Spring Data also supports filtering and sorting along with pagination.

References