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

Restful API using Jersey 3 Jakarta EE 9

This article walks through a sample REST application built using Jersey3 and then we will see how to test the rest endpoints. Last not but least how to deploy it on Server.

Project Structure



Technologies Used
  • Java 15
  • Mvn 3.5.0
  • Jersey 3.0.2
  • JUnit 5.3.1

Java Classes

JakartaRestfulApp.java
Main Jersey Application Class, registers MenuResource class.
public class JakartaRestfulApp extends Application {
	private final Set> classes;

	public JakartaRestfulApp() {
		HashSet> c = new HashSet>();
		c.add(MenuResource.class);
		classes = Collections.unmodifiableSet(c);
	}

	@Override
	public Set> getClasses() {
		return classes;
	}
}
MenuResource.java
Our Resourse class which exposes Restful endpoints for the Menu object. It uses MenuService to store and retrieve Menu items.
@Path("/rest")
public class MenuResource {
	MenuService service = MenuService.getInstance();

	@GET
	@Path("/menus")
	@Produces("application/json")
	public List getMenus() {
		return service.getAll();
	}

	@GET
	@Path("/menus/{menu_ID}")
	@Produces("application/json")
	public Response getMenu(@PathParam("menu_ID") Long menuId) {
		try {
			return Response.ok(service.get(menuId)).build();
		} catch (Exception e) {
			return Response.serverError().status(HttpStatus.BAD_REQUEST_400.getStatusCode(), e.getMessage()).build();
		}
	}

	@POST
	@Path("/menus")
	@Produces("application/json")
	public Response add(Menu c) {
		service.add(c);
		return Response.ok(c).status(HttpStatus.CREATED_201.getStatusCode(), "Created").build();
	}

	@PUT
	@Path("/menus/{menu_ID}")
	@Produces("application/json")
	public Response update(@PathParam("menu_ID") Long menuId, Menu c) {
		try {
			return Response.ok(service.update(menuId,c.getName())).build();
		} catch (Exception e) {
			return Response.serverError().status(HttpStatus.BAD_REQUEST_400.getStatusCode(), e.getMessage()).build();
		}
	}

	@PATCH
	@Path("/menus/{menu_ID}")
	@Produces("application/json")
	public Response update2(@PathParam("menu_ID") Long menuId, @QueryParam("name") String name) {
		try {
			return Response.ok(service.update(menuId,name)).build();
		} catch (Exception e) {
			return Response.serverError().status(HttpStatus.BAD_REQUEST_400.getStatusCode(), e.getMessage()).build();
		}
	}

	@DELETE
	@Path("/menus/{menu_ID}")
	@Produces("application/json")
	public Response delete(@PathParam("menu_ID") Long menuId) {
		try {
			service.delete(menuId);
			return Response.ok().status(HttpStatus.OK_200.getStatusCode()).build();
		} catch (Exception e) {
			return Response.serverError().status(HttpStatus.BAD_REQUEST_400.getStatusCode(), e.getMessage()).build();
		}
	}

	@OPTIONS
	@Path("/menus")
	@Produces("text/plain")
	public String touch() {
		return "options";
	}

	@HEAD
	@Path("/menus")
	@Produces("text/plain")
	public String head() {
		return "head";
	}
}
MenuService.java
This class is used to store and retrieve Menu objects. It uses a HashSet to store objects created.
public class MenuService {

	private static MenuService instance = new MenuService();
	private static HashSet menus;

	private MenuService() {
		menus = new HashSet<>();
		menus.add(new Menu(1L, "Menu One"));
	}

	public static MenuService getInstance() {
		return instance;
	}

	public void add(Menu menu) {
		menus.add(menu);
	}

	public List getAll() {
		return new ArrayList(menus);
	}

	public Menu get(Long id) throws Exception {
		Iterator it = menus.iterator();
		while (it.hasNext()) {
			Menu curr = (Menu) it.next();
			if (curr.getId() == id)
				return curr;
		}
		throw new Exception("Object not found");
	}

	public boolean delete(Long id) throws Exception {
		Iterator it = menus.iterator();
		while (it.hasNext()) {
			Menu curr = (Menu) it.next();
			if (curr.getId() == id) {
				it.remove();
				return true;
			}
		}
		throw new Exception("Object not found");
	}
	
	public Menu update(Long id, String update) throws Exception {
		Iterator it = menus.iterator();
		while (it.hasNext()) {
			Menu curr = (Menu) it.next();
			if (curr.getId() == id) {
				curr.setName(update);
				return curr;
			}
				
		}
		throw new Exception("Object not found");
	}
}
Menu.java
Menu object representing a restaurant menu containing some basic information like id and name.
public class Menu {

	private Long id;

	private String name;

	public Menu() {
	}

	public Menu(Long id, String name) {
		this.id = id;
		this.name = name;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
JDKSEServer.java
Jersey supports a number of deployment options. For this example, we will use a lightweight JDK server that comes with JDK.
public class JDKSEServer {
	private static final Logger LOGGER = Logger.getLogger(JDKSEServer.class.getName());
	/**
	 * Starts the JDK HTTP server serving the JAX-RS application.
	 */
	static HttpServer startServer() throws IOException {
		ResourceConfig config = new ResourceConfig(MenuResource.class);
		HttpServer server = JdkHttpServerFactory.createHttpServer(getBaseURI(), config);
		return server;
	}

	public static void main(String[] args) {
		try {
			final HttpServer httpServer = startServer();
			Runtime.getRuntime().addShutdownHook(new Thread(() -> {
				try {
					LOGGER.info("Shutting down the application...");
					httpServer.stop(0);
				} catch (Exception e) {
					LOGGER.log(Level.SEVERE, null, e);
				}
			}));

			LOGGER.info("Application started.%nStop the application using CTRL+C");
			Thread.currentThread().join();
		} catch (Exception ex) {
			LOGGER.log(Level.SEVERE, null, ex);
		}
	}

	/**
	 * Gets base {@link URI}.
	 */
	public static URI getBaseURI() {
		return UriBuilder.fromUri("http://localhost/").port(8080).build();
	}
}

Unit Testing

TestMenuResource.java
We will use JerseyTest to test some of the methods that MenuResource supports.
public class TestMenuResource extends JerseyTest {

	@BeforeEach
	void init() throws Exception {
		super.setUp();
	}

	@Override
	protected Application configure() {
                 //to start a new container in s different port
		forceSet(TestProperties.CONTAINER_PORT, "0");
		return new ResourceConfig(MenuResource.class);
	}

	@Test
	public void get_one() throws Exception {
		Response response = target("/rest/menus/1").request().get();
		System.out.println("sd " + response.getStatus());
		assertEquals(response.getStatus(), 200);
		assertEquals(response.readEntity(Menu.class).getName(), "Menu One");
	}

	protected TestContainerFactory getTestContainerFactory() {
		return new JdkHttpServerTestContainerFactory();
	}

}

Executing Code

mvn clean compile exec:java
Sep 24, 2021 4:57:57 PM org.glassfish.jersey.server.wadl.WadlFeature configure WARNING: JAX-B API not found . WADL feature is disabled. Sep 24, 2021 4:57:57 PM jersey.server.JDKSEServer main INFO: Application started.%nStop the application using CTRL+C

References

Summary
In this article, we saw how to build and test Jakarta Restful API with Jersey 3.

Introduction

In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. REST is an architectural style for building distributed systems based on hypermedia. REST is independent of any underlying protocol and is not necessarily tied to HTTP.

What is REST

REST stands for representational state transfer. It is a set of constraints that set out how an API (application programming interface) should work.

REST API Design Principles

  • Uniform Interface: REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client. A resource has an identifier, which is a URI that uniquely identifies that resource.
    Use Noun and not verb to represent a resource
    In general, it helps to use plural nouns

  • Client-Server: Client and Server are independent of each others and the only way the client interacts is through the URI of the resources.
    Client and server can evolve independently.
    Client and server can be implemented in different tech stack.

  • Stateless : REST APIs use a stateless request model. HTTP requests should be independent and may occur in any order. The only place where information is stored is in the resources themselves, and each request should be an atomic operation.
    Being stateless means REST API can scale easily.

  • Cacheable: response to a request be implicitly or explicitly labeled as cacheable or non-cacheable.

  • Layered System: Client and Server should not be tightly coupled and if required and added any intermediate layer the API still should work.

Navigating Treemap in Java

Treemap in java is A Red-Black tree-based NavigableMap implementation. NavigableMap interface provides some interesting methods to navigate the map. In this article, we will quickly go through those methods.

NavigableMap

NavigableMap provides a method to navigate the map in interesting ways. For instance, rather than getting value stored for a key, we can retrieve the value stored against the smallest key or get the next immediate bigger key for the given key. Following are some of the interesting methods that we will look into. We can see actually these methods are helping us to access the TreeMap on both ends like (get the lowest key, get the highest key), etc.
Important method
  • lowerkey (key): Returns the greatest key strictly less than the given key, or null if there is no such key
  • lowerEntry (key): Follows the above and returns the key-value mapping for the key.
  • floorKey (key): Returns the greatest key less than the given key or equal to the given key, or null if there is no such key
  • floorEntry (key): Follows the above and returns the key-value mapping for the key.
  • higherKey (key): Returns the lowest key strictly greater than the given key, or null if there is no such key
  • higherEntry (key): Follows the above and returns the key-value mapping for the key.
  • ceilingKey (key): Returns the least key greater than or equal to the given key, or null if there is no such key
  • ceilingEntry (key): Follows the above and returns the key-value mapping for the key.
  • firstEntry (): Returns a key-value mapping associated with the least key in this map
  • lastEntry (): Returns a key-value mapping associated with the highest key in this map
  • pollFirstEntry (): Remove and returns a key-value mapping associated with the least key in this map
  • pollLastEntry (): Remove and returns a key-value mapping associated with the highest key in this map

Java Code to see above methods

Create and Populate Map
TreeMap<Integer, String> map = new TreeMap<> ();
map.put(15, "banana");
map.put(16, "apple");
lowerKey and lowerEntry Example
Here when we try with lowerKey(16) it looks for available keys and returns the greatest key lower then 16, in this case it is 15.
key = map.lowerKey(16);
test = map.lowerEntry(16);
System.out.println(key);  //15
System.out.println(test); //banana
floorKey and floorKeyEntry Example
Here when we try with floorKey(16) it looks for available keys and returns the greatest key lower than (or equal to 16), in this case, it is 16.
key = map.floorKey(16);
test = map.floorEntry(16);
System.out.println(key);  //16
System.out.println(test); //apple
		
higherKey and higherEntry
higher key will return the least key strictly greater than the given key and following the same logic higherEntry will return the key-value pair. Note that in this case, 14 key does not exist in the map
key = map.higherKey(14);
test = map.higherEntry(14);
System.out.println(key);  //15
System.out.println(test); //banana
ceilingKey and ceilingEntry
ceilingKey logic is very similar to higherkey, except the fact that it checks for the least key equal to or greater the given key.
key = map.ceilingKey(16);
test = map.ceilingEntry(16);
System.out.println(key); 			  //16
System.out.println(test.getValue()); //apple

Important Points
  • Treemap is Red-Black tree-based implementation.
  • Treemap provides guaranteed log(n) time cost for containsKey(), get(), put(), and remove() .

References